Skip to content

Commit

Permalink
Add comprehensive request header parsing and testing
Browse files Browse the repository at this point in the history
Enhanced HTTP request parsing by properly handling and storing headers. Updated tests to include comprehensive assertions for the parsed headers, ensuring robustness and correctness in the parsing logic. Added the new test case to the CMake build configuration.

Took 52 minutes
  • Loading branch information
SeriousSamV committed Oct 28, 2024
1 parent 1111d0a commit 3bf7db9
Show file tree
Hide file tree
Showing 4 changed files with 73 additions and 3 deletions.
2 changes: 2 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -21,3 +21,5 @@ add_library(tiny_http_server_lib src/tiny_http/tiny_http_server_lib.c src/tiny_h

add_executable(assert_tiny_http_server_lib test/assert_tiny_http_server_lib.c)
target_link_libraries(assert_tiny_http_server_lib tiny_http_server_lib)

add_test(test_tiny_http_server_lib assert_tiny_http_server_lib)
54 changes: 53 additions & 1 deletion src/tiny_http/tiny_http_server_lib.c
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,59 @@ http_request *parse_http_request(const uint8_t *const http_packet, const size_t
free(request);
return nullptr;
}
// TODO parse the rest

if (ptr >= http_packet_len || ptr + 2 >= http_packet_len) {
return request;
}

ptr += 2; // '\r\n'
for (size_t i = 0; ptr < http_packet_len; i++) {
if (ptr + 2 >= http_packet_len) {
break;
}
http_header *header = calloc(1, sizeof(http_header));
const size_t header_name_start_ptr = ptr;
size_t header_name_len = 0;
for (; ptr < http_packet_len; ptr++) {
if (http_packet[ptr] == ' ') {
header_name_len = ptr - header_name_start_ptr;
break;
}
}
if (header_name_len == 0) {
fprintf(stderr, "misformed header");
fflush(stderr);
free(request->url);
free(request);
free(header);
return nullptr;
}
header->name = strndup((char *) http_packet + ptr - header_name_len, header_name_len - 1);

for (; ptr < http_packet_len; ptr++) {
if (http_packet[ptr] != ' ') {
break;
}
}
const size_t header_value_start = ptr;
size_t header_value_len = 0;
for (; ptr < http_packet_len; ptr++) {
if (http_packet[ptr] == '\r' && http_packet[ptr + 1] == '\n') {
header_value_len = ptr - header_value_start;
break;
}
}
header->value = strndup((char *) http_packet + ptr - header_value_len, header_value_len);
if (request->headers == NULL) {
request->headers = calloc(1, sizeof(http_header*));
} else {
const http_header **new_headers = realloc(request->headers, sizeof(http_header*) * (i + 1));
request->headers = new_headers;
}
request->headers[i] = header;
request->headers_cnt = i + 1;
ptr += 2;
}

return request;
}
2 changes: 1 addition & 1 deletion src/tiny_http/tiny_http_server_lib.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ typedef struct http_request {
http_version version;
http_method method;
char *url;
http_header *headers;
http_header **headers;
size_t headers_cnt;
uint8_t *body;
size_t body_len;
Expand Down
18 changes: 17 additions & 1 deletion test/assert_tiny_http_server_lib.c
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,9 @@
//

#include <assert.h>
#include <stdio.h>
#include <string.h>
#include <_stdlib.h>
#include <stdlib.h>

#include "../src/tiny_http/tiny_http_server_lib.h"

Expand All @@ -13,6 +14,21 @@ int main() {
const uint8_t request[] = "GET / HTTP/1.0\r\nHost: localhost:8085\r\nUser-Agent: curl/8.7.1\r\nAccept: */*\r\n\r\n";
const http_request* http_req = parse_http_request(request, strlen((char *)request));
assert(http_req != nullptr);
assert(http_req->method == GET);
assert(http_req->version == HTTP_1_0);
assert(strncmp(http_req->url, "/", 1) == 0);
assert(http_req->headers_cnt == 3);
printf("Header 1: '%s': '%s'\n", http_req->headers[0]->name, http_req->headers[0]->value);
assert(strncmp(http_req->headers[0]->name , "Host", 255) == 0);
assert(strncmp(http_req->headers[0]->value, "localhost:8085", 255) == 0);
printf("Header 2: '%s': '%s'\n", http_req->headers[1]->name, http_req->headers[1]->value);
assert(strncmp(http_req->headers[1]->name, "User-Agent", 255) == 0);
assert(strncmp(http_req->headers[1]->value, "curl/8.7.1", 255) == 0);
printf("Header 3: '%s': '%s'\n", http_req->headers[2]->name, http_req->headers[2]->value);
assert(strncmp(http_req->headers[2]->name, "Accept", 255) == 0);
assert(strncmp(http_req->headers[2]->value, "*/*", 255) == 0);
assert(http_req->body == nullptr);
assert(http_req->body_len == 0);

return EXIT_SUCCESS;
}

0 comments on commit 3bf7db9

Please sign in to comment.