commit 1089b24
Santtu Lakkala
·
2025-02-05 22:47:49 +0000 UTC
parent de8fd83
Rewrite http header parsing
2 files changed,
+35,
-23
M
xs_io.h
+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);
M
xs_io.h
+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