commit bbadb5af33b03192d6ecd5e47d344dabedadbbe7
parent 7948a965f9fadc2b36d840de4f2aa626a5b2b2a4
Author: quantumish <freifeld.david@gmail.com>
Date: Wed, 12 Apr 2023 21:19:54 -0700
Switch to hashmap repr of headers
Diffstat:
4 files changed, 48 insertions(+), 27 deletions(-)
diff --git a/http.c b/http.c
@@ -51,14 +51,24 @@ response_t serve_file(request_t req) {
resp_set_ctype(&r, ext);
- bool ok = false;
+ bool ok = true;
char* mtype = (char*)ext_to_mtype(ext);
- for (int i = 0; i < req.headers.vec_sz; i++) {
- char* item = shitvec_get(&req.headers, i);
- if (strcmp(item, ext) == 0 || strcmp(item, "*/*") == 0) {
- ok = true;
- break;
- }
+ char* hdr;
+ char check[MAX_HEADER_NAME] = {0};
+ strcpy(check, "Accept");
+ if ((hdr = hashmap_get(&req.headers, check))) {
+ log_debug("Handling Accept header");
+ ok = false;
+ shitvec_t mtypes = hdr_parse_accept(hdr);
+ for (int j = 0; j < mtypes.vec_sz; j++) {
+ struct req_mimetype* a_mtype = shitvec_get(&mtypes, j);
+ log_debug("%s", a_mtype->item);
+ // TODO doesn't handle stuff like image/* (is that even allowed?)
+ if (strcmp(a_mtype->item, mtype) == 0 || strcmp(a_mtype->item, "*/*") == 0) {
+ ok = true;
+ break;
+ }
+ }
}
if (!ok) return serve_error(NotAcceptable);
diff --git a/http/request.c b/http/request.c
@@ -3,7 +3,6 @@
#include <stdint.h>
#include "../utils/log.h"
-#include "../utils/shitvec.h"
#include "request.h"
const char* method_names[] = {"GET", "HEAD", "POST", "PUT", "DELETE", "CONNECT", "OPTIONS", "TRACE"};
@@ -17,13 +16,6 @@ enum http_method method_enum(char* p) {
return method_codes[((*(uint64_t*)p*0x1b8b6e6d) % 0x100000000) >> 28];
}
-header_line_t header_line_new() {
- header_line_t hl;
- memset(hl.name, 0, MAX_HEADER_NAME);
- memset(hl.value, 0, MAX_HEADER_VALUE);
- return hl;
-}
-
request_t req_new(char* reqbuf, size_t bufsize) {
request_t req;
req.buf = reqbuf;
@@ -48,7 +40,7 @@ shitvec_t hdr_parse_accept(char* val) {
next = strtok(NULL, ",");
float q = 1;
char* qptr = NULL;
- if ((qptr = (char*)memchr(start, ';', next-start))) {
+ if (next != NULL && (qptr = (char*)memchr(start, ';', next-start))) {
sscanf(qptr, ";q=%f", &q);
}
struct req_mimetype mtype;
@@ -69,24 +61,25 @@ int req_parse(request_t* req) {
if (matched < 3 || matched == EOF) return -1;
req->method = method_enum((char*)method);
- req->headers = shitvec_new(sizeof(header_line_t));
+ req->headers = hashmap_new(MAX_HEADER_NAME, MAX_HEADER_VALUE);
char* start = memchr(req->buf, '\n', MAX_HEADER_NAME+MAX_HEADER_VALUE)+1;
while (start+MAX_HEADER_NAME+MAX_HEADER_VALUE < req->buf+req->bufsize) {
- header_line_t hdr = header_line_new();
- int matched = sscanf(start, "%32[^:]: %s", hdr.name, hdr.value);
+ char name[MAX_HEADER_NAME] = {0};
+ char value[MAX_HEADER_VALUE] = {0};
+ int matched = sscanf(start, "%32[^:]: %s", name, value);
if (matched == 0) return 0; // No more headers;
else if (matched == 1) {
- if (hdr.name[0] == '\r') return 0; // TODO sketch
+ if (name[0] == '\r') return 0; // TODO sketch
return -1; // Uhh... half a header.
}
- shitvec_push(&req->headers, &hdr);
+ hashmap_set(&req->headers, &name, &value);
start = memchr(start, '\n', MAX_HEADER_NAME+MAX_HEADER_VALUE)+1;
}
return 0;
}
void req_free(request_t* req) {
- shitvec_free(&req->headers);
+ hashmap_free(&req->headers);
}
#ifdef TEST
diff --git a/http/request.h b/http/request.h
@@ -2,6 +2,7 @@
#define REQUEST_H
#include "../utils/shitvec.h"
+#include "../utils/hashmap.h"
enum http_method {
GET,
@@ -25,10 +26,10 @@ struct req_mimetype {
char item[MAX_MIMETYPE_LEN];
};
-typedef struct header_line {
- char name[MAX_HEADER_NAME];
- char value[MAX_HEADER_VALUE];
-} header_line_t;
+/* typedef struct header_line { */
+/* char name[MAX_HEADER_NAME]; */
+/* char value[MAX_HEADER_VALUE]; */
+/* } header_line_t; */
shitvec_t hdr_parse_accept(char* val);
@@ -38,7 +39,7 @@ typedef struct request {
enum http_method method;
char path[MAX_PATH_LEN];
float ver;
- shitvec_t headers;
+ hashmap_t headers;
} request_t;
request_t req_new(char* reqbuf, size_t bufsize);
diff --git a/utils/hashmap.c b/utils/hashmap.c
@@ -140,3 +140,20 @@ void hashmap_free(hashmap_t* h) {
free(h->keys);
free(h->vals);
}
+
+#ifdef TEST
+#include "../test.h"
+
+void test_hashmap_sanity() {
+ hashmap_t h = hashmap_new(16, 64);
+ hashmap_set(&h, "whoo", "This is a test.");
+ hashmap_set(&h, "Accept", "image/png,text/plain;q=0.5,image/jpeg");
+ hashmap_resize(&h); // make sure it doesn't explode
+ hashmap_set(&h, "Blah blah", "This is (another) test.");
+ assert_str_eq(hashmap_get(&h, "whoo"), "This is a test.");
+ assert_str_eq(hashmap_get(&h, "Accept"), "image/png,text/plain;q=0.5,image/jpeg");
+ assert_str_eq(hashmap_get(&h, "Blah blah"), "This is (another) test.");
+ hashmap_free(&h);
+}
+
+#endif