aboutsummaryrefslogtreecommitdiff
path: root/src/zenhttp/servers/httpparser.h
diff options
context:
space:
mode:
authorStefan Boberg <[email protected]>2023-10-13 09:55:27 +0200
committerGitHub <[email protected]>2023-10-13 09:55:27 +0200
commit74d104d4eb3735e0881f0e1fccc2df8aa4d3f57d (patch)
treeacae59dac67b4d051403f35e580201c214ec4fda /src/zenhttp/servers/httpparser.h
parentfaster oplog iteration (#471) (diff)
downloadzen-74d104d4eb3735e0881f0e1fccc2df8aa4d3f57d.tar.xz
zen-74d104d4eb3735e0881f0e1fccc2df8aa4d3f57d.zip
restructured zenhttp (#472)
separating the http server implementations into a directory and moved diagsvcs into zenserver since it's somewhat hard-coded for it
Diffstat (limited to 'src/zenhttp/servers/httpparser.h')
-rw-r--r--src/zenhttp/servers/httpparser.h112
1 files changed, 112 insertions, 0 deletions
diff --git a/src/zenhttp/servers/httpparser.h b/src/zenhttp/servers/httpparser.h
new file mode 100644
index 000000000..219ac351d
--- /dev/null
+++ b/src/zenhttp/servers/httpparser.h
@@ -0,0 +1,112 @@
+// Copyright Epic Games, Inc. All Rights Reserved.
+
+#pragma once
+
+#include <zencore/uid.h>
+#include <zenhttp/httpcommon.h>
+
+ZEN_THIRD_PARTY_INCLUDES_START
+#include <http_parser.h>
+ZEN_THIRD_PARTY_INCLUDES_END
+
+namespace zen {
+
+class HttpRequestParserCallbacks
+{
+public:
+ virtual ~HttpRequestParserCallbacks() = default;
+ virtual void HandleRequest() = 0;
+ virtual void TerminateConnection() = 0;
+};
+
+struct HttpRequestParser
+{
+ explicit HttpRequestParser(HttpRequestParserCallbacks& Connection);
+ ~HttpRequestParser();
+
+ size_t ConsumeData(const char* InputData, size_t DataSize);
+ void ResetState();
+
+ HttpVerb RequestVerb() const { return m_RequestVerb; }
+ bool IsKeepAlive() const { return m_KeepAlive; }
+ std::string_view Url() const { return m_NormalizedUrl.empty() ? std::string_view(m_Url, m_UrlLength) : m_NormalizedUrl; }
+ std::string_view QueryString() const { return std::string_view(m_QueryString, m_QueryLength); }
+ IoBuffer Body() { return m_BodyBuffer; }
+
+ inline HttpContentType ContentType()
+ {
+ if (m_ContentTypeHeaderIndex < 0)
+ {
+ return HttpContentType::kUnknownContentType;
+ }
+
+ return ParseContentType(m_Headers[m_ContentTypeHeaderIndex].Value);
+ }
+
+ inline HttpContentType AcceptType()
+ {
+ if (m_AcceptHeaderIndex < 0)
+ {
+ return HttpContentType::kUnknownContentType;
+ }
+
+ return ParseContentType(m_Headers[m_AcceptHeaderIndex].Value);
+ }
+
+ Oid SessionId() const { return m_SessionId; }
+ int RequestId() const { return m_RequestId; }
+
+ std::string_view RangeHeader() const { return m_RangeHeaderIndex != -1 ? m_Headers[m_RangeHeaderIndex].Value : std::string_view(); }
+
+private:
+ struct HeaderEntry
+ {
+ HeaderEntry() = default;
+
+ HeaderEntry(std::string_view InName, std::string_view InValue) : Name(InName), Value(InValue) {}
+
+ std::string_view Name;
+ std::string_view Value;
+ };
+
+ HttpRequestParserCallbacks& m_Connection;
+ char* m_HeaderCursor = m_HeaderBuffer;
+ char* m_Url = nullptr;
+ size_t m_UrlLength = 0;
+ char* m_QueryString = nullptr;
+ size_t m_QueryLength = 0;
+ char* m_CurrentHeaderName = nullptr; // Used while parsing headers
+ size_t m_CurrentHeaderNameLength = 0;
+ char* m_CurrentHeaderValue = nullptr; // Used while parsing headers
+ size_t m_CurrentHeaderValueLength = 0;
+ std::vector<HeaderEntry> m_Headers;
+ int8_t m_ContentLengthHeaderIndex;
+ int8_t m_AcceptHeaderIndex;
+ int8_t m_ContentTypeHeaderIndex;
+ int8_t m_RangeHeaderIndex;
+ HttpVerb m_RequestVerb;
+ bool m_KeepAlive = false;
+ bool m_Expect100Continue = false;
+ int m_RequestId = -1;
+ Oid m_SessionId{};
+ IoBuffer m_BodyBuffer;
+ uint64_t m_BodyPosition = 0;
+ http_parser m_Parser;
+ char m_HeaderBuffer[1024];
+ std::string m_NormalizedUrl;
+
+ void AppendCurrentHeader();
+
+ int OnMessageBegin();
+ int OnUrl(const char* Data, size_t Bytes);
+ int OnHeader(const char* Data, size_t Bytes);
+ int OnHeaderValue(const char* Data, size_t Bytes);
+ int OnHeadersComplete();
+ int OnBody(const char* Data, size_t Bytes);
+ int OnMessageComplete();
+
+ static HttpRequestParser* GetThis(http_parser* Parser) { return reinterpret_cast<HttpRequestParser*>(Parser->data); }
+ static http_parser_settings s_ParserSettings;
+};
+
+} // namespace zen