From 6bc388a7cd90b954dbcd65886eb67fb1c15cb8c9 Mon Sep 17 00:00:00 2001 From: Nigro Simone Date: Sat, 3 Oct 2026 07:51:34 +0200 Subject: [PATCH] Accept the asterisk form for OPTIONS --- src/HttpParser.h | 4 ++-- tests/HttpParser.cpp | 23 +++++++++++++++++++++++ 2 files changed, 25 insertions(+), 2 deletions(-) diff --git a/src/HttpParser.h b/src/HttpParser.h index 5154536b2..d82d67eb1 100644 --- a/src/HttpParser.h +++ b/src/HttpParser.h @@ -302,14 +302,14 @@ struct HttpParser { /* Puts method as key, target as value and returns non-null (or nullptr on error). */ static inline char *consumeRequestLine(char *data, char *end, HttpRequest::Header &header) { - /* Scan until single SP, assume next is / (origin request) */ + /* Scan until single SP, assume next is / (origin request), or * for OPTIONS (asterisk form) */ char *start = data; /* This catches the post padded CR and fails */ while (data[0] > 32) data++; if (&data[1] == end) [[unlikely]] { return nullptr; } - if (data[0] == 32 && data[1] == '/') [[likely]] { + if (data[0] == 32 && (data[1] == '/' || (data[1] == '*' && data[2] == 32 && data - start == 7 && !memcmp(start, "OPTIONS", 7)))) [[likely]] { header.key = {start, (size_t) (data - start)}; data++; /* Scan for less than 33 (catches post padded CR and fails) or more than 126 (not ASCII, fails) */ diff --git a/tests/HttpParser.cpp b/tests/HttpParser.cpp index e1836527a..6c56babbf 100644 --- a/tests/HttpParser.cpp +++ b/tests/HttpParser.cpp @@ -147,4 +147,27 @@ int main() { return 1; } } + + /* RFC 9112 3.2.4: the asterisk form is only for OPTIONS, the app gets "*" as URL */ + for (std::string method : {"OPTIONS", "GET"}) { + std::string req = method + " * HTTP/1.1\r\nHost: 127.0.0.1\r\n\r\n"; + unsigned int length = (unsigned int) req.size(); + req.append(32, 'E'); + + std::string url; + void *starUser = (void *) 13; + uWS::HttpParser starParser; + auto [starErr, starReturned] = starParser.consumePostPadded(req.data(), length, starUser, nullptr, [&url](void *s, uWS::HttpRequest *httpRequest) -> void * { + url = httpRequest->getUrl(); + return s; + }, [](void *s, std::string_view, bool) -> void * { + return s; + }); + + bool accepted = starReturned == starUser && url == "*"; + if (accepted != (method == "OPTIONS")) { + std::cerr << method << " * expected " << (method == "OPTIONS" ? "accept" : "400") << ", got err=" << starErr << std::endl; + return 1; + } + } }