add http utils

This commit is contained in:
Seven Du 2014-09-04 08:43:51 +08:00
parent 7d11e19983
commit f0b9407cca
2 changed files with 182 additions and 0 deletions

View File

@ -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:

View File

@ -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: