aboutsummaryrefslogtreecommitdiff
path: root/zencore/httpserver.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'zencore/httpserver.cpp')
-rw-r--r--zencore/httpserver.cpp459
1 files changed, 265 insertions, 194 deletions
diff --git a/zencore/httpserver.cpp b/zencore/httpserver.cpp
index d7e6a875f..a9096b99b 100644
--- a/zencore/httpserver.cpp
+++ b/zencore/httpserver.cpp
@@ -481,21 +481,55 @@ HttpServerRequest::ReadPayloadPackage()
#if ZEN_PLATFORM_WINDOWS
class HttpSysServer;
-class HttpTransaction;
+class HttpSysTransaction;
+class HttpMessageResponseRequest;
class HttpSysRequestHandler
{
public:
- HttpSysRequestHandler(HttpTransaction& InRequest) : m_Request(InRequest) {}
+ HttpSysRequestHandler(HttpSysTransaction& InRequest) : m_Request(InRequest) {}
virtual ~HttpSysRequestHandler() = default;
virtual void IssueRequest() = 0;
virtual HttpSysRequestHandler* HandleCompletion(ULONG IoResult, ULONG_PTR NumberOfBytesTransferred) = 0;
- HttpTransaction& Transaction() { return m_Request; }
+ HttpSysTransaction& Transaction() { return m_Request; }
private:
- HttpTransaction& m_Request; // Outermost HTTP transaction object
+ HttpSysTransaction& m_Request; // Outermost HTTP transaction object
+};
+
+struct InitialRequestHandler : public HttpSysRequestHandler
+{
+ inline PHTTP_REQUEST HttpRequest() { return (PHTTP_REQUEST)m_RequestBuffer; }
+ inline uint32_t RequestBufferSize() const { return sizeof m_RequestBuffer; }
+
+ InitialRequestHandler(HttpSysTransaction& InRequest) : HttpSysRequestHandler(InRequest) {}
+ ~InitialRequestHandler() {}
+
+ virtual void IssueRequest() override;
+ virtual HttpSysRequestHandler* HandleCompletion(ULONG IoResult, ULONG_PTR NumberOfBytesTransferred) override;
+
+ PHTTP_REQUEST m_HttpRequestPtr = (HTTP_REQUEST*)(m_RequestBuffer);
+ UCHAR m_RequestBuffer[16384 + sizeof(HTTP_REQUEST)];
+};
+
+class HttpSysServerRequest : public HttpServerRequest
+{
+public:
+ HttpSysServerRequest() = default;
+ HttpSysServerRequest(HttpSysTransaction& Tx, HttpService& Service);
+ ~HttpSysServerRequest() = default;
+
+ virtual void ReadPayload(std::function<void(HttpServerRequest&, IoBuffer)>&& CompletionHandler) override;
+ virtual IoBuffer ReadPayload() override;
+ virtual void WriteResponse(HttpResponse HttpResponseCode) override;
+ virtual void WriteResponse(HttpResponse HttpResponseCode, HttpContentType ContentType, std::span<IoBuffer> Blobs) override;
+ virtual void WriteResponse(HttpResponse HttpResponseCode, HttpContentType ContentType, std::u8string_view ResponseString) override;
+
+ bool m_IsInitialized = false;
+ HttpSysTransaction& m_HttpTx;
+ HttpMessageResponseRequest* m_Response = nullptr; // TODO: make this more general
};
/** HTTP transaction
@@ -503,12 +537,12 @@ private:
There will be an instance of this per pending and in-flight HTTP transaction
*/
-class HttpTransaction
+class HttpSysTransaction
{
public:
- HttpTransaction(HttpSysServer& Server) : m_HttpServer(Server), m_HttpHandler(&m_InitialHttpHandler) {}
+ HttpSysTransaction(HttpSysServer& Server) : m_HttpServer(Server), m_HttpHandler(&m_InitialHttpHandler) {}
- virtual ~HttpTransaction() {}
+ virtual ~HttpSysTransaction() {}
enum class Status
{
@@ -533,16 +567,15 @@ public:
// than one thread at any given moment. This means we need to be careful about what
// happens in here
- HttpTransaction* Transaction = CONTAINING_RECORD(pOverlapped, HttpTransaction, m_HttpOverlapped);
+ HttpSysTransaction* Transaction = CONTAINING_RECORD(pOverlapped, HttpSysTransaction, m_HttpOverlapped);
- if (Transaction->HandleCompletion(IoResult, NumberOfBytesTransferred) == HttpTransaction::Status::kDone)
+ if (Transaction->HandleCompletion(IoResult, NumberOfBytesTransferred) == HttpSysTransaction::Status::kDone)
{
delete Transaction;
}
}
- void IssueInitialRequest();
-
+ void IssueInitialRequest();
PTP_IO Iocp();
HANDLE RequestQueueHandle();
inline OVERLAPPED* Overlapped() { return &m_HttpOverlapped; }
@@ -557,31 +590,41 @@ protected:
RwLock m_Lock;
private:
- struct InitialRequestHandler : public HttpSysRequestHandler
- {
- inline PHTTP_REQUEST HttpRequest() { return (PHTTP_REQUEST)m_RequestBuffer; }
- inline uint32_t RequestBufferSize() const { return sizeof m_RequestBuffer; }
+ InitialRequestHandler m_InitialHttpHandler{*this};
+};
- InitialRequestHandler(HttpTransaction& InRequest) : HttpSysRequestHandler(InRequest) {}
- ~InitialRequestHandler() {}
+//////////////////////////////////////////////////////////////////////////
- virtual void IssueRequest() override;
- virtual HttpSysRequestHandler* HandleCompletion(ULONG IoResult, ULONG_PTR NumberOfBytesTransferred) override;
+class HttpPayloadReadRequest : public HttpSysRequestHandler
+{
+public:
+ HttpPayloadReadRequest(HttpSysTransaction& InRequest) : HttpSysRequestHandler(InRequest) {}
- PHTTP_REQUEST m_HttpRequestPtr = (HTTP_REQUEST*)(m_RequestBuffer);
- UCHAR m_RequestBuffer[16384 + sizeof(HTTP_REQUEST)];
- } m_InitialHttpHandler{*this};
+ virtual void IssueRequest() override;
+ virtual HttpSysRequestHandler* HandleCompletion(ULONG IoResult, ULONG_PTR NumberOfBytesTransferred) override;
};
+void
+HttpPayloadReadRequest::IssueRequest()
+{
+}
+
+HttpSysRequestHandler*
+HttpPayloadReadRequest::HandleCompletion(ULONG IoResult, ULONG_PTR NumberOfBytesTransferred)
+{
+ ZEN_UNUSED(IoResult, NumberOfBytesTransferred);
+ return nullptr;
+}
+
//////////////////////////////////////////////////////////////////////////
class HttpMessageResponseRequest : public HttpSysRequestHandler
{
public:
- HttpMessageResponseRequest(HttpTransaction& InRequest, uint16_t ResponseCode);
- HttpMessageResponseRequest(HttpTransaction& InRequest, uint16_t ResponseCode, const char* Message);
- HttpMessageResponseRequest(HttpTransaction& InRequest, uint16_t ResponseCode, const void* Payload, size_t PayloadSize);
- HttpMessageResponseRequest(HttpTransaction& InRequest, uint16_t ResponseCode, std::span<IoBuffer> Blobs);
+ HttpMessageResponseRequest(HttpSysTransaction& InRequest, uint16_t ResponseCode);
+ HttpMessageResponseRequest(HttpSysTransaction& InRequest, uint16_t ResponseCode, const char* Message);
+ HttpMessageResponseRequest(HttpSysTransaction& InRequest, uint16_t ResponseCode, const void* Payload, size_t PayloadSize);
+ HttpMessageResponseRequest(HttpSysTransaction& InRequest, uint16_t ResponseCode, std::span<IoBuffer> Blobs);
~HttpMessageResponseRequest();
virtual void IssueRequest() override;
@@ -603,14 +646,15 @@ private:
std::vector<IoBuffer> m_DataBuffers;
};
-HttpMessageResponseRequest::HttpMessageResponseRequest(HttpTransaction& InRequest, uint16_t ResponseCode) : HttpSysRequestHandler(InRequest)
+HttpMessageResponseRequest::HttpMessageResponseRequest(HttpSysTransaction& InRequest, uint16_t ResponseCode)
+: HttpSysRequestHandler(InRequest)
{
std::array<IoBuffer, 0> buffers;
Initialize(ResponseCode, buffers);
}
-HttpMessageResponseRequest::HttpMessageResponseRequest(HttpTransaction& InRequest, uint16_t ResponseCode, const char* Message)
+HttpMessageResponseRequest::HttpMessageResponseRequest(HttpSysTransaction& InRequest, uint16_t ResponseCode, const char* Message)
: HttpSysRequestHandler(InRequest)
{
IoBuffer MessageBuffer(IoBuffer::Wrap, Message, strlen(Message));
@@ -619,10 +663,10 @@ HttpMessageResponseRequest::HttpMessageResponseRequest(HttpTransaction& InReques
Initialize(ResponseCode, buffers);
}
-HttpMessageResponseRequest::HttpMessageResponseRequest(HttpTransaction& InRequest,
- uint16_t ResponseCode,
- const void* Payload,
- size_t PayloadSize)
+HttpMessageResponseRequest::HttpMessageResponseRequest(HttpSysTransaction& InRequest,
+ uint16_t ResponseCode,
+ const void* Payload,
+ size_t PayloadSize)
: HttpSysRequestHandler(InRequest)
{
IoBuffer MessageBuffer(IoBuffer::Wrap, Payload, PayloadSize);
@@ -631,7 +675,7 @@ HttpMessageResponseRequest::HttpMessageResponseRequest(HttpTransaction& InReques
Initialize(ResponseCode, buffers);
}
-HttpMessageResponseRequest::HttpMessageResponseRequest(HttpTransaction& InRequest, uint16_t ResponseCode, std::span<IoBuffer> Blobs)
+HttpMessageResponseRequest::HttpMessageResponseRequest(HttpSysTransaction& InRequest, uint16_t ResponseCode, std::span<IoBuffer> Blobs)
: HttpSysRequestHandler(InRequest)
{
Initialize(ResponseCode, Blobs);
@@ -708,7 +752,9 @@ HttpMessageResponseRequest::HandleCompletion(ULONG IoResult, ULONG_PTR NumberOfB
ZEN_UNUSED(IoResult);
if (m_RemainingChunkCount == 0)
+ {
return nullptr; // All done
+ }
return this;
}
@@ -716,7 +762,7 @@ HttpMessageResponseRequest::HandleCompletion(ULONG IoResult, ULONG_PTR NumberOfB
void
HttpMessageResponseRequest::IssueRequest()
{
- HttpTransaction& Tx = Transaction();
+ HttpSysTransaction& Tx = Transaction();
HTTP_REQUEST* const HttpReq = Tx.HttpRequest();
PTP_IO const Iocp = Tx.Iocp();
@@ -828,7 +874,7 @@ HttpMessageResponseRequest::IssueRequest()
class HttpSysServer
{
- friend class HttpTransaction;
+ friend class HttpSysTransaction;
public:
HttpSysServer(WinIoThreadPool& InThreadPool);
@@ -945,7 +991,7 @@ HttpSysServer::Initialize(const wchar_t* UrlPath)
// Create I/O completion port
- m_ThreadPool.CreateIocp(m_RequestQueueHandle, HttpTransaction::IoCompletionCallback, this);
+ m_ThreadPool.CreateIocp(m_RequestQueueHandle, HttpSysTransaction::IoCompletionCallback, this);
// Check result!
}
@@ -1015,7 +1061,7 @@ HttpSysServer::IssueNewRequestMaybe()
return;
}
- std::unique_ptr<HttpTransaction> Request = std::make_unique<HttpTransaction>(*this);
+ std::unique_ptr<HttpSysTransaction> Request = std::make_unique<HttpSysTransaction>(*this);
Request->IssueInitialRequest();
@@ -1083,227 +1129,235 @@ HttpSysServer::RemoveEndpoint(const char* UrlPath, HttpService& Service)
//////////////////////////////////////////////////////////////////////////
-class HttpSysServerRequest : public HttpServerRequest
+HttpSysServerRequest::HttpSysServerRequest(HttpSysTransaction& Tx, HttpService& Service) : m_IsInitialized(true), m_HttpTx(Tx)
{
-public:
- HttpSysServerRequest(HttpTransaction& Tx, HttpService& Service) : m_HttpTx(Tx)
- {
- PHTTP_REQUEST HttpRequestPtr = Tx.HttpRequest();
+ PHTTP_REQUEST HttpRequestPtr = Tx.HttpRequest();
- const int PrefixLength = Service.UriPrefixLength();
- const int AbsPathLength = HttpRequestPtr->CookedUrl.AbsPathLength / sizeof(char16_t);
+ const int PrefixLength = Service.UriPrefixLength();
+ const int AbsPathLength = HttpRequestPtr->CookedUrl.AbsPathLength / sizeof(char16_t);
- if (AbsPathLength >= PrefixLength)
- {
- // We convert the URI immediately because most of the code involved prefers to deal
- // with utf8. This has some performance impact which I'd prefer to avoid but for now
- // we just have to live with it
+ if (AbsPathLength >= PrefixLength)
+ {
+ // We convert the URI immediately because most of the code involved prefers to deal
+ // with utf8. This has some performance impact which I'd prefer to avoid but for now
+ // we just have to live with it
- WideToUtf8({(char16_t*)HttpRequestPtr->CookedUrl.pAbsPath + PrefixLength, gsl::narrow<size_t>(AbsPathLength - PrefixLength)},
- m_Uri);
- }
- else
- {
- m_Uri.Reset();
- }
+ WideToUtf8({(char16_t*)HttpRequestPtr->CookedUrl.pAbsPath + PrefixLength, gsl::narrow<size_t>(AbsPathLength - PrefixLength)},
+ m_Uri);
+ }
+ else
+ {
+ m_Uri.Reset();
+ }
- if (auto QueryStringLength = HttpRequestPtr->CookedUrl.QueryStringLength)
- {
- --QueryStringLength;
+ if (auto QueryStringLength = HttpRequestPtr->CookedUrl.QueryStringLength)
+ {
+ --QueryStringLength;
- WideToUtf8({(char16_t*)(HttpRequestPtr->CookedUrl.pQueryString) + 1, QueryStringLength / sizeof(char16_t)}, m_QueryString);
- }
- else
- {
- m_QueryString.Reset();
- }
+ WideToUtf8({(char16_t*)(HttpRequestPtr->CookedUrl.pQueryString) + 1, QueryStringLength / sizeof(char16_t)}, m_QueryString);
+ }
+ else
+ {
+ m_QueryString.Reset();
+ }
- switch (HttpRequestPtr->Verb)
- {
- case HttpVerbOPTIONS:
- m_Verb = HttpVerb::kOptions;
- break;
-
- case HttpVerbGET:
- m_Verb = HttpVerb::kGet;
- break;
-
- case HttpVerbHEAD:
- m_Verb = HttpVerb::kHead;
- break;
-
- case HttpVerbPOST:
- m_Verb = HttpVerb::kPost;
- break;
-
- case HttpVerbPUT:
- m_Verb = HttpVerb::kPut;
- break;
-
- case HttpVerbDELETE:
- m_Verb = HttpVerb::kDelete;
- break;
-
- case HttpVerbCOPY:
- m_Verb = HttpVerb::kCopy;
- break;
-
- default:
- // TODO: invalid request?
- m_Verb = (HttpVerb)0;
- break;
- }
+ switch (HttpRequestPtr->Verb)
+ {
+ case HttpVerbOPTIONS:
+ m_Verb = HttpVerb::kOptions;
+ break;
- const HTTP_KNOWN_HEADER& clh = HttpRequestPtr->Headers.KnownHeaders[HttpHeaderContentLength];
- std::string_view cl(clh.pRawValue, clh.RawValueLength);
- std::from_chars(cl.data(), cl.data() + cl.size(), m_ContentLength);
+ case HttpVerbGET:
+ m_Verb = HttpVerb::kGet;
+ break;
- const HTTP_KNOWN_HEADER& CtHdr = HttpRequestPtr->Headers.KnownHeaders[HttpHeaderContentType];
- m_ContentType = MapContentType({CtHdr.pRawValue, CtHdr.RawValueLength});
- }
+ case HttpVerbHEAD:
+ m_Verb = HttpVerb::kHead;
+ break;
- ~HttpSysServerRequest() {}
+ case HttpVerbPOST:
+ m_Verb = HttpVerb::kPost;
+ break;
- virtual IoBuffer ReadPayload() override
- {
- // This is presently synchronous for simplicity, but we
- // need to implement an asynchronous version also
+ case HttpVerbPUT:
+ m_Verb = HttpVerb::kPut;
+ break;
- HTTP_REQUEST* const HttpReq = m_HttpTx.HttpRequest();
+ case HttpVerbDELETE:
+ m_Verb = HttpVerb::kDelete;
+ break;
- IoBuffer PayloadBuffer(m_ContentLength);
+ case HttpVerbCOPY:
+ m_Verb = HttpVerb::kCopy;
+ break;
- HttpContentType ContentType = RequestContentType();
- PayloadBuffer.SetContentType(ContentType);
+ default:
+ // TODO: invalid request?
+ m_Verb = (HttpVerb)0;
+ break;
+ }
- uint64_t BytesToRead = m_ContentLength;
+ const HTTP_KNOWN_HEADER& clh = HttpRequestPtr->Headers.KnownHeaders[HttpHeaderContentLength];
+ std::string_view cl(clh.pRawValue, clh.RawValueLength);
+ std::from_chars(cl.data(), cl.data() + cl.size(), m_ContentLength);
- uint8_t* ReadPointer = reinterpret_cast<uint8_t*>(PayloadBuffer.MutableData());
+ const HTTP_KNOWN_HEADER& CtHdr = HttpRequestPtr->Headers.KnownHeaders[HttpHeaderContentType];
+ m_ContentType = MapContentType({CtHdr.pRawValue, CtHdr.RawValueLength});
+}
- // First deal with any payload which has already been copied
- // into our request buffer
+void
+HttpSysServerRequest::ReadPayload(std::function<void(HttpServerRequest&, IoBuffer)>&& CompletionHandler)
+{
+ ZEN_UNUSED(CompletionHandler);
+}
- const int EntityChunkCount = HttpReq->EntityChunkCount;
+IoBuffer
+HttpSysServerRequest::ReadPayload()
+{
+ // This is presently synchronous for simplicity, but we
+ // need to implement an asynchronous version also
- for (int i = 0; i < EntityChunkCount; ++i)
- {
- HTTP_DATA_CHUNK& EntityChunk = HttpReq->pEntityChunks[i];
+ HTTP_REQUEST* const HttpReq = m_HttpTx.HttpRequest();
- ZEN_ASSERT(EntityChunk.DataChunkType == HttpDataChunkFromMemory);
+ IoBuffer PayloadBuffer(m_ContentLength);
- const uint64_t BufferLength = EntityChunk.FromMemory.BufferLength;
+ HttpContentType ContentType = RequestContentType();
+ PayloadBuffer.SetContentType(ContentType);
- ZEN_ASSERT(BufferLength <= BytesToRead);
+ uint64_t BytesToRead = m_ContentLength;
- memcpy(ReadPointer, EntityChunk.FromMemory.pBuffer, BufferLength);
+ uint8_t* ReadPointer = reinterpret_cast<uint8_t*>(PayloadBuffer.MutableData());
- ReadPointer += BufferLength;
- BytesToRead -= BufferLength;
- }
+ // First deal with any payload which has already been copied
+ // into our request buffer
- // Call http.sys API to receive the remaining data
+ const int EntityChunkCount = HttpReq->EntityChunkCount;
- static const uint64_t kMaxBytesPerApiCall = 1 * 1024 * 1024;
+ for (int i = 0; i < EntityChunkCount; ++i)
+ {
+ HTTP_DATA_CHUNK& EntityChunk = HttpReq->pEntityChunks[i];
- while (BytesToRead)
- {
- ULONG BytesRead = 0;
+ ZEN_ASSERT(EntityChunk.DataChunkType == HttpDataChunkFromMemory);
- const uint64_t BytesToReadThisCall = zen::Min(BytesToRead, kMaxBytesPerApiCall);
+ const uint64_t BufferLength = EntityChunk.FromMemory.BufferLength;
- ULONG ApiResult = HttpReceiveRequestEntityBody(m_HttpTx.RequestQueueHandle(),
- HttpReq->RequestId,
- 0, /* Flags */
- ReadPointer,
- gsl::narrow<ULONG>(BytesToReadThisCall),
- &BytesRead,
- NULL /* Overlapped */
- );
+ ZEN_ASSERT(BufferLength <= BytesToRead);
- if (ApiResult != NO_ERROR && ApiResult != ERROR_HANDLE_EOF)
- {
- throw HttpServerException("payload read failed", ApiResult);
- }
+ memcpy(ReadPointer, EntityChunk.FromMemory.pBuffer, BufferLength);
- BytesToRead -= BytesRead;
- ReadPointer += BytesRead;
- }
+ ReadPointer += BufferLength;
+ BytesToRead -= BufferLength;
+ }
+ if (BytesToRead == 0)
+ {
PayloadBuffer.MakeImmutable();
return PayloadBuffer;
}
- virtual void WriteResponse(HttpResponse HttpResponseCode) override
+ // Call http.sys API to receive the remaining data SYNCHRONOUSLY
+
+ static const uint64_t kMaxBytesPerApiCall = 1 * 1024 * 1024;
+
+ while (BytesToRead)
{
- ZEN_ASSERT(m_IsHandled == false);
+ ULONG BytesRead = 0;
+
+ const uint64_t BytesToReadThisCall = zen::Min(BytesToRead, kMaxBytesPerApiCall);
- m_Response = new HttpMessageResponseRequest(m_HttpTx, (uint16_t)HttpResponseCode);
+ ULONG ApiResult = HttpReceiveRequestEntityBody(m_HttpTx.RequestQueueHandle(),
+ HttpReq->RequestId,
+ 0, /* Flags */
+ ReadPointer,
+ gsl::narrow<ULONG>(BytesToReadThisCall),
+ &BytesRead,
+ NULL /* Overlapped */
+ );
- if (m_SuppressBody)
+ if (ApiResult != NO_ERROR && ApiResult != ERROR_HANDLE_EOF)
{
- m_Response->SuppressResponseBody();
+ throw HttpServerException("payload read failed", ApiResult);
}
- m_IsHandled = true;
+ BytesToRead -= BytesRead;
+ ReadPointer += BytesRead;
}
- virtual void WriteResponse(HttpResponse HttpResponseCode, HttpContentType ContentType, std::span<IoBuffer> Blobs) override
- {
- ZEN_ASSERT(m_IsHandled == false);
- ZEN_UNUSED(ContentType);
+ PayloadBuffer.MakeImmutable();
- m_Response = new HttpMessageResponseRequest(m_HttpTx, (uint16_t)HttpResponseCode, Blobs);
+ return PayloadBuffer;
+}
- if (m_SuppressBody)
- {
- m_Response->SuppressResponseBody();
- }
+void
+HttpSysServerRequest::WriteResponse(HttpResponse HttpResponseCode)
+{
+ ZEN_ASSERT(m_IsHandled == false);
+
+ m_Response = new HttpMessageResponseRequest(m_HttpTx, (uint16_t)HttpResponseCode);
- m_IsHandled = true;
+ if (m_SuppressBody)
+ {
+ m_Response->SuppressResponseBody();
}
- virtual void WriteResponse(HttpResponse HttpResponseCode, HttpContentType ContentType, std::u8string_view ResponseString) override
+ m_IsHandled = true;
+}
+
+void
+HttpSysServerRequest::WriteResponse(HttpResponse HttpResponseCode, HttpContentType ContentType, std::span<IoBuffer> Blobs)
+{
+ ZEN_ASSERT(m_IsHandled == false);
+ ZEN_UNUSED(ContentType);
+
+ m_Response = new HttpMessageResponseRequest(m_HttpTx, (uint16_t)HttpResponseCode, Blobs);
+
+ if (m_SuppressBody)
{
- ZEN_ASSERT(m_IsHandled == false);
- ZEN_UNUSED(ContentType);
+ m_Response->SuppressResponseBody();
+ }
- m_Response = new HttpMessageResponseRequest(m_HttpTx, (uint16_t)HttpResponseCode, ResponseString.data(), ResponseString.size());
+ m_IsHandled = true;
+}
- if (m_SuppressBody)
- {
- m_Response->SuppressResponseBody();
- }
+void
+HttpSysServerRequest::WriteResponse(HttpResponse HttpResponseCode, HttpContentType ContentType, std::u8string_view ResponseString)
+{
+ ZEN_ASSERT(m_IsHandled == false);
+ ZEN_UNUSED(ContentType);
+
+ m_Response = new HttpMessageResponseRequest(m_HttpTx, (uint16_t)HttpResponseCode, ResponseString.data(), ResponseString.size());
- m_IsHandled = true;
+ if (m_SuppressBody)
+ {
+ m_Response->SuppressResponseBody();
}
- HttpTransaction& m_HttpTx;
- HttpMessageResponseRequest* m_Response = nullptr;
-};
+ m_IsHandled = true;
+}
//////////////////////////////////////////////////////////////////////////
PTP_IO
-HttpTransaction::Iocp()
+HttpSysTransaction::Iocp()
{
return m_HttpServer.m_ThreadPool.Iocp();
}
HANDLE
-HttpTransaction::RequestQueueHandle()
+HttpSysTransaction::RequestQueueHandle()
{
return m_HttpServer.m_RequestQueueHandle;
}
void
-HttpTransaction::IssueInitialRequest()
+HttpSysTransaction::IssueInitialRequest()
{
m_InitialHttpHandler.IssueRequest();
}
-HttpTransaction::Status
-HttpTransaction::HandleCompletion(ULONG IoResult, ULONG_PTR NumberOfBytesTransferred)
+HttpSysTransaction::Status
+HttpSysTransaction::HandleCompletion(ULONG IoResult, ULONG_PTR NumberOfBytesTransferred)
{
// We use this to ensure sequential execution of completion handlers
// for any given transaction.
@@ -1347,6 +1401,7 @@ HttpTransaction::HandleCompletion(ULONG IoResult, ULONG_PTR NumberOfBytesTransfe
}
}
+ // Ensure new requests are enqueued
m_HttpServer.IssueNewRequestMaybe();
if (RequestPending)
@@ -1360,13 +1415,13 @@ HttpTransaction::HandleCompletion(ULONG IoResult, ULONG_PTR NumberOfBytesTransfe
//////////////////////////////////////////////////////////////////////////
void
-HttpTransaction::InitialRequestHandler::IssueRequest()
+InitialRequestHandler::IssueRequest()
{
PTP_IO Iocp = Transaction().Iocp();
StartThreadpoolIo(Iocp);
- HttpTransaction& Tx = Transaction();
+ HttpSysTransaction& Tx = Transaction();
HTTP_REQUEST* HttpReq = Tx.HttpRequest();
@@ -1389,14 +1444,14 @@ HttpTransaction::InitialRequestHandler::IssueRequest()
// CleanupHttpIoRequest(pIoRequest);
- fprintf(stderr, "HttpReceiveHttpRequest failed, error 0x%lx\n", Result);
+ spdlog::error("HttpReceiveHttpRequest failed, error {:x}", Result);
return;
}
}
HttpSysRequestHandler*
-HttpTransaction::InitialRequestHandler::HandleCompletion(ULONG IoResult, ULONG_PTR NumberOfBytesTransferred)
+InitialRequestHandler::HandleCompletion(ULONG IoResult, ULONG_PTR NumberOfBytesTransferred)
{
ZEN_UNUSED(IoResult);
ZEN_UNUSED(NumberOfBytesTransferred);
@@ -1536,10 +1591,28 @@ HttpRequestRouter::AddPattern(const char* Id, const char* Regex)
void
HttpRequestRouter::RegisterRoute(const char* Regex, HttpRequestRouter::HandlerFunc_t&& HandlerFunc, HttpVerb SupportedVerbs)
{
- // Expand patterns
+ ExtendableStringBuilder<128> ExpandedRegex;
+ ProcessRegexSubstitutions(Regex, ExpandedRegex);
+ m_Handlers.emplace_back(ExpandedRegex.c_str(), SupportedVerbs, std::move(HandlerFunc), Regex);
+}
+
+void
+HttpRequestRouter::RegisterRoute(const char* Regex, PackageEndpointHandler& Handler)
+{
ExtendableStringBuilder<128> ExpandedRegex;
+ ProcessRegexSubstitutions(Regex, ExpandedRegex);
+
+ m_Handlers.emplace_back(
+ ExpandedRegex.c_str(),
+ HttpVerb::kPost,
+ [&Handler](HttpRouterRequest& Request) { Handler.HandleRequest(Request); },
+ Regex);
+}
+void
+HttpRequestRouter::ProcessRegexSubstitutions(const char* Regex, StringBuilderBase& OutExpandedRegex)
+{
size_t RegexLen = strlen(Regex);
for (size_t i = 0; i < RegexLen;)
@@ -1558,13 +1631,13 @@ HttpRequestRouter::RegisterRoute(const char* Regex, HttpRequestRouter::HandlerFu
if (auto it = m_PatternMap.find(Pattern); it != m_PatternMap.end())
{
- ExpandedRegex.Append(it->second.c_str());
+ OutExpandedRegex.Append(it->second.c_str());
}
else
{
// Default to anything goes (or should this just be an error?)
- ExpandedRegex.Append("(.+?)");
+ OutExpandedRegex.Append("(.+?)");
}
// skip ahead
@@ -1579,11 +1652,9 @@ HttpRequestRouter::RegisterRoute(const char* Regex, HttpRequestRouter::HandlerFu
if (!matched)
{
- ExpandedRegex.Append(Regex[i++]);
+ OutExpandedRegex.Append(Regex[i++]);
}
}
-
- m_Handlers.emplace_back(ExpandedRegex.c_str(), SupportedVerbs, std::move(HandlerFunc), Regex);
}
bool