commit c5bdd89

grunfink  ·  2025-02-06 09:42:02 +0000 UTC
parents 4ed3a01, 1089b24
Merge pull request 'Rewrite http header parsing' (#298) from inz/snac2:http-header-parse into master

Reviewed-on: https://codeberg.org/grunfink/snac2/pulls/298
2 files changed,  +35, -23
+34, -20
 1@@ -15,41 +15,48 @@ xs_dict *xs_httpd_request(FILE *f, xs_str **payload, int *p_size)
 2 {
 3     xs *q_vars = NULL;
 4     xs *p_vars = NULL;
 5-    xs *l1, *l2;
 6+    xs *l1;
 7     const char *v;
 8+    char *saveptr;
 9 
10     xs_socket_timeout(fileno(f), 2.0, 0.0);
11 
12     /* read the first line and split it */
13     l1 = xs_strip_i(xs_readline(f));
14-    l2 = xs_split(l1, " ");
15+    char *raw_path;
16+    const char *mtd;
17+    const char *proto;
18+
19+    if (!(mtd = strtok_r(l1, " ", &saveptr)) ||
20+        !(raw_path = strtok_r(NULL, " ", &saveptr)) ||
21+        !(proto = strtok_r(NULL, " ", &saveptr)) ||
22+        strtok_r(NULL, " ", &saveptr))
23+        return NULL;
24 
25-    if (xs_list_len(l2) != 3) {
26-        /* error or timeout */
27+    if (!xs_is_string(mtd) || !xs_is_string(raw_path) || !xs_is_string(proto))
28         return NULL;
29-    }
30 
31     xs_dict *req = xs_dict_new();
32 
33-    req = xs_dict_append(req, "method", xs_list_get(l2, 0));
34-    req = xs_dict_append(req, "raw_path", xs_list_get(l2, 1));
35-    req = xs_dict_append(req, "proto",  xs_list_get(l2, 2));
36+    req = xs_dict_append(req, "method", mtd);
37+    req = xs_dict_append(req, "raw_path", raw_path);
38+    req = xs_dict_append(req, "proto",  proto);
39 
40     {
41-        /* split the path with its optional variables */
42-        const xs_val *udp = xs_list_get(l2, 1);
43-        xs *pnv = xs_split_n(udp, "?", 1);
44-
45-        /* store the path */
46-        req = xs_dict_append(req, "path", xs_list_get(pnv, 0));
47+        char *q = strchr(raw_path, '?');
48 
49         /* get the variables */
50-        q_vars = xs_url_vars(xs_list_get(pnv, 1));
51+        if (q) {
52+                *q++ = '\0';
53+                q_vars = xs_url_vars(q);
54+        }
55+        /* store the path */
56+        req = xs_dict_append(req, "path", raw_path);
57     }
58 
59     /* read the headers */
60     for (;;) {
61-        xs *l, *p = NULL;
62+        xs *l;
63 
64         l = xs_strip_i(xs_readline(f));
65 
66@@ -58,11 +65,18 @@ xs_dict *xs_httpd_request(FILE *f, xs_str **payload, int *p_size)
67             break;
68 
69         /* split header and content */
70-        p = xs_split_n(l, ": ", 1);
71+        char *cnt = strchr(l, ':');
72+        if (!cnt)
73+            continue;
74+
75+        *cnt++ = '\0';
76+        cnt += strspn(cnt, " \r\n\t\v\f");
77+        xs_rstrip_chars_i(l, " \r\n\t\v\f");
78+
79+        if (!xs_is_string(cnt))
80+            continue;
81 
82-        if (xs_list_len(p) == 2)
83-            req = xs_dict_append(req, xs_tolower_i(
84-                    (xs_str *)xs_list_get(p, 0)), xs_list_get(p, 1));
85+        req = xs_dict_append(req, xs_tolower_i(l), cnt);
86     }
87 
88     xs_socket_timeout(fileno(f), 5.0, 0.0);
+1, -3
 1@@ -14,7 +14,7 @@ xs_val *xs_readall(FILE *f);
 2 xs_str *xs_readline(FILE *f)
 3 /* reads a line from a file */
 4 {
 5-    xs_str *s = NULL;
 6+    xs_str *s = xs_str_new(NULL);
 7 
 8     errno = 0;
 9 
10@@ -22,8 +22,6 @@ xs_str *xs_readline(FILE *f)
11     if (!feof(f)) {
12         int c;
13 
14-        s = xs_str_new(NULL);
15-
16         while ((c = fgetc(f)) != EOF) {
17             unsigned char rc = c;
18