--- 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; } +