]> git.ipfire.org Git - thirdparty/freeswitch.git/commitdiff
add http utils
authorSeven Du <dujinfang@gmail.com>
Thu, 4 Sep 2014 00:43:51 +0000 (08:43 +0800)
committerSeven Du <dujinfang@gmail.com>
Thu, 4 Sep 2014 00:43:51 +0000 (08:43 +0800)
src/include/switch_utils.h
src/switch_utils.c

index 8e019f1fb300f74d8466ba95bc65f1e6781d97fb..2c0bac818332cc911fd10e6c88583cf9af7cc563 100644 (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:
index 3028122c92fe8bdc176b4b2d9859189f1878434a..d5de0a50f5b7c40c8e1ad55b631a088e8b79ad37 100644 (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: