src/server/daemon/httpparser.c

changeset 662
70fdf948b642
parent 415
d938228c382e
child 663
bd116bd44926
--- a/src/server/daemon/httpparser.c	Tue Feb 03 19:09:53 2026 +0100
+++ b/src/server/daemon/httpparser.c	Fri Feb 06 14:06:04 2026 +0100
@@ -35,11 +35,17 @@
 
 
 HttpParser* http_parser_new(HTTPRequest *request) {
+    return http_parser_new2(0, request->netbuf, request->headers);
+}
+
+HttpParser* http_parser_new2(int type, netbuf *netbuf, HeaderArray *headers) {
     HttpParser *parser = calloc(1, sizeof(HttpParser));
-    parser->request = request;
+    parser->type = type;
+    parser->netbuf = netbuf;
+    parser->headers = headers;
     
     parser->state = 0;
-    parser->start_line.ptr = (char*)request->netbuf->inbuf;
+    parser->start_line.ptr = (char*)netbuf->inbuf;
     parser->start_line.length = 0;
     
     parser->offset = 0;
@@ -51,6 +57,12 @@
     free(parser);
 }
 
+void http_parser_update_request(HttpParser *parser, HTTPRequest *request) {
+    request->method = parser->method;
+    request->uri = parser->uri;
+    request->httpv = parser->httpv;
+}
+
 int http_parser_process(HttpParser *parser) {
     switch(parser->state) {
         case 0: {
@@ -59,7 +71,16 @@
                 case 0: break;
                 default: return r;
             }
-            parse_request_line(parser);
+            if(parser->type == 0) {
+                if(parse_request_line(parser)) {
+                    return 2;
+                }
+            } else {
+                if(parse_response_line(parser)) {
+                    return 2;
+                }
+            }
+            
             parser->state++;
         }
         case 1: {
@@ -73,19 +94,27 @@
 }
 
 int http_parser_validate(HttpParser *parser) {
-    HTTPRequest *req = parser->request;
-    if(
-            !req->method.ptr || req->method.length == 0
-            || !req->uri.ptr || req->uri.length == 0
-            || !req->httpv.ptr || req->httpv.length == 0)
-    {
-        return 0;
+    if(parser->type == 0) {
+        if (!parser->method.ptr || parser->method.length == 0
+            || !parser->uri.ptr || parser->uri.length == 0
+            || !parser->httpv.ptr || parser->httpv.length == 0)
+        {
+            return 0;
+        }
+    } else {
+        if (!parser->httpv.ptr || parser->httpv.length == 0
+            || !parser->msg.ptr || parser->msg.length == 0
+            || parser->status == 0)
+        {
+            return 0;
+        }
     }
+    
     return 1;
 }
 
 int get_start_line(HttpParser *parser) {
-    netbuf *buf = parser->request->netbuf;
+    netbuf *buf = parser->netbuf;
     while(buf->pos < buf->cursize) {
         unsigned char c = buf->inbuf[buf->pos];
         if(c == '\n') {
@@ -115,7 +144,7 @@
 }
 
 int http_parser_parse_header(HttpParser *parser) {
-    netbuf *buf = parser->request->netbuf;
+    netbuf *buf = parser->netbuf;
 
     parser->offset = buf->pos; // line offset
     parser->name.ptr = NULL;
@@ -154,8 +183,8 @@
                         parser->value.ptr = "";
                     }
                     // add header
-                    header_add(
-                            parser->request->headers,
+                    header_array_add(
+                            parser->headers,
                             parser->name,
                             parser->value);
                 } else {
@@ -174,54 +203,117 @@
 
 int parse_request_line(HttpParser *parser) {
     cxmutstr line = parser->start_line;
-    parser->request->request_line = line;
     
-    /*
-     * parse method, url and http version
-     */
+    // parse method, url and http version
     
     int i = 0;
     int ns = 0;
 
-    parser->request->method.ptr = line.ptr;
+    parser->method.ptr = line.ptr;
     for(;i<line.length;i++) {
         if(!ns && line.ptr[i] == ' ') {
             ns = 1;
-            parser->request->method.length = i;
+            parser->method.length = i;
         } else if(ns) {
             if(line.ptr[i] != ' ') {
                 break;
             }
         }
     }
+    if(i == line.length) {
+        return 1;
+    }
 
-    parser->request->uri.ptr = line.ptr + i;
+    parser->uri.ptr = line.ptr + i;
     ns = 0;
     int s = i;
     for(;i<line.length;i++) {
         if(!ns && isspace(line.ptr[i])) {
             ns = 1;
-            parser->request->uri.length = i - s;
+            parser->uri.length = i - s;
         } else if(ns) {
             if(line.ptr[i] > 32) {
                 break;
             }
         }
     }
+    if(i == line.length) {
+        return 1;
+    }
 
-    parser->request->httpv.ptr = line.ptr + i;
+    parser->httpv.ptr = line.ptr + i;
     ns = 0;
     s = i;
     for(;i<line.length;i++) {
         if(!ns && isspace(line.ptr[i])) {
             ns = 1;
-            parser->request->httpv.length = i - s;
+            parser->httpv.length = i - s;
+        } else if(ns) {
+            if(line.ptr[i] > 32) {
+                return 1; // non-whitespace char after httpv
+            }
+        }
+    }
+
+    return 0;
+}
+
+int parse_response_line(HttpParser *parser) {
+    cxmutstr line = parser->start_line;
+    
+    // parse http version, status num, status message
+    
+    int i = 0;
+    int ns = 0;
+    
+    parser->httpv.ptr = line.ptr;
+    for(;i<line.length;i++) {
+        if(!ns && line.ptr[i] == ' ') {
+            ns = 1;
+            parser->httpv.length = i;
+        } else if(ns) {
+            if(line.ptr[i] != ' ') {
+                break;
+            }
+        }
+    }
+    
+    ns = 0;
+    int s = i;
+    cxmutstr num_str;
+    num_str.ptr = line.ptr + i;
+    num_str.length = 0;
+    for(;i<line.length;i++) {
+        if(!ns && isspace(line.ptr[i])) {
+            ns = 1;
+            num_str.length = i - s;
         } else if(ns) {
             if(line.ptr[i] > 32) {
                 break;
             }
         }
     }
-
+    
+    if(num_str.length != 3) {
+        return 1;
+    }
+    if(cx_strtoi(num_str, &parser->status, 10)) {
+        return 1;
+    }
+    
+    parser->msg.ptr = line.ptr + i;
+    ns = 1;
+    s = i;
+    for(;i<line.length;i++) {
+        char c = line.ptr[i];
+        if(ns && c < 33) {
+            parser->msg.length = i - s;
+            ns = 0;
+        } else {
+            ns = 1;
+        }
+    }
+    
     return 0;
 }
+

mercurial