Work on request header parsing
This commit is contained in:
@@ -3,6 +3,7 @@
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include "http.h"
|
||||
#include "../main.h"
|
||||
|
||||
/*
|
||||
* METHOD_GET, METHOD_POST, METHOD_HEAD, METHOD_PUT,
|
||||
@@ -32,7 +33,7 @@ http_method http_method_fromstring(const char* method) {
|
||||
METHOD_CONNECT};
|
||||
|
||||
size_t count = sizeof(methods) / sizeof(http_method);
|
||||
for(int i; i < count; i++) {
|
||||
for(int i=0; i < count; i++) {
|
||||
if (strcmp(http_method_getstring(methods[i],NULL), method) == 0) {
|
||||
return methods[i];
|
||||
}
|
||||
@@ -42,6 +43,9 @@ http_method http_method_fromstring(const char* method) {
|
||||
|
||||
http_request_line *http_request_line_new(http_method method, const char* other) {
|
||||
http_request_line *req = calloc(1, sizeof(http_request_line));
|
||||
if (req == NULL) {
|
||||
fatal("calloc failed");
|
||||
}
|
||||
req->method = method;
|
||||
if (req->method == METHOD_OTHER) {
|
||||
req->method_other = calloc(strlen(other)+1, sizeof(char));
|
||||
@@ -59,6 +63,9 @@ void http_request_line_delete(http_request_line *req) {
|
||||
|
||||
http_response_line *http_response_line_new(uint16_t code) {
|
||||
http_response_line *resp = calloc(1, sizeof(http_response_line));
|
||||
if (resp == NULL) {
|
||||
fatal("calloc failed");
|
||||
}
|
||||
resp->code = code;
|
||||
resp->version = HTTP11;
|
||||
return resp;
|
||||
@@ -117,7 +124,9 @@ void http_reponse_line_delete(http_response_line *resp) {
|
||||
|
||||
http_header *http_header_new(const char* name) {
|
||||
http_header *header = calloc(1, sizeof(http_header));
|
||||
|
||||
if (header == NULL) {
|
||||
fatal("calloc failed");
|
||||
}
|
||||
header->name = calloc(strlen(name)+1, sizeof(char));
|
||||
strcpy(header->name, name);
|
||||
|
||||
@@ -126,10 +135,16 @@ http_header *http_header_new(const char* name) {
|
||||
void http_header_append_content(http_header *header, const char* content) {
|
||||
if (header->content == NULL) {
|
||||
header->content = calloc(strlen(content)+1, sizeof(char));
|
||||
if (header->content == NULL) {
|
||||
fatal("calloc failed");
|
||||
}
|
||||
strcpy(header->content, content);
|
||||
} else {
|
||||
uint32_t newlen = strlen(header->content) + strlen(content) + 1;
|
||||
header->content = realloc(header->content, newlen);
|
||||
if (header->content == NULL) {
|
||||
fatal("calloc failed");
|
||||
}
|
||||
strcat(header->content, content);
|
||||
}
|
||||
}
|
||||
@@ -141,13 +156,20 @@ void http_header_delete(http_header *header) {
|
||||
|
||||
http_request *http_request_new() {
|
||||
http_request *req = calloc(1, sizeof(http_request));
|
||||
if (req == NULL) {
|
||||
fatal("calloc failed");
|
||||
}
|
||||
req->header_count = 0;
|
||||
req->body = NULL;
|
||||
req->parsestatus = PARSE_REQUESTLINE;
|
||||
return req;
|
||||
}
|
||||
void http_request_add_header(http_request *req, http_header *header) {
|
||||
req->header_count++;
|
||||
req->headers = realloc(req->headers, req->header_count * sizeof(http_header*));
|
||||
if (req->headers == NULL) {
|
||||
fatal("calloc failed");
|
||||
}
|
||||
req->headers[req->header_count-1] = header;
|
||||
}
|
||||
void http_request_apppend_body(http_request *req, const char* body) {
|
||||
@@ -157,6 +179,9 @@ void http_request_apppend_body(http_request *req, const char* body) {
|
||||
}
|
||||
bodylen += strlen(body) + 1;
|
||||
req->body = realloc(req->body, bodylen * sizeof(char));
|
||||
if (req->body == NULL) {
|
||||
fatal("calloc failed");
|
||||
}
|
||||
strcat(req->body, body);
|
||||
}
|
||||
void http_request_delete(http_request *req) {
|
||||
|
||||
@@ -13,7 +13,6 @@ extern "C" {
|
||||
#endif
|
||||
|
||||
#include <stdint.h>
|
||||
#include "request.h"
|
||||
|
||||
typedef enum http_method {
|
||||
METHOD_GET, METHOD_POST, METHOD_HEAD, METHOD_PUT,
|
||||
@@ -43,13 +42,19 @@ extern "C" {
|
||||
char* content;
|
||||
} http_header;
|
||||
|
||||
typedef enum http_request_parsestatus {
|
||||
PARSE_REQUESTLINE, PARSE_HEADERS, PARSE_BODY, PARSE_DONE, PARSE_FAIL
|
||||
} http_request_parsestatus;
|
||||
|
||||
typedef struct http_request {
|
||||
http_request_line *req;
|
||||
http_request_parsestatus parsestatus;
|
||||
http_header **headers;
|
||||
uint32_t header_count;
|
||||
char *body;
|
||||
} http_request;
|
||||
|
||||
|
||||
char* http_method_getstring(http_method method, char* method_other);
|
||||
http_method http_method_fromstring(const char* method);
|
||||
|
||||
|
||||
@@ -1,6 +1,66 @@
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <strings.h>
|
||||
#include "../main.h"
|
||||
#include "http.h"
|
||||
|
||||
|
||||
char* parse_request(http_request *req, char *input) {
|
||||
size_t line_count;
|
||||
char** lines = str_splitlines(input, &line_count);
|
||||
|
||||
switch(req->parsestatus) {
|
||||
case PARSE_REQUESTLINE:
|
||||
if (line_count == 0) {
|
||||
break;
|
||||
}
|
||||
|
||||
char* requestStr = lines[0];
|
||||
|
||||
char methodStr[20] = {0};
|
||||
char uriStr[1024] = {0};
|
||||
char versionStr[16] = {0};
|
||||
|
||||
int count = sscanf(requestStr, "%19s%*[ \t]%1023s%*[ \t]%15s", methodStr, uriStr, versionStr);
|
||||
if (count < 3) {
|
||||
req->parsestatus = PARSE_FAIL;
|
||||
break;
|
||||
}
|
||||
|
||||
http_method method = http_method_fromstring(methodStr);
|
||||
if (method == METHOD_INVALID) {
|
||||
req->parsestatus = PARSE_FAIL;
|
||||
break;
|
||||
}
|
||||
|
||||
http_version version;
|
||||
if (strcasecmp(versionStr, "HTTP/1.0") == 0) { version = HTTP10; }
|
||||
if (strcasecmp(versionStr, "HTTP/1.1") == 0) { version = HTTP11; }
|
||||
|
||||
http_request_line *request_line = http_request_line_new(method, NULL);
|
||||
request_line->version = version;
|
||||
request_line->uri = calloc(strlen(uriStr)+1, sizeof(char));
|
||||
if (request_line->uri == NULL) {
|
||||
fatal("calloc failed");
|
||||
}
|
||||
strcpy(request_line->uri, uriStr);
|
||||
req->req = request_line;
|
||||
req->parsestatus = PARSE_HEADERS;
|
||||
|
||||
break;
|
||||
case PARSE_HEADERS:
|
||||
break;
|
||||
case PARSE_BODY:
|
||||
break;
|
||||
case PARSE_DONE:
|
||||
case PARSE_FAIL:
|
||||
break;
|
||||
}
|
||||
|
||||
for(size_t i=0; i < line_count; i++) {
|
||||
free(lines[i]);
|
||||
free(lines);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
@@ -12,9 +12,10 @@
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "../ut/utstring.h"
|
||||
#include "http.h"
|
||||
|
||||
|
||||
char* parse_request(http_request *req, char *input);
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
||||
56
src/main.c
56
src/main.c
@@ -12,16 +12,26 @@
|
||||
#include <strings.h>
|
||||
|
||||
#include "ut/utlist.h"
|
||||
#include "ut/utarray.h"
|
||||
#include "main.h"
|
||||
#include "socket.h"
|
||||
#include "http/http.h"
|
||||
#include "http/request.h"
|
||||
|
||||
int serverfd = 0;
|
||||
char* teststr = "GET /testing/123 HTTP/1.1\r\n";
|
||||
|
||||
/*
|
||||
*
|
||||
*/
|
||||
int main(int argc, char** argv) {
|
||||
/*char *test = calloc(strlen(teststr)+1, sizeof(char));
|
||||
strcpy(test, teststr);
|
||||
|
||||
http_request *req = http_request_new();
|
||||
parse_request(req, test);
|
||||
|
||||
return 0;*/
|
||||
skt_elem *connections = NULL;
|
||||
|
||||
serverfd = svr_create();
|
||||
@@ -38,6 +48,7 @@ int main(int argc, char** argv) {
|
||||
if (info != NULL) {
|
||||
skt_elem* newconn = calloc(1, sizeof(skt_elem));
|
||||
newconn->info = info;
|
||||
newconn->current_request = http_request_new();
|
||||
LL_APPEND(connections, newconn);
|
||||
}
|
||||
}
|
||||
@@ -90,6 +101,9 @@ int main(int argc, char** argv) {
|
||||
if (elem->info->closed) {
|
||||
LL_DELETE(connections, elem);
|
||||
skt_delete(elem->info);
|
||||
if (elem->current_request != NULL) {
|
||||
http_request_delete(elem->current_request);
|
||||
}
|
||||
free(elem);
|
||||
}
|
||||
}
|
||||
@@ -124,4 +138,46 @@ void info(char* msg, ...) {
|
||||
vfprintf(stdout, msg, va);
|
||||
fputc('\n', stdout);
|
||||
va_end(va);
|
||||
}
|
||||
|
||||
char** str_splitlines(char *str, size_t *line_count) {
|
||||
char **result;
|
||||
*line_count = 0;
|
||||
char *tmp = str;
|
||||
|
||||
while(*tmp) {
|
||||
if (*tmp == '\n') {
|
||||
(*line_count)++;
|
||||
}
|
||||
tmp++;
|
||||
}
|
||||
if (*line_count == 0) {
|
||||
result = calloc(1, sizeof(char*));
|
||||
result[0] = calloc(strlen(str), sizeof(char));
|
||||
strcpy(result[0], str);
|
||||
return result;
|
||||
}
|
||||
result = calloc(*line_count, sizeof(char*));
|
||||
if (result == NULL) {
|
||||
fatal("calloc failed");
|
||||
}
|
||||
|
||||
size_t i=0, linelen = 0;
|
||||
char *line = strtok(str, "\n");
|
||||
while(line) {
|
||||
linelen = strlen(line);
|
||||
result[i] = calloc(linelen+1, sizeof(char));
|
||||
if (result[i] == NULL) {
|
||||
fatal("calloc failed");
|
||||
}
|
||||
strcpy(result[i], line);
|
||||
if (result[i][linelen-1] == '\r') {
|
||||
result[i][linelen-1] = '\0';
|
||||
result[i] = realloc(result[i], linelen);
|
||||
}
|
||||
line = strtok(NULL, "\n");
|
||||
i++;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
@@ -20,6 +20,8 @@ void fatal(char* msg);
|
||||
void warning(char* msg, bool showPError);
|
||||
void info(char* msg, ...);
|
||||
|
||||
char** str_splitlines(char *str, size_t *line_count);
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
||||
@@ -17,8 +17,9 @@ extern "C" {
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#include <time.h>
|
||||
#include "http/http.h"
|
||||
#include "ut/utstring.h"
|
||||
|
||||
|
||||
typedef struct skt_info skt_info;
|
||||
|
||||
struct skt_info {
|
||||
@@ -36,6 +37,7 @@ extern "C" {
|
||||
|
||||
typedef struct skt_elem {
|
||||
skt_info* info;
|
||||
http_request *current_request;
|
||||
struct skt_elem *next;
|
||||
} skt_elem;
|
||||
|
||||
|
||||
@@ -218,7 +218,12 @@ typedef struct {
|
||||
/* last we pre-define a few icd for common utarrays of ints and strings */
|
||||
static void utarray_str_cpy(void *dst, const void *src) {
|
||||
char **_src = (char**)src, **_dst = (char**)dst;
|
||||
*_dst = (*_src == NULL) ? NULL : strdup(*_src);
|
||||
if (*_src != NULL) {
|
||||
*_dst = calloc(strlen(*_src)+1, sizeof(char));
|
||||
if (*_dst != NULL) {
|
||||
strcpy(*_dst, *_src);
|
||||
}
|
||||
}
|
||||
}
|
||||
static void utarray_str_dtor(void *elt) {
|
||||
char **eltc = (char**)elt;
|
||||
|
||||
Reference in New Issue
Block a user