diff options
| author | Stefan Boberg <[email protected]> | 2021-10-03 21:40:20 +0200 |
|---|---|---|
| committer | Stefan Boberg <[email protected]> | 2021-10-03 21:40:20 +0200 |
| commit | 132c476c82e82ed7978e82067c9159aaeebbd36f (patch) | |
| tree | ded8d61005361a7d9feb7e5a1aa1153e79d98839 /zenhttp | |
| parent | Merge branch 'main' of https://github.com/EpicGames/zen (diff) | |
| parent | http: Moved logic for body suppression to a more central location (diff) | |
| download | zen-132c476c82e82ed7978e82067c9159aaeebbd36f.tar.xz zen-132c476c82e82ed7978e82067c9159aaeebbd36f.zip | |
Merge branch 'main' of https://github.com/EpicGames/zen
Diffstat (limited to 'zenhttp')
| -rw-r--r-- | zenhttp/httpserver.cpp | 40 | ||||
| -rw-r--r-- | zenhttp/httpsys.cpp | 42 |
2 files changed, 69 insertions, 13 deletions
diff --git a/zenhttp/httpserver.cpp b/zenhttp/httpserver.cpp index cfd1463ba..193426ed2 100644 --- a/zenhttp/httpserver.cpp +++ b/zenhttp/httpserver.cpp @@ -67,13 +67,16 @@ MapContentTypeToString(HttpContentType ContentType) ////////////////////////////////////////////////////////////////////////// static constinit uint32_t HashBinary = HashStringDjb2("application/octet-stream"sv); -static constinit uint32_t HashJson = HashStringDjb2("application/json"sv); -static constinit uint32_t HashYaml = HashStringDjb2("text/yaml"sv); +static constinit uint32_t HashApplicationJson = HashStringDjb2("application/json"sv); +static constinit uint32_t HashApplicationYaml = HashStringDjb2("text/yaml"sv); static constinit uint32_t HashText = HashStringDjb2("text/plain"sv); static constinit uint32_t HashCompactBinary = HashStringDjb2("application/x-ue-cb"sv); static constinit uint32_t HashCompactBinaryPackage = HashStringDjb2("application/x-ue-cbpkg"sv); static constinit uint32_t HashCompactBinaryPackageOffer = HashStringDjb2("application/x-ue-offer"sv); static constinit uint32_t HashCompressedBinary = HashStringDjb2("application/x-ue-comp"sv); +static constinit uint32_t HashJson = HashStringDjb2("json"sv); +static constinit uint32_t HashYaml = HashStringDjb2("yaml"sv); +static constinit uint32_t HashHtml = HashStringDjb2("text/html"sv); std::once_flag InitContentTypeLookup; @@ -81,14 +84,21 @@ struct HashedTypeEntry { uint32_t Hash; HttpContentType Type; -} TypeHashTable[] = {{HashBinary, HttpContentType::kBinary}, - {HashCompactBinary, HttpContentType::kCbObject}, - {HashCompactBinaryPackage, HttpContentType::kCbPackage}, - {HashCompactBinaryPackageOffer, HttpContentType::kCbPackageOffer}, - {HashJson, HttpContentType::kJSON}, - {HashYaml, HttpContentType::kYAML}, - {HashText, HttpContentType::kText}, - {HashCompressedBinary, HttpContentType::kCompressedBinary}}; +} TypeHashTable[] = { + // clang-format off + {HashBinary, HttpContentType::kBinary}, + {HashCompactBinary, HttpContentType::kCbObject}, + {HashCompactBinaryPackage, HttpContentType::kCbPackage}, + {HashCompactBinaryPackageOffer, HttpContentType::kCbPackageOffer}, + {HashJson, HttpContentType::kJSON}, + {HashApplicationJson, HttpContentType::kJSON}, + {HashYaml, HttpContentType::kYAML}, + {HashApplicationYaml, HttpContentType::kYAML}, + {HashText, HttpContentType::kText}, + {HashCompressedBinary, HttpContentType::kCompressedBinary}, + {HashHtml, HttpContentType::kHTML}, + // clang-format on +}; HttpContentType ParseContentTypeImpl(const std::string_view& ContentTypeString) @@ -120,6 +130,16 @@ ParseContentTypeInit(const std::string_view& ContentTypeString) std::sort(std::begin(TypeHashTable), std::end(TypeHashTable), [](const HashedTypeEntry& Lhs, const HashedTypeEntry& Rhs) { return Lhs.Hash < Rhs.Hash; }); + + // validate that there are no hash collisions + + uint32_t LastHash = 0; + + for (const auto& Item : TypeHashTable) + { + ZEN_ASSERT(LastHash != Item.Hash); + LastHash = Item.Hash; + } }); ParseContentType = ParseContentTypeImpl; diff --git a/zenhttp/httpsys.cpp b/zenhttp/httpsys.cpp index 9b2e7f832..fedaf282e 100644 --- a/zenhttp/httpsys.cpp +++ b/zenhttp/httpsys.cpp @@ -1086,6 +1086,8 @@ HttpSysServerRequest::HttpSysServerRequest(HttpSysTransaction& Tx, HttpService& const int PrefixLength = Service.UriPrefixLength(); const int AbsPathLength = HttpRequestPtr->CookedUrl.AbsPathLength / sizeof(char16_t); + HttpContentType AcceptContentType = HttpContentType::kUnknownContentType; + if (AbsPathLength >= PrefixLength) { // We convert the URI immediately because most of the code involved prefers to deal @@ -1094,15 +1096,33 @@ HttpSysServerRequest::HttpSysServerRequest(HttpSysTransaction& Tx, HttpService& WideToUtf8({(char16_t*)HttpRequestPtr->CookedUrl.pAbsPath + PrefixLength, gsl::narrow<size_t>(AbsPathLength - PrefixLength)}, m_UriUtf8); + + std::string_view Uri8{m_UriUtf8}; + + const size_t LastComponentIndex = Uri8.find_last_of('/'); + + if (LastComponentIndex != std::string_view::npos) + { + Uri8.remove_prefix(LastComponentIndex); + } + + const size_t LastDotIndex = Uri8.find_last_of('.'); + + if (LastDotIndex != std::string_view::npos) + { + Uri8.remove_prefix(LastDotIndex + 1); + } + + AcceptContentType = ParseContentType(Uri8); } else { m_UriUtf8.Reset(); } - if (auto QueryStringLength = HttpRequestPtr->CookedUrl.QueryStringLength) + if (uint16_t QueryStringLength = HttpRequestPtr->CookedUrl.QueryStringLength) { - --QueryStringLength; + --QueryStringLength; // We skip the leading question mark WideToUtf8({(char16_t*)(HttpRequestPtr->CookedUrl.pQueryString) + 1, QueryStringLength / sizeof(char16_t)}, m_QueryStringUtf8); } @@ -1114,7 +1134,23 @@ HttpSysServerRequest::HttpSysServerRequest(HttpSysTransaction& Tx, HttpService& m_Verb = TranslateHttpVerb(HttpRequestPtr->Verb); m_ContentLength = GetContentLength(HttpRequestPtr); m_ContentType = GetContentType(HttpRequestPtr); - m_AcceptType = GetAcceptType(HttpRequestPtr); + + // It an explicit content type extension was specified then we'll use that over any + // Accept: header value that may be present + + if (AcceptContentType != HttpContentType::kUnknownContentType) + { + m_AcceptType = AcceptContentType; + } + else + { + m_AcceptType = GetAcceptType(HttpRequestPtr); + } + + if (m_Verb == HttpVerb::kHead) + { + SetSuppressResponseBody(); + } } Oid |