commit 1089b24171934bc742c2e438f17ec1774b90c728
parent de8fd8305396abd1e7e7208f443be4a4891219cd
Author: Santtu Lakkala <inz@inz.fi>
Date: Thu, 6 Feb 2025 00:47:49 +0200
Rewrite http header parsing
Diffstat:
M | xs_httpd.h | | | 54 | ++++++++++++++++++++++++++++++++++-------------------- |
M | xs_io.h | | | 4 | +--- |
2 files changed, 35 insertions(+), 23 deletions(-)
diff --git a/xs_httpd.h b/xs_httpd.h
@@ -15,41 +15,48 @@ xs_dict *xs_httpd_request(FILE *f, xs_str **payload, int *p_size)
{
xs *q_vars = NULL;
xs *p_vars = NULL;
- xs *l1, *l2;
+ xs *l1;
const char *v;
+ char *saveptr;
xs_socket_timeout(fileno(f), 2.0, 0.0);
/* read the first line and split it */
l1 = xs_strip_i(xs_readline(f));
- l2 = xs_split(l1, " ");
+ char *raw_path;
+ const char *mtd;
+ const char *proto;
+
+ if (!(mtd = strtok_r(l1, " ", &saveptr)) ||
+ !(raw_path = strtok_r(NULL, " ", &saveptr)) ||
+ !(proto = strtok_r(NULL, " ", &saveptr)) ||
+ strtok_r(NULL, " ", &saveptr))
+ return NULL;
- if (xs_list_len(l2) != 3) {
- /* error or timeout */
+ if (!xs_is_string(mtd) || !xs_is_string(raw_path) || !xs_is_string(proto))
return NULL;
- }
xs_dict *req = xs_dict_new();
- req = xs_dict_append(req, "method", xs_list_get(l2, 0));
- req = xs_dict_append(req, "raw_path", xs_list_get(l2, 1));
- req = xs_dict_append(req, "proto", xs_list_get(l2, 2));
+ req = xs_dict_append(req, "method", mtd);
+ req = xs_dict_append(req, "raw_path", raw_path);
+ req = xs_dict_append(req, "proto", proto);
{
- /* split the path with its optional variables */
- const xs_val *udp = xs_list_get(l2, 1);
- xs *pnv = xs_split_n(udp, "?", 1);
-
- /* store the path */
- req = xs_dict_append(req, "path", xs_list_get(pnv, 0));
+ char *q = strchr(raw_path, '?');
/* get the variables */
- q_vars = xs_url_vars(xs_list_get(pnv, 1));
+ if (q) {
+ *q++ = '\0';
+ q_vars = xs_url_vars(q);
+ }
+ /* store the path */
+ req = xs_dict_append(req, "path", raw_path);
}
/* read the headers */
for (;;) {
- xs *l, *p = NULL;
+ xs *l;
l = xs_strip_i(xs_readline(f));
@@ -58,11 +65,18 @@ xs_dict *xs_httpd_request(FILE *f, xs_str **payload, int *p_size)
break;
/* split header and content */
- p = xs_split_n(l, ": ", 1);
+ char *cnt = strchr(l, ':');
+ if (!cnt)
+ continue;
+
+ *cnt++ = '\0';
+ cnt += strspn(cnt, " \r\n\t\v\f");
+ xs_rstrip_chars_i(l, " \r\n\t\v\f");
+
+ if (!xs_is_string(cnt))
+ continue;
- if (xs_list_len(p) == 2)
- req = xs_dict_append(req, xs_tolower_i(
- (xs_str *)xs_list_get(p, 0)), xs_list_get(p, 1));
+ req = xs_dict_append(req, xs_tolower_i(l), cnt);
}
xs_socket_timeout(fileno(f), 5.0, 0.0);
diff --git a/xs_io.h b/xs_io.h
@@ -14,7 +14,7 @@ xs_val *xs_readall(FILE *f);
xs_str *xs_readline(FILE *f)
/* reads a line from a file */
{
- xs_str *s = NULL;
+ xs_str *s = xs_str_new(NULL);
errno = 0;
@@ -22,8 +22,6 @@ xs_str *xs_readline(FILE *f)
if (!feof(f)) {
int c;
- s = xs_str_new(NULL);
-
while ((c = fgetc(f)) != EOF) {
unsigned char rc = c;