#include #include #include "lnm/common.h" #include "lnm/http/consts.h" #include "lnm/http/loop.h" #include "lnm/http/req.h" lnm_http_parse_err lnm_http_req_parse(lnm_http_req *req, char *buf, size_t len) { const char *method; char *path; size_t method_len, path_len; req->headers.len = LNM_HTTP_MAX_REQ_HEADERS; int req_len = phr_parse_request( buf, len, &method, &method_len, (const char **)&path, &path_len, &req->minor_version, req->headers.arr, &req->headers.len, req->len); if (req_len == -1) { req->len = len; return lnm_http_parse_err_invalid; } else if (req_len == -2) { return lnm_http_parse_err_incomplete; } bool known_method = false; for (size_t i = 0; i < lnm_http_method_names_len && !known_method; i++) { if (strncmp(method, lnm_http_method_names[i], method_len) == 0) { req->method = i; known_method = true; } } if (!known_method) { return lnm_http_parse_err_unknown_method; } // Path will always end with a newline, which we can safely set to nul path[path_len] = '\0'; char *question_mark = strchr(path, '?'); // Only store query if the path doesn't simply end with a question mark if ((question_mark != NULL) && (path_len - (question_mark + 1 - path) > 0)) { req->query.s = question_mark + 1; req->query.len = path_len - (question_mark + 1 - path); path_len = question_mark - path; // All parsed strings should be null-terminated. This character is either a // newline (if at the end of the path), or a question mark (if a query is // present). path[path_len] = '\0'; } req->path.len = path_len; req->path.s = path; req->len = req_len; return lnm_http_parse_err_ok; } void lnm_http_req_reset(lnm_http_req *req) { if (req->body.owned) { free(req->body.buf); } memset(req, 0, sizeof(lnm_http_req)); } lnm_err lnm_http_req_header_get(const char **out, size_t *out_len, lnm_http_req *req, lnm_http_header type) { return lnm_http_req_header_get_s(out, out_len, req, lnm_http_header_names[type]); } lnm_err lnm_http_req_header_get_s(const char **out, size_t *out_len, lnm_http_req *req, const char *name) { size_t name_len = strlen(name); for (size_t i = 0; i < req->headers.len; i++) { const struct phr_header *header = &req->headers.arr[i]; if (lnm_strnieq(header->name, header->name_len, name, name_len)) { *out = header->value; *out_len = header->value_len; return lnm_err_ok; } } return lnm_err_not_found; }