refactor(http): improve http parse method
This commit is contained in:
@@ -1,5 +1,6 @@
|
|||||||
#include "http/request.h"
|
#include "http/request.h"
|
||||||
|
|
||||||
|
#include <myclib/mystring.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
@@ -33,109 +34,73 @@ static cws_http_method_e http_parse_method(const char *method) {
|
|||||||
return HTTP_UNKNOWN;
|
return HTTP_UNKNOWN;
|
||||||
}
|
}
|
||||||
|
|
||||||
cws_http_s *cws_http_parse(string_s *request_str) {
|
static bool parse_method(cws_http_s *req, char **cursor) {
|
||||||
if (!request_str || !request_str->data) {
|
char *s = *cursor + strspn(*cursor, " ");
|
||||||
return NULL;
|
size_t len = strcspn(s, " ");
|
||||||
|
if (len == 0 || s[len] == '\0') {
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
cws_http_s *request = http_new();
|
s[len] = '\0';
|
||||||
if (request == NULL) {
|
CWS_LOG_DEBUG("method: %s", s);
|
||||||
return NULL;
|
req->method = http_parse_method(s);
|
||||||
|
*cursor = s + len + 1;
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
char *str = strdup(request_str->data);
|
static bool parse_location(cws_http_s *req, char **cursor) {
|
||||||
if (!str) {
|
char *s = *cursor + strspn(*cursor, " ");
|
||||||
cws_http_free(request);
|
size_t len = strcspn(s, " ");
|
||||||
return NULL;
|
if (len == 0 || s[len] == '\0') {
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
char *str_free = str;
|
|
||||||
|
|
||||||
/* Parse HTTP method */
|
s[len] = '\0';
|
||||||
str += strspn(str, " ");
|
CWS_LOG_DEBUG("location: %s", s);
|
||||||
if (*str == '\0') {
|
string_append(req->location, s);
|
||||||
free(str_free);
|
*cursor = s + len + 1;
|
||||||
cws_http_free(request);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
size_t len = strcspn(str, " ");
|
|
||||||
if (str[len] == '\0') {
|
|
||||||
free(str_free);
|
|
||||||
cws_http_free(request);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
str[len] = '\0';
|
|
||||||
CWS_LOG_DEBUG("method: %s", str);
|
|
||||||
request->method = http_parse_method(str);
|
|
||||||
str += len + 1;
|
|
||||||
|
|
||||||
/* Parse location */
|
return true;
|
||||||
str += strspn(str, " ");
|
|
||||||
if (*str == '\0') {
|
|
||||||
free(str_free);
|
|
||||||
cws_http_free(request);
|
|
||||||
return NULL;
|
|
||||||
}
|
}
|
||||||
len = strcspn(str, " ");
|
|
||||||
if (str[len] == '\0') {
|
|
||||||
free(str_free);
|
|
||||||
cws_http_free(request);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
str[len] = '\0';
|
|
||||||
string_append(request->location, str);
|
|
||||||
str += len + 1;
|
|
||||||
|
|
||||||
/* Adjust location path */
|
static bool parse_version(cws_http_s *req, char **cursor) {
|
||||||
/* @TODO: fix path traversal */
|
char *s = *cursor + strspn(*cursor, " \t");
|
||||||
string_append(request->location_path, "www");
|
size_t len = strcspn(s, "\r\n");
|
||||||
if (strcmp(request->location->data, "/") == 0) {
|
if (len == 0 || s[len] == '\0') {
|
||||||
string_append(request->location_path, "/index.html");
|
return false;
|
||||||
} else {
|
|
||||||
string_append(request->location_path, request->location->data);
|
|
||||||
}
|
}
|
||||||
CWS_LOG_DEBUG("location path: %s", request->location_path->data);
|
|
||||||
|
|
||||||
/* Parse HTTP version */
|
s[len] = '\0';
|
||||||
str += strspn(str, " \t");
|
CWS_LOG_DEBUG("version: %s", s);
|
||||||
if (*str == '\0') {
|
string_append(req->http_version, s);
|
||||||
free(str_free);
|
*cursor = s + len + 1;
|
||||||
cws_http_free(request);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
len = strcspn(str, "\r\n");
|
|
||||||
if (len == 0) {
|
|
||||||
free(str_free);
|
|
||||||
cws_http_free(request);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
str[len] = '\0';
|
|
||||||
CWS_LOG_DEBUG("version: %s", str);
|
|
||||||
string_append(request->http_version, str);
|
|
||||||
str += len;
|
|
||||||
|
|
||||||
/* Parse headers until a blank line (\r\n\r\n) */
|
return true;
|
||||||
request->headers =
|
}
|
||||||
|
|
||||||
|
static bool parse_headers(cws_http_s *req, char **cursor) {
|
||||||
|
req->headers =
|
||||||
hm_new(my_str_hash_fn, my_str_equal_fn, my_str_free_fn, my_str_free_fn,
|
hm_new(my_str_hash_fn, my_str_equal_fn, my_str_free_fn, my_str_free_fn,
|
||||||
sizeof(char) * CWS_HTTP_HEADER_MAX, sizeof(char) * CWS_HTTP_HEADER_CONTENT_MAX);
|
sizeof(char) * CWS_HTTP_HEADER_MAX, sizeof(char) * CWS_HTTP_HEADER_CONTENT_MAX);
|
||||||
|
|
||||||
str += strspn(str, "\r\n");
|
char *s = *cursor + strspn(*cursor, "\r\n");
|
||||||
|
while (*s != '\0' && *s != '\r') {
|
||||||
while (*str != '\0' && *str != '\r') {
|
char *line_end = strstr(s, "\r\n");
|
||||||
char *line_end = strstr(str, "\r\n");
|
|
||||||
if (!line_end) {
|
if (!line_end) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
*line_end = '\0';
|
*line_end = '\0';
|
||||||
|
|
||||||
char *colon = strchr(str, ':');
|
char *colon = strchr(s, ':');
|
||||||
if (!colon) {
|
if (!colon) {
|
||||||
str = line_end + 2;
|
s = line_end + 2;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
*colon = '\0';
|
*colon = '\0';
|
||||||
|
|
||||||
char *header_key = str;
|
char *header_key = s;
|
||||||
char *header_value = colon + 1;
|
char *header_value = colon + 1;
|
||||||
header_value += strspn(header_value, " \t");
|
header_value += strspn(header_value, " \t");
|
||||||
|
|
||||||
@@ -148,16 +113,62 @@ cws_http_s *cws_http_parse(string_s *request_str) {
|
|||||||
strncpy(hv, header_value, sizeof(hv) - 1);
|
strncpy(hv, header_value, sizeof(hv) - 1);
|
||||||
hv[sizeof(hv) - 1] = '\0';
|
hv[sizeof(hv) - 1] = '\0';
|
||||||
|
|
||||||
hm_set(request->headers, hk, hv);
|
// CWS_LOG_DEBUG("%s:%s", hk, hv);
|
||||||
|
hm_set(req->headers, hk, hv);
|
||||||
|
|
||||||
/* Move to the next line */
|
/* Move to the next line */
|
||||||
str = line_end + 2;
|
s = line_end + 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
free(str_free);
|
*cursor = s;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
cws_http_s *cws_http_parse(string_s *request_str) {
|
||||||
|
if (!request_str || !request_str->data) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
cws_http_s *request = http_new();
|
||||||
|
if (!request) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
char *str = strdup(request_str->data);
|
||||||
|
if (!str) {
|
||||||
|
cws_http_free(request);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
char *orig = str;
|
||||||
|
|
||||||
|
/* Parse HTTP method */
|
||||||
|
parse_method(request, &str);
|
||||||
|
|
||||||
|
/* Parse location */
|
||||||
|
parse_location(request, &str);
|
||||||
|
|
||||||
|
/* Adjust location path */
|
||||||
|
/* @TODO: fix path traversal */
|
||||||
|
string_append(request->location_path, "www");
|
||||||
|
if (strcmp(request->location->data, "/") == 0) {
|
||||||
|
string_append(request->location_path, "/index.html");
|
||||||
|
} else {
|
||||||
|
string_append(request->location_path, request->location->data);
|
||||||
|
}
|
||||||
|
CWS_LOG_DEBUG("location path: %s", request->location_path->data);
|
||||||
|
|
||||||
|
/* Parse HTTP version */
|
||||||
|
parse_version(request, &str);
|
||||||
|
|
||||||
|
/* Parse headers */
|
||||||
|
parse_headers(request, &str);
|
||||||
|
|
||||||
/* TODO: Parse body */
|
/* TODO: Parse body */
|
||||||
/* str is at the beginning of the body */
|
/* orig is at the beginning of the body */
|
||||||
|
|
||||||
|
/* Free the original string */
|
||||||
|
free(orig);
|
||||||
|
|
||||||
return request;
|
return request;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -103,7 +103,6 @@ static void http_send_resource(cws_http_s *request) {
|
|||||||
/* Retrieve correct Content-Type */
|
/* Retrieve correct Content-Type */
|
||||||
char content_type[CWS_HTTP_CONTENT_TYPE];
|
char content_type[CWS_HTTP_CONTENT_TYPE];
|
||||||
http_get_content_type(request->location_path->data, content_type);
|
http_get_content_type(request->location_path->data, content_type);
|
||||||
CWS_LOG_DEBUG("content-type: %s", content_type);
|
|
||||||
|
|
||||||
/* TODO: Check for keep-alive */
|
/* TODO: Check for keep-alive */
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user