bunkum

an old and silly c99 web server with some fun features
Log | Files | Refs | README

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:
Mhttp.c | 24+++++++++++++++++-------
Mhttp/request.c | 23++++++++---------------
Mhttp/request.h | 11++++++-----
Mutils/hashmap.c | 17+++++++++++++++++
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