From 2c825adc1d97661183225daa226f582c51bef64c Mon Sep 17 00:00:00 2001 From: jmsgrogan Date: Tue, 10 Jan 2023 09:28:15 +0000 Subject: [PATCH] Clean up win32 server example. --- .../test/TestBlochSphereNode.cpp | 1 + src/console/BasicWebApp.cpp | 28 +++ src/console/BasicWebApp.h | 11 + src/console/CMakeLists.txt | 8 +- src/console/MainApplication.cpp | 7 +- src/core/CMakeLists.txt | 2 + src/core/http/HttpHeader.cpp | 17 ++ src/core/http/HttpHeader.h | 8 +- src/core/http/HttpResponse.cpp | 25 ++- src/core/http/HttpResponse.h | 18 +- src/network/NetworkManager.cpp | 13 +- src/network/NetworkManager.h | 10 +- src/network/server/win32/Win32Buffer.cpp | 4 +- src/network/server/win32/Win32Buffer.h | 2 +- src/network/server/win32/Win32WebRequest.cpp | 49 +++++ src/network/server/win32/Win32WebRequest.h | 22 +- src/network/server/win32/Win32WebResponse.cpp | 50 +++-- src/network/server/win32/Win32WebResponse.h | 11 + src/network/server/win32/Win32WebServer.cpp | 188 ++++++++---------- src/network/server/win32/Win32WebServer.h | 8 +- src/network/web/HttpMessageHandler.cpp | 4 +- test/network/TestNetworkManagerClient.cpp | 2 +- test/network/TestWin32WebServer.cpp | 5 +- 23 files changed, 337 insertions(+), 156 deletions(-) create mode 100644 src/console/BasicWebApp.cpp create mode 100644 src/console/BasicWebApp.h diff --git a/plugins/quantum_computing/test/TestBlochSphereNode.cpp b/plugins/quantum_computing/test/TestBlochSphereNode.cpp index 564fd02..57ef710 100644 --- a/plugins/quantum_computing/test/TestBlochSphereNode.cpp +++ b/plugins/quantum_computing/test/TestBlochSphereNode.cpp @@ -7,6 +7,7 @@ #include "SvgConverter.h" #include "SvgWriter.h" +#include "SvgDocument.h" #include "File.h" diff --git a/src/console/BasicWebApp.cpp b/src/console/BasicWebApp.cpp new file mode 100644 index 0000000..75024bc --- /dev/null +++ b/src/console/BasicWebApp.cpp @@ -0,0 +1,28 @@ +#include "BasicWebApp.h" + +#include "FileLogger.h" + +HttpResponse BasicWebApp::onHttpRequest(const HttpRequest& request) +{ + const auto url = request.getPath(); + + HttpResponse response; + if (request.getVerb() == HttpRequest::Verb::GET) + { + MLOG_INFO("Got a GET request for: " << url); + response.setBody("Hey! You hit the server \r\n"); + response.setStatusCode(200); + response.setResponseReason("OK"); + } + else if (request.getVerb() == HttpRequest::Verb::POST) + { + MLOG_INFO("Got a POST request for: " << url); + } + else + { + MLOG_INFO("Got an unknown request for: " << url); + response.setStatusCode(503); + response.setResponseReason("Not Implemented"); + } + return response; +} \ No newline at end of file diff --git a/src/console/BasicWebApp.h b/src/console/BasicWebApp.h new file mode 100644 index 0000000..d76df22 --- /dev/null +++ b/src/console/BasicWebApp.h @@ -0,0 +1,11 @@ +#pragma once + +#include "AbstractWebApp.h" +#include "HttpRequest.h" +#include "HttpResponse.h" + +class BasicWebApp : public AbstractWebApp +{ +public: + HttpResponse onHttpRequest(const HttpRequest& request) override; +}; \ No newline at end of file diff --git a/src/console/CMakeLists.txt b/src/console/CMakeLists.txt index 5b1179c..e7556b0 100644 --- a/src/console/CMakeLists.txt +++ b/src/console/CMakeLists.txt @@ -1,6 +1,10 @@ -list(APPEND console_HEADERS MainApplication.h) +list(APPEND console_HEADERS + MainApplication.h + BasicWebApp.h) -list(APPEND console_LIB_INCLUDES MainApplication.cpp) +list(APPEND console_LIB_INCLUDES + BasicWebApp.cpp + MainApplication.cpp) add_library(console SHARED ${console_LIB_INCLUDES} ${console_HEADERS}) diff --git a/src/console/MainApplication.cpp b/src/console/MainApplication.cpp index 6dde651..c5673c8 100644 --- a/src/console/MainApplication.cpp +++ b/src/console/MainApplication.cpp @@ -13,6 +13,8 @@ #include "DiscretePoint.h" #include "Scene.h" +#include "BasicWebApp.h" + #include @@ -118,7 +120,8 @@ void MainApplication::run() void MainApplication::runServer() { - mNetworkManager->RunHttpServer(); + BasicWebApp web_app; + mNetworkManager->runHttpServer(&web_app); } void MainApplication::playAudio() @@ -151,7 +154,7 @@ void MainApplication::shutDown() if (mNetworkManager) { - mNetworkManager->ShutDown(); + mNetworkManager->shutDown(); } MLOG_INFO("Shut down"); diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt index 44b7916..1f4dd5b 100644 --- a/src/core/CMakeLists.txt +++ b/src/core/CMakeLists.txt @@ -14,6 +14,8 @@ list(APPEND core_HEADERS file_utilities/PathUtils.h StringUtils.h http/HttpResponse.h + http/HttpHeader.h + http/HttpRequest.h serializers/TomlReader.h ) diff --git a/src/core/http/HttpHeader.cpp b/src/core/http/HttpHeader.cpp index a3475c6..b273b8d 100644 --- a/src/core/http/HttpHeader.cpp +++ b/src/core/http/HttpHeader.cpp @@ -2,6 +2,23 @@ #include "StringUtils.h" +HttpHeader::HttpHeader() + : mContentType("text / html"), + mHttpVersion("1.1") +{ + +} + +std::string HttpHeader::getContentType() const +{ + return mContentType; +} + +std::string HttpHeader::getHttpVersion() const +{ + return mHttpVersion; +} + void HttpHeader::parse(const std::vector& message) { std::string tag; diff --git a/src/core/http/HttpHeader.h b/src/core/http/HttpHeader.h index e2b6610..d9b231d 100644 --- a/src/core/http/HttpHeader.h +++ b/src/core/http/HttpHeader.h @@ -7,10 +7,16 @@ class HttpHeader { public: + HttpHeader(); void parse(const std::vector& message); -private: + std::string getContentType() const; + std::string getHttpVersion() const; + +private: + std::string mHttpVersion; + std::string mContentType; std::string mHost; std::string mUserAgent; std::string mAccept; diff --git a/src/core/http/HttpResponse.cpp b/src/core/http/HttpResponse.cpp index ac904fe..da48a00 100644 --- a/src/core/http/HttpResponse.cpp +++ b/src/core/http/HttpResponse.cpp @@ -1,10 +1,8 @@ #include "HttpResponse.h" HttpResponse::HttpResponse() - : mHttpVersion("1.1"), - mStatusCode(200), + : mStatusCode(200), mResponseReason("OK"), - mContentType("text/plain"), mBody() { @@ -15,6 +13,11 @@ HttpResponse::~HttpResponse() } +const HttpHeader& HttpResponse::getHeader() const +{ + return mHeader; +} + unsigned short HttpResponse::getStatusCode() const { return mStatusCode; @@ -37,13 +40,13 @@ unsigned HttpResponse::getBodyLength() const std::string HttpResponse::getHeaderString() const { - std::string header = "HTTP/" + mHttpVersion + " " + std::to_string(mStatusCode) + " " + mResponseReason + "\n"; - header += "Content-Type: " + mContentType + "\n"; + std::string header = "HTTP/" + mHeader.getHttpVersion() + " " + std::to_string(mStatusCode) + " " + mResponseReason + "\n"; + header += "Content-Type: " + mHeader.getContentType() + "\n"; header += "Content-Length: " + std::to_string(getBodyLength()) + "\n"; return header; } -std::string HttpResponse::getResponseReason() const +const std::string& HttpResponse::getResponseReason() const { return mResponseReason; } @@ -52,3 +55,13 @@ std::string HttpResponse::toString() const { return getHeaderString() + "\n\n" + mBody; } + +void HttpResponse::setStatusCode(unsigned short code) +{ + mStatusCode = code; +} + +void HttpResponse::setResponseReason(const std::string& reason) +{ + mResponseReason = reason; +} diff --git a/src/core/http/HttpResponse.h b/src/core/http/HttpResponse.h index 0dd2675..667df70 100644 --- a/src/core/http/HttpResponse.h +++ b/src/core/http/HttpResponse.h @@ -1,5 +1,7 @@ #pragma once +#include "HttpHeader.h" + #include class HttpResponse @@ -9,25 +11,29 @@ public: ~HttpResponse(); - void setBody(const std::string& body); - unsigned getBodyLength() const; const std::string& getBody() const; + const HttpHeader& getHeader() const; + std::string getHeaderString() const; std::string toString() const; unsigned short getStatusCode() const; - std::string getResponseReason() const; + const std::string& getResponseReason() const; + + void setStatusCode(unsigned short code); + + void setResponseReason(const std::string& reason); + + void setBody(const std::string& body); private: + HttpHeader mHeader; unsigned short mStatusCode{ 200 }; std::string mResponseReason{ }; - - std::string mHttpVersion; - std::string mContentType; std::string mBody; }; diff --git a/src/network/NetworkManager.cpp b/src/network/NetworkManager.cpp index e2e3b96..61ea732 100644 --- a/src/network/NetworkManager.cpp +++ b/src/network/NetworkManager.cpp @@ -24,18 +24,19 @@ std::unique_ptr NetworkManager::Create() return std::make_unique(); } -void NetworkManager::Initialize() +void NetworkManager::initialize() { #ifdef __linux__ mSocketInterface = UnixSocketInterface::Create(); #endif } -void NetworkManager::RunHttpServer() +void NetworkManager::runHttpServer(AbstractWebApp* webApp) { #ifdef _WIN32 - Win32WebServer server; + Win32WebServer server(webApp); server.initialize(); + server.run(); #else if (!mSocketInterface) { @@ -49,11 +50,11 @@ void NetworkManager::RunHttpServer() #endif } -void NetworkManager::RunHttpClient() +void NetworkManager::runHttpClient() { if (!mSocketInterface) { - Initialize(); + initialize(); } if (!mSocketInterface) @@ -66,7 +67,7 @@ void NetworkManager::RunHttpClient() mSocketInterface->Write(socket, "Hello Friend"); } -void NetworkManager::ShutDown() +void NetworkManager::shutDown() { } diff --git a/src/network/NetworkManager.h b/src/network/NetworkManager.h index dcd0043..33b8fef 100644 --- a/src/network/NetworkManager.h +++ b/src/network/NetworkManager.h @@ -6,6 +6,8 @@ #include #include +class AbstractWebApp; + class NetworkManager { public: @@ -16,13 +18,13 @@ public: static std::unique_ptr Create(); - void Initialize(); + void initialize(); - void RunHttpServer(); + void runHttpServer(AbstractWebApp* webApp); - void RunHttpClient(); + void runHttpClient(); - void ShutDown(); + void shutDown(); private: std::vector mActiveSockets; diff --git a/src/network/server/win32/Win32Buffer.cpp b/src/network/server/win32/Win32Buffer.cpp index 0588160..01fc51d 100644 --- a/src/network/server/win32/Win32Buffer.cpp +++ b/src/network/server/win32/Win32Buffer.cpp @@ -21,9 +21,9 @@ Win32Buffer::~Win32Buffer() clearBuffer(); } -PUCHAR Win32Buffer::getBufferAsUChar() const +unsigned char* Win32Buffer::getBufferAsUChar() const { - return reinterpret_cast(mBuffer); + return reinterpret_cast(mBuffer); } void* Win32Buffer::getBuffer() const diff --git a/src/network/server/win32/Win32Buffer.h b/src/network/server/win32/Win32Buffer.h index 142e02c..86178a3 100644 --- a/src/network/server/win32/Win32Buffer.h +++ b/src/network/server/win32/Win32Buffer.h @@ -9,7 +9,7 @@ public: void* getBuffer() const; - PUCHAR getBufferAsUChar() const; + unsigned char* getBufferAsUChar() const; bool isValid() const; diff --git a/src/network/server/win32/Win32WebRequest.cpp b/src/network/server/win32/Win32WebRequest.cpp index fe6f437..3042ef8 100644 --- a/src/network/server/win32/Win32WebRequest.cpp +++ b/src/network/server/win32/Win32WebRequest.cpp @@ -2,6 +2,9 @@ #include "StringUtils.h" #include "HttpRequest.h" +#include "FileLogger.h" + +#include "Win32TempFile.h" Win32WebRequest::Win32WebRequest() : mBuffer(DEFAULT_BUFFER_SIZE) @@ -55,8 +58,10 @@ HttpRequest Win32WebRequest::getRequest() const { case HttpVerbGET: verb = HttpRequest::Verb::GET; + break; case HttpVerbPOST: verb = HttpRequest::Verb::POST; + break; default: verb = HttpRequest::Verb::UNKNOWN; break; @@ -64,4 +69,48 @@ HttpRequest Win32WebRequest::getRequest() const HttpRequest request(verb, getUrlFromRequest()); return request; +} + +bool Win32WebRequest::startReceiveEntity() +{ + mEntityBuffer = std::make_unique(ENTITY_BUFFER_SIZE); + if (!mEntityBuffer->isValid()) + { + MLOG_ERROR("Failed to allocate entity buffer"); + return false; + } + + mTempFile = std::make_unique(); + if (!mTempFile->isValid()) + { + MLOG_ERROR("Failed to create tempfile"); + return false; + } + return true; +} + +Win32Buffer* Win32WebRequest::getEntityBuffer() const +{ + return mEntityBuffer.get(); +} + +unsigned Win32WebRequest::getEntityBufferSize() const +{ + return ENTITY_BUFFER_SIZE; +} + +Win32TempFile* Win32WebRequest::getTempFile() const +{ + return mTempFile.get(); +} + +void Win32WebRequest::flushEntityBuffer(unsigned numBytes) +{ + mEntityTotalSize += numBytes; + mTempFile->write(mEntityBuffer->getBufferAsUChar(), numBytes); +} + +unsigned Win32WebRequest::getEntityTotalSize() const +{ + return mEntityTotalSize; } \ No newline at end of file diff --git a/src/network/server/win32/Win32WebRequest.h b/src/network/server/win32/Win32WebRequest.h index 745cb46..cd5a75e 100644 --- a/src/network/server/win32/Win32WebRequest.h +++ b/src/network/server/win32/Win32WebRequest.h @@ -14,31 +14,49 @@ #include #include +#include #include "Win32Buffer.h" class HttpRequest; +class Win32TempFile; class Win32WebRequest { public: Win32WebRequest(); - bool isValid() const; + HttpRequest getRequest() const; PHTTP_REQUEST getHandle() const; unsigned getBufferSize() const; + Win32Buffer* getEntityBuffer() const; + + unsigned getEntityBufferSize() const; + + unsigned getEntityTotalSize() const; + + void flushEntityBuffer(unsigned numBytes); + + Win32TempFile* getTempFile() const; + + bool isValid() const; + void resizeBuffer(unsigned size); void zeroBufferMemory(); - HttpRequest getRequest() const; + bool startReceiveEntity(); private: std::string getUrlFromRequest() const; + static const unsigned ENTITY_BUFFER_SIZE{ 2048 }; + std::unique_ptr mEntityBuffer; + std::unique_ptr mTempFile; + unsigned mEntityTotalSize{ 0 }; static const unsigned DEFAULT_BUFFER_SIZE{ sizeof(HTTP_REQUEST) + 2048 }; Win32Buffer mBuffer; diff --git a/src/network/server/win32/Win32WebResponse.cpp b/src/network/server/win32/Win32WebResponse.cpp index be29164..d9a2162 100644 --- a/src/network/server/win32/Win32WebResponse.cpp +++ b/src/network/server/win32/Win32WebResponse.cpp @@ -1,34 +1,60 @@ #include "Win32WebResponse.h" #include "HttpResponse.h" +#include "Win32WebRequest.h" + +#include "FileLogger.h" Win32WebResponse::Win32WebResponse(const HttpResponse& response) { RtlZeroMemory((&mResponse), sizeof(*(&mResponse))); + + mResponse.StatusCode = response.getStatusCode(); - std::string reason = response.getResponseReason(); - mResponse.pReason = reason.c_str(); - mResponse.ReasonLength = (USHORT)strlen(reason.c_str()); + mResponseReason = response.getResponseReason(); + mResponse.pReason = mResponseReason.c_str(); + mResponse.ReasonLength = (USHORT)strlen(mResponseReason.c_str()); - const std::string content_type = "text / html"; - mResponse.Headers.KnownHeaders[HttpHeaderContentType].pRawValue = content_type.c_str(); - mResponse.Headers.KnownHeaders[HttpHeaderContentType].RawValueLength = (USHORT)strlen(content_type.c_str()); + populateHeader(response); - auto body = response.getBody(); - if (!body.empty()) + populateBody(response); +} + +HTTP_RESPONSE& Win32WebResponse::getResponse() +{ + return mResponse; +} + +void Win32WebResponse::populateBody(const HttpResponse& response) +{ + mBody = response.getBody(); + if (!mBody.empty()) { + mContentLength = std::to_string(mBody.size()); + mResponse.Headers.KnownHeaders[HttpHeaderContentLength].pRawValue = mContentLength.c_str(); + mResponse.Headers.KnownHeaders[HttpHeaderContentLength].RawValueLength = (USHORT)strlen(mContentLength.c_str()); + HTTP_DATA_CHUNK dataChunk; dataChunk.DataChunkType = HttpDataChunkFromMemory; - dataChunk.FromMemory.pBuffer = body.data(); - dataChunk.FromMemory.BufferLength = (ULONG)strlen(body.data()); + dataChunk.FromMemory.pBuffer = mBody.data(); + dataChunk.FromMemory.BufferLength = (ULONG)strlen(mBody.data()); mResponse.EntityChunkCount = 1; mResponse.pEntityChunks = &dataChunk; } } -HTTP_RESPONSE& Win32WebResponse::getResponse() +void Win32WebResponse::populateHeader(const HttpResponse& response) { - return mResponse; + mContentType = response.getHeader().getContentType(); + mResponse.Headers.KnownHeaders[HttpHeaderContentType].pRawValue = mContentType.c_str(); + mResponse.Headers.KnownHeaders[HttpHeaderContentType].RawValueLength = (USHORT)strlen(mContentType.c_str()); +} + +void Win32WebResponse::addRequestContentLength(const Win32WebRequest& request) +{ + mContentLength = std::to_string(request.getEntityTotalSize()); + mResponse.Headers.KnownHeaders[HttpHeaderContentLength].pRawValue = mContentLength.c_str(); + mResponse.Headers.KnownHeaders[HttpHeaderContentLength].RawValueLength = (USHORT)strlen(mContentLength.c_str()); } \ No newline at end of file diff --git a/src/network/server/win32/Win32WebResponse.h b/src/network/server/win32/Win32WebResponse.h index 16c6831..feaf64a 100644 --- a/src/network/server/win32/Win32WebResponse.h +++ b/src/network/server/win32/Win32WebResponse.h @@ -17,6 +17,7 @@ #include class HttpResponse; +class Win32WebRequest; class Win32WebResponse { @@ -25,6 +26,16 @@ public: HTTP_RESPONSE& getResponse(); + void addRequestContentLength(const Win32WebRequest& request); + private: + void populateBody(const HttpResponse& response); + void populateHeader(const HttpResponse& response); + + std::string mResponseReason; + std::string mContentType; + std::string mBody; + + std::string mContentLength; HTTP_RESPONSE mResponse; }; \ No newline at end of file diff --git a/src/network/server/win32/Win32WebServer.cpp b/src/network/server/win32/Win32WebServer.cpp index b36ff75..d6478d2 100644 --- a/src/network/server/win32/Win32WebServer.cpp +++ b/src/network/server/win32/Win32WebServer.cpp @@ -12,7 +12,7 @@ #include "StringUtils.h" Win32WebServer::Win32WebServer(AbstractWebApp* webApp) - : mListenUrl("http://localhost:80/49152"), + : mListenUrl("http://localhost:49153/"), mWebApp(webApp) { @@ -64,19 +64,66 @@ void Win32WebServer::initialize() } } -DWORD Win32WebServer::onRequest(const Win32WebRequest& request) +bool Win32WebServer::onPostRequest(Win32WebRequest& request) { - auto app_request = request.getRequest(); - auto response = mWebApp->onHttpRequest(app_request); + if (request.getHandle()->Flags & HTTP_REQUEST_FLAG_MORE_ENTITY_BODY_EXISTS) + { + if (!request.startReceiveEntity()) + { + return false; + } - DWORD result; + ULONG bytes_read = 0; + do + { + bytes_read = 0; + auto result = ::HttpReceiveRequestEntityBody(mWorkingQueue, request.getHandle()->RequestId, 0, request.getEntityBuffer()->getBuffer(), + request.getEntityBufferSize(), &bytes_read, nullptr); + + if (result == NO_ERROR || result == ERROR_HANDLE_EOF) + { + request.flushEntityBuffer(bytes_read); + if (result == ERROR_HANDLE_EOF) + { + return true; + } + } + else + { + MLOG_ERROR("HttpReceiveRequestEntityBody failed with: " << result); + return false; + } + } while (true); + } + return true; + +} + +bool Win32WebServer::onRequest(Win32WebRequest& request) +{ + if (request.getHandle()->Verb == HttpVerbPOST) + { + if (!onPostRequest(request)) + { + return false; + } + } + + const auto app_request = request.getRequest(); + const auto response = mWebApp->onHttpRequest(app_request); if (app_request.getVerb() == HttpRequest::Verb::POST) { - result = sendHttpPostResponse(request.getHandle()); + if (!sendHttpPostResponse(request, response)) + { + return false; + } } else { - result = sendHttpResponse(request.getHandle(), response); + if (!sendHttpResponse(request, response)) + { + return false; + } } /* @@ -94,123 +141,57 @@ DWORD Win32WebServer::onRequest(const Win32WebRequest& request) break; */ - return result; + return true; } -DWORD Win32WebServer::sendHttpResponse(PHTTP_REQUEST pRequest, const HttpResponse& appResponse) +bool Win32WebServer::sendHttpResponse(const Win32WebRequest& request, const HttpResponse& appResponse) { Win32WebResponse response(appResponse); DWORD bytesSent; - const auto result = ::HttpSendHttpResponse(mWorkingQueue, pRequest->RequestId, 0, &(response.getResponse()), NULL, &bytesSent, NULL, 0, NULL, NULL); + const auto result = ::HttpSendHttpResponse(mWorkingQueue, request.getHandle()->RequestId, 0, &(response.getResponse()), NULL, &bytesSent, NULL, 0, NULL, NULL); if (result != NO_ERROR) { MLOG_ERROR("Http response failed with error: " << result); } - return result; + return result == NO_ERROR; } -#define MAX_ULONG_STR ((ULONG) sizeof("4294967295")) - -DWORD Win32WebServer::sendHttpPostResponse(PHTTP_REQUEST pRequest) +bool Win32WebServer::sendHttpPostResponse(const Win32WebRequest& request, const HttpResponse& appResponse) { - // Allocate space for an entity buffer. Buffer can be increased on demand. - const ULONG entity_buffer_length = 2048; - - Win32Buffer entity_buffer(entity_buffer_length); - if (!entity_buffer.isValid()) - { - return ERROR_NOT_ENOUGH_MEMORY; - } - - HTTP_RESPONSE response; - initializeHttpResponse(response, 200, "OK"); - DWORD result{ 0 }; - if (pRequest->Flags & HTTP_REQUEST_FLAG_MORE_ENTITY_BODY_EXISTS) + if (request.getEntityBuffer()) { - Win32TempFile temp_file; - if (!temp_file.isValid()) - { - return 0; - } + Win32WebResponse response(appResponse); + response.addRequestContentLength(request); - ULONG total_bytes_read = 0; - ULONG bytes_read = 0; - do - { - // Read the entity chunk from the request. - bytes_read = 0; - result = ::HttpReceiveRequestEntityBody(mWorkingQueue, pRequest->RequestId, 0, entity_buffer.getBuffer(), entity_buffer_length, &bytes_read, nullptr); - - switch (result) - { - case NO_ERROR: - if (bytes_read != 0) - { - total_bytes_read += bytes_read; - temp_file.write(entity_buffer.getBufferAsUChar(), bytes_read); - } - break; - case ERROR_HANDLE_EOF: - // The last request entity body has been read. Send back a response. - // - // To illustrate entity sends via HttpSendResponseEntityBody, the response will - // be sent over multiple calls. To do this, pass the HTTP_SEND_RESPONSE_FLAG_MORE_DATA flag. - - if (bytes_read != 0) - { - total_bytes_read += bytes_read; - temp_file.write(entity_buffer.getBufferAsUChar(), bytes_read); - } - - // Because the response is sent over multiple API calls, add a content-length. - // Alternatively, the response could have been sent using chunked transfer encoding, by passimg "Transfer-Encoding: Chunked". - // NOTE: Because the TotalBytesread in a ULONG are accumulated, this will not work for entity bodies larger than 4 GB. - // For support of large entity bodies, use a ULONGLONG. - CHAR szContentLength[MAX_ULONG_STR]; - sprintf_s(szContentLength, MAX_ULONG_STR, "%lu", total_bytes_read); - response.Headers.KnownHeaders[HttpHeaderContentLength].pRawValue = szContentLength; - response.Headers.KnownHeaders[HttpHeaderContentLength].RawValueLength = (USHORT)strlen(szContentLength); - - DWORD bytesSent; - result = ::HttpSendHttpResponse(mWorkingQueue, pRequest->RequestId, HTTP_SEND_RESPONSE_FLAG_MORE_DATA, &response, NULL, &bytesSent, NULL, 0, NULL, NULL); - if (result != NO_ERROR) - { - MLOG_ERROR("HttpSendHttpResponse failed with: " << result); - return; - } - - // Send entity body from a file handle. - HTTP_DATA_CHUNK dataChunk; - dataChunk.DataChunkType = HttpDataChunkFromFileHandle; - dataChunk.FromFileHandle.ByteRange.StartingOffset.QuadPart = 0; - dataChunk.FromFileHandle.ByteRange.Length.QuadPart = HTTP_BYTE_RANGE_TO_EOF; - dataChunk.FromFileHandle.FileHandle = temp_file.getHandle(); - - result = ::HttpSendResponseEntityBody(mWorkingQueue, pRequest->RequestId, 0, 1, &dataChunk, NULL, NULL, 0, NULL, NULL); - if (result != NO_ERROR) - { - MLOG_ERROR("HttpSendResponseEntityBody failed" << result); - } - break; - default: - MLOG_ERROR("HttpReceiveRequestEntityBody failed with: " << result); - break; - } - - } while (true); - } - else - { DWORD bytesSent; - result = ::HttpSendHttpResponse(mWorkingQueue, pRequest->RequestId, 0, &response, NULL, &bytesSent, NULL, 0, NULL, NULL ); + result = ::HttpSendHttpResponse(mWorkingQueue, request.getHandle()->RequestId, HTTP_SEND_RESPONSE_FLAG_MORE_DATA, &(response.getResponse()), NULL, &bytesSent, NULL, 0, NULL, NULL); if (result != NO_ERROR) { MLOG_ERROR("HttpSendHttpResponse failed with: " << result); + return false; + } + + // Send entity body from a file handle. + HTTP_DATA_CHUNK dataChunk; + dataChunk.DataChunkType = HttpDataChunkFromFileHandle; + dataChunk.FromFileHandle.ByteRange.StartingOffset.QuadPart = 0; + dataChunk.FromFileHandle.ByteRange.Length.QuadPart = HTTP_BYTE_RANGE_TO_EOF; + dataChunk.FromFileHandle.FileHandle = request.getTempFile()->getHandle(); + + result = ::HttpSendResponseEntityBody(mWorkingQueue, request.getHandle()->RequestId, 0, 1, &dataChunk, NULL, NULL, 0, NULL, NULL); + if (result != NO_ERROR) + { + MLOG_ERROR("HttpSendResponseEntityBody failed" << result); + return false; } } - return result; + else + { + result = sendHttpResponse(request, appResponse); + } + return result == NO_ERROR;; } void Win32WebServer::run() @@ -232,8 +213,7 @@ void Win32WebServer::run() auto result = ::HttpReceiveHttpRequest(mWorkingQueue, request_id, 0, request.getHandle(), request.getBufferSize(), &bytes_read, nullptr); if (NO_ERROR == result) { - result = onRequest(request); - if (result != NO_ERROR) + if (!onRequest(request)) { break; } diff --git a/src/network/server/win32/Win32WebServer.h b/src/network/server/win32/Win32WebServer.h index 8aba70e..df34cf5 100644 --- a/src/network/server/win32/Win32WebServer.h +++ b/src/network/server/win32/Win32WebServer.h @@ -18,7 +18,6 @@ class AbstractWebApp; class Win32WebRequest; - class HttpResponse; class Win32WebServer @@ -35,10 +34,11 @@ public: void run(); private: - DWORD onRequest(const Win32WebRequest& request); + bool onRequest(Win32WebRequest& request); + bool onPostRequest(Win32WebRequest& request); - DWORD sendHttpResponse(PHTTP_REQUEST pRequest, const HttpResponse& response); - DWORD sendHttpPostResponse(PHTTP_REQUEST pRequest); + bool sendHttpResponse(const Win32WebRequest& request, const HttpResponse& response); + bool sendHttpPostResponse(const Win32WebRequest& request, const HttpResponse& response); AbstractWebApp* mWebApp{ nullptr }; diff --git a/src/network/web/HttpMessageHandler.cpp b/src/network/web/HttpMessageHandler.cpp index a3ca4ff..e664423 100644 --- a/src/network/web/HttpMessageHandler.cpp +++ b/src/network/web/HttpMessageHandler.cpp @@ -9,9 +9,9 @@ std::string HttpMessageHandler::onMessage(const std::string& message) request.parseMessage(message); HttpResponse response; - response.SetBody("Hello world!"); + response.setBody("Hello world!"); - const auto response_message = response.ToString(); + const auto response_message = response.toString(); return response_message; } diff --git a/test/network/TestNetworkManagerClient.cpp b/test/network/TestNetworkManagerClient.cpp index 3a49624..d8a4e7f 100644 --- a/test/network/TestNetworkManagerClient.cpp +++ b/test/network/TestNetworkManagerClient.cpp @@ -8,5 +8,5 @@ TEST_CASE(TestNetworkManagerClient, "network") { auto network_manager = NetworkManager::Create(); - network_manager->RunHttpClient(); + network_manager->runHttpClient(); } diff --git a/test/network/TestWin32WebServer.cpp b/test/network/TestWin32WebServer.cpp index c0d1da9..6b9c529 100644 --- a/test/network/TestWin32WebServer.cpp +++ b/test/network/TestWin32WebServer.cpp @@ -2,9 +2,12 @@ #include "TestFramework.h" +#include "BasicWebApp.h" + TEST_CASE(TestWin32WebServer, "network") { auto network_manager = NetworkManager::Create(); - network_manager->RunHttpServer(); + BasicWebApp web_app; + network_manager->runHttpServer(&web_app); }