commit ec4d9dcdef6e1be313614e40af9f38947dea07c7
parent d7d48e8ddff7914d7cc26366cc97643888a58d4e
Author: quantumish <freifeld.david@gmail.com>
Date: Thu, 13 Apr 2023 16:50:45 -0700
Fix various bugs, improve MIME type mapping
Diffstat:
6 files changed, 35 insertions(+), 25 deletions(-)
diff --git a/Makefile b/Makefile
@@ -1,4 +1,4 @@
-CFLAGS?=-O2 -g
+CFLAGS?= -g
LIBS:=-lz -lpthread
CLIBS = $(wildcard utils/*.c) $(wildcard http/*.c)
OBJ = $(wildcard build/*.o)
diff --git a/http.c b/http.c
@@ -25,7 +25,6 @@
#include "http/response.h"
#include "http/request.h"
-
response_t serve_error(enum StatusCode c) {
response_t r = resp_new(c);
resp_add_hdr(&r, "Content-Type", "text/html");
@@ -37,6 +36,13 @@ response_t serve_error(enum StatusCode c) {
shitvec_t paths;
+char* get_file_ext(char* filename) {
+ char* ext = strtok(filename, ".");
+ char* next;
+ while ((next = strtok(NULL, "."))) ext = next;
+ return ext;
+}
+
response_t serve_file(request_t req) {
char path[128+8] = "./public";
strcat(path, req.path);
@@ -48,7 +54,8 @@ response_t serve_file(request_t req) {
char* fbuf = malloc(st.st_size); // TODO what if file larger than memory?
for (size_t i = 0; read(fd, fbuf+(i*4096), 4096) > 0; i++);
- char* ext = strchr(req.path, '.'); // NOTE breaks if there's a dir with a dot...
+
+ char* ext = get_file_ext(req.path);
resp_set_ctype(&r, ext);
@@ -56,12 +63,10 @@ response_t serve_file(request_t req) {
char* mtype = (char*)ext_to_mtype(ext);
char* hdr;
if ((hdr = hashmap_get(&req.headers, "Accept"))) {
- 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;
@@ -69,17 +74,15 @@ response_t serve_file(request_t req) {
}
}
}
-
+
char* buf = fbuf; // buffer to be written
size_t bufsize = st.st_size;
if (ok && (hdr = hashmap_get(&req.headers, "Accept-Encoding"))) {
- log_debug("Handling Accept-Encoding header");
ok = false;
shitvec_t mtypes = hdr_parse_accept(hdr); // abuse of this func
for (int j = 0; j < mtypes.vec_sz; j++) {
struct req_mimetype* a_mtype = shitvec_get(&mtypes, j);
- log_debug("%s", a_mtype->item);
if (strcmp(a_mtype->item, "gzip") == 0) {
resp_add_hdr(&r, "Content-Encoding", "gzip");
buf = gzip_compress(buf, &bufsize);
@@ -97,10 +100,12 @@ response_t serve_file(request_t req) {
}
}
if (!ok) return serve_error(NotAcceptable);
-
- /* char datebuf[64]; */
- /* time_to_str(st.st_mtim.tv_sec, datebuf); */
- /* resp_add_hdr(&r, "Last-Modified", datebuf); */
+
+ #ifndef __APPLE__
+ char datebuf[64];
+ time_to_str(st.st_mtim.tv_sec, datebuf);
+ resp_add_hdr(&r, "Last-Modified", datebuf);
+ #endif
resp_add_content(&r, buf, bufsize);
free(buf);
diff --git a/http/request.c b/http/request.c
@@ -63,17 +63,17 @@ int req_parse(request_t* req) {
req->headers = hashmap_new(MAX_HEADER_NAME, MAX_HEADER_VALUE);
req->headers.vark = true;
+ // FIXME if start is null this causes problems
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) {
char name[MAX_HEADER_NAME] = {0};
- char value[MAX_HEADER_VALUE] = {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 (name[0] == '\r') return 0; // TODO sketch
return -1; // Uhh... half a header. NOTE doesn't even seem to work. fun.
}
- log_debug("Inserting '%s' (len %d) -> '%s'", name, strlen(name), value);
hashmap_set(&req->headers, name, value);
start = memchr(start, '\n', MAX_HEADER_NAME+MAX_HEADER_VALUE)+1;
}
diff --git a/http/request.h b/http/request.h
@@ -18,7 +18,7 @@ const char* method_name(enum http_method m);
#define MAX_PATH_LEN 128
#define MAX_HEADER_NAME 32
-#define MAX_HEADER_VALUE 128
+#define MAX_HEADER_VALUE 512
#define MAX_MIMETYPE_LEN 32
struct req_mimetype {
diff --git a/http/response.c b/http/response.c
@@ -3,6 +3,7 @@
#include <stdlib.h>
#include <stdio.h>
+#include "../utils/log.h"
#include "../utils/hashmap.h"
#include "../utils/time.h"
#include "response.h"
@@ -28,7 +29,7 @@ void resp_add_hdr(response_t* r, char* hdr, char* val) {
}
void resp_add_content(response_t* r, char* content, size_t content_len) {
- char length[8];
+ char length[32];
sprintf(length, "%ld", content_len);
resp_add_hdr(r, "Content-Length", length);
@@ -41,19 +42,23 @@ void resp_add_content(response_t* r, char* content, size_t content_len) {
memcpy(r->content+header_len, content, content_len);
}
+const char* exts[] = {"html", "css", "js", "png", "gif", "jpeg", "svg", "ttf", "woff", "woff2", NULL}; // TODO sentinel sketchy
+const char* mtypes[] = {"text/html", "text/css", "text/javascript", "image/png",
+ "image/gif", "image/jpeg", "image/svg+xml", "font/ttf", "font/woff", "font/woff2"};
+
+// TODO find cleaner way of doing this
+// two lists and loop
const char* ext_to_mtype(char* ext) {
if (ext == NULL) {
return"text/plain";
- } else if (strcmp(ext+1, "html") == 0) {
- return"text/html";
- } else if (strcmp(ext+1, "png") == 0) {
- return"image/png";
- } else if (strcmp(ext+1, "svg") == 0) {
- return "image/svg+xml";
- } else if (strcmp(ext+1, "jpeg") == 0) {
- return "image/jpeg";
}
+ for (size_t i = 0; exts[i] != NULL; i++) {
+ if (strcmp(ext, exts[i]) == 0) return mtypes[i];
+ }
+
+ log_warn("Giving up on mapping %s extension to a MIME type!", ext);
+ return "text/plain";
}
void resp_set_ctype(response_t* r, char* ext) {
diff --git a/utils/log.c b/utils/log.c
@@ -11,7 +11,7 @@
#include "log.h"
-#define LOG_MAX_MSGLEN 128
+#define LOG_MAX_MSGLEN 1024
#define ANSI_RED "\x1b[31m"
#define ANSI_BOLDRED "\x1b[1;31m"