aboutsummaryrefslogtreecommitdiff
path: root/zenhttp
diff options
context:
space:
mode:
authorStefan Boberg <[email protected]>2021-10-03 21:40:20 +0200
committerStefan Boberg <[email protected]>2021-10-03 21:40:20 +0200
commit132c476c82e82ed7978e82067c9159aaeebbd36f (patch)
treeded8d61005361a7d9feb7e5a1aa1153e79d98839 /zenhttp
parentMerge branch 'main' of https://github.com/EpicGames/zen (diff)
parenthttp: Moved logic for body suppression to a more central location (diff)
downloadzen-132c476c82e82ed7978e82067c9159aaeebbd36f.tar.xz
zen-132c476c82e82ed7978e82067c9159aaeebbd36f.zip
Merge branch 'main' of https://github.com/EpicGames/zen
Diffstat (limited to 'zenhttp')
-rw-r--r--zenhttp/httpserver.cpp40
-rw-r--r--zenhttp/httpsys.cpp42
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