diff --git a/runtime/fastly/common/normalize_http_method.cpp b/runtime/fastly/common/normalize_http_method.cpp index cc92da6e8b..f63d4b15d6 100644 --- a/runtime/fastly/common/normalize_http_method.cpp +++ b/runtime/fastly/common/normalize_http_method.cpp @@ -1,44 +1,28 @@ +#include +#include #include -using namespace std::literals::string_view_literals; - namespace fastly::common { -namespace { -inline char *ascii_uppercase(char *str, size_t length) { - char *up = reinterpret_cast(malloc(length + 1)); - int i = 0; - while (i < length) { - auto ch = str[i]; - if (ch >= 'a' && ch <= 'z') { - up[i] = ch & ~0x20; - } else { - up[i] = ch; - } - i++; - } - up[i] = '\0'; - return up; -} -} // namespace // https://fetch.spec.whatwg.org/#concept-method-normalize // To normalize a method, if it is a byte-case-insensitive match for `DELETE`, `GET`, `HEAD`, // `OPTIONS`, `POST`, or `PUT`, byte-uppercase it. bool normalize_http_method(char *method, size_t length) { - auto m = std::string_view(method, length); - // It's quite likely the method is already uppercased, - // so let's check it first before we create a copy of the method to uppercase it. - // These have been order by most likely to occur. - if (m != "GET"sv && m != "HEAD"sv && m != "OPTIONS"sv && m != "POST"sv && m != "PUT"sv && - m != "DELETE"sv) [[unlikely]] { - auto umethod = ascii_uppercase(method, length); - if (strcmp(umethod, "GET") == 0 || strcmp(umethod, "HEAD") == 0 || - strcmp(umethod, "OPTIONS") == 0 || strcmp(umethod, "POST") == 0 || - strcmp(umethod, "PUT") == 0 || strcmp(umethod, "DELETE") == 0) { - strcpy(method, umethod); - return true; - } + // Ordered by most likely to occur. + constexpr std::string_view methods[] = {"GET", "HEAD", "OPTIONS", "POST", "PUT", "DELETE"}; + std::string_view m(method, length); + + auto iequal = [](unsigned char a, unsigned char b) { return std::toupper(a) == std::toupper(b); }; + + auto it = std::ranges::find_if(methods, [&](std::string_view candidate) { + return std::ranges::equal(m, candidate, iequal); + }); + + if (it == std::ranges::end(methods) || *it == m) { + return false; // not a recognized method, or already normalized } - return false; + + std::ranges::copy(*it, method); // copy the already-uppercase canonical form + return true; } } // namespace fastly::common \ No newline at end of file