add http utils
This commit is contained in:
parent
7d11e19983
commit
f0b9407cca
|
@ -1102,6 +1102,39 @@ SWITCH_DECLARE(char *) switch_strerror_r(int errnum, char *buf, switch_size_t bu
|
|||
SWITCH_DECLARE(int) switch_wait_sock(switch_os_socket_t sock, uint32_t ms, switch_poll_t flags);
|
||||
SWITCH_DECLARE(int) switch_wait_socklist(switch_waitlist_t *waitlist, uint32_t len, uint32_t ms);
|
||||
|
||||
typedef struct switch_http_request_s {
|
||||
const char *method; /* GET POST PUT DELETE OPTIONS PATCH HEAD */
|
||||
const char *uri;
|
||||
const char *qs; /* query string*/
|
||||
const char *host;
|
||||
switch_port_t port;
|
||||
const char *from;
|
||||
const char *user_agent;
|
||||
const char *referer;
|
||||
const char *user;
|
||||
switch_bool_t keepalive;
|
||||
switch_event_t *headers;
|
||||
void *user_data; /* private user data */
|
||||
|
||||
/* private members used by the parser internally */
|
||||
char *_buffer;
|
||||
const char *_unparsed_data;
|
||||
switch_size_t _unparsed_len;
|
||||
switch_bool_t _destroy_headers;
|
||||
} switch_http_request_t;
|
||||
|
||||
/**
|
||||
* parse http headers in a buffer
|
||||
* return status of success or not
|
||||
* \param[in] buffer the buffer start from the very begining of the http request, e.g. 'GET '
|
||||
* \param[in] datalen the buffer length
|
||||
* \param[out] the http request pointer or null, need destroy later if got non-NULL pointer
|
||||
* \return SWITCH_STATUS_SUCCESS | SWITCH_STATUS_FALSE
|
||||
*/
|
||||
SWITCH_DECLARE(switch_status_t) switch_http_parse_header(char *buffer, uint32_t datalen, switch_http_request_t *request);
|
||||
SWITCH_DECLARE(void) switch_http_free_request(switch_http_request_t *request);
|
||||
SWITCH_DECLARE(void) switch_http_dump_request(switch_http_request_t *request);
|
||||
|
||||
SWITCH_END_EXTERN_C
|
||||
#endif
|
||||
/* For Emacs:
|
||||
|
|
|
@ -3603,6 +3603,155 @@ SWITCH_DECLARE(char *) switch_strerror_r(int errnum, char *buf, switch_size_t bu
|
|||
#endif
|
||||
}
|
||||
|
||||
SWITCH_DECLARE(switch_status_t) switch_http_parse_header(char *buffer, uint32_t datalen, switch_http_request_t *request)
|
||||
{
|
||||
switch_status_t status = SWITCH_STATUS_FALSE;
|
||||
char *p = buffer;
|
||||
int i = 10;
|
||||
char *http = NULL;
|
||||
int header_count;
|
||||
char *headers[64] = { 0 };
|
||||
int argc;
|
||||
char *argv[2] = { 0 };
|
||||
char *body = NULL;
|
||||
int header_len = 0;
|
||||
|
||||
if (datalen < 16) return status; /* minimum GET / HTTP/1.1\r\n */
|
||||
|
||||
while(i--) { // sanity check
|
||||
if (*p++ == ' ') break;
|
||||
}
|
||||
|
||||
if (i == 0) return status;
|
||||
|
||||
if ((body = strstr(p, "\r\n\r\n"))) {
|
||||
*body = '\0';
|
||||
header_len = body - buffer + 1;
|
||||
body += 4;
|
||||
} else if (( body = strstr(p, "\n\n"))) {
|
||||
*body = '\0';
|
||||
header_len = body - buffer + 1;
|
||||
body += 2;
|
||||
}
|
||||
|
||||
request->_buffer = strdup(buffer);
|
||||
request->method = request->_buffer;
|
||||
if (body && *body) {
|
||||
request->_unparsed_data = body;
|
||||
request->_unparsed_len = datalen - (body - buffer);
|
||||
switch_assert(request->_unparsed_len > 0);
|
||||
}
|
||||
|
||||
p = strchr(request->method, ' ');
|
||||
*p++ = '\0';
|
||||
|
||||
request->uri = p;
|
||||
p = strchr(request->uri, ' ');
|
||||
|
||||
if (!p) goto err;
|
||||
*p++ = '\0';
|
||||
|
||||
http = p;
|
||||
p = strchr(http, '\n');
|
||||
|
||||
if (!p) goto err;
|
||||
|
||||
if (!strncmp(http, "HTTP/1.1", 8)) {
|
||||
request->keepalive = SWITCH_TRUE;
|
||||
} else if (strncmp(http, "HTTP/1.0", 8)) {
|
||||
goto err;
|
||||
}
|
||||
|
||||
p++; // now the first header
|
||||
|
||||
if (!request->headers) {
|
||||
if (switch_event_create(&request->headers, SWITCH_EVENT_CHANNEL_DATA) != SWITCH_STATUS_SUCCESS) {
|
||||
goto err;
|
||||
}
|
||||
request->_destroy_headers = SWITCH_TRUE;
|
||||
}
|
||||
|
||||
header_count = switch_separate_string(p, '\n', headers, sizeof(headers)/ sizeof(headers[0]));
|
||||
|
||||
if (header_count < 2) goto err; /* at least two lines */
|
||||
|
||||
for (i = 0; i < header_count; i++) {
|
||||
char *header, *value;
|
||||
int len;
|
||||
|
||||
argc = switch_separate_string(headers[i], ':', argv, 2);
|
||||
|
||||
if (argc != 2) goto err;
|
||||
|
||||
header = argv[0];
|
||||
value = argv[1];
|
||||
|
||||
if (*value == ' ') value++;
|
||||
|
||||
len = strlen(value);
|
||||
|
||||
if (len && *(value + len - 1) == '\r') *(value + len - 1) = '\0';
|
||||
|
||||
switch_event_add_header_string(request->headers, SWITCH_STACK_BOTTOM, header, value);
|
||||
|
||||
if (!strncasecmp(header, "User-Agent", 10)) {
|
||||
request->user_agent = value;
|
||||
} else if (!strncasecmp(header, "Host", 4)) {
|
||||
request->host = value;
|
||||
p = strchr(value, ':');
|
||||
|
||||
if (p) {
|
||||
*p++ = '\0';
|
||||
|
||||
if (*p) request->port = atoi(p);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return SWITCH_STATUS_SUCCESS;
|
||||
|
||||
err:
|
||||
switch_http_free_request(request);
|
||||
return status;
|
||||
}
|
||||
|
||||
SWITCH_DECLARE(void) switch_http_free_request(switch_http_request_t *request)
|
||||
{
|
||||
if (request->_buffer) free(request->_buffer);
|
||||
if (request->_destroy_headers && request->headers) {
|
||||
switch_event_destroy(&request->headers);
|
||||
}
|
||||
}
|
||||
|
||||
/* for debugging only */
|
||||
SWITCH_DECLARE(void) switch_http_dump_request(switch_http_request_t *request)
|
||||
{
|
||||
switch_assert(request->method);
|
||||
|
||||
printf("method: %s\n", request->method);
|
||||
|
||||
if (request->uri) printf("uri: %s\n", request->uri);
|
||||
if (request->qs) printf("qs: %s\n", request->qs);
|
||||
if (request->host) printf("host: %s\n", request->host);
|
||||
if (request->port) printf("port: %d\n", request->port);
|
||||
if (request->from) printf("from: %s\n", request->from);
|
||||
if (request->user_agent) printf("user_agent: %s\n", request->user_agent);
|
||||
if (request->referer) printf("referer: %s\n", request->referer);
|
||||
if (request->user) printf("user: %s\n", request->user);
|
||||
if (request->keepalive) printf("uri: %d\n", request->keepalive);
|
||||
if (request->_unparsed_data) printf("body: %p\n", request->_unparsed_data);
|
||||
|
||||
{
|
||||
switch_event_header_t *header = request->headers->headers;
|
||||
|
||||
printf("headers:\n-------------------------\n");
|
||||
|
||||
while(header) {
|
||||
printf("%s: %s\n", header->name, header->value);
|
||||
header = header->next;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* For Emacs:
|
||||
* Local Variables:
|
||||
|
|
Loading…
Reference in New Issue