diff options
| author | Zousar Shaker <[email protected]> | 2021-11-25 14:24:37 -0700 |
|---|---|---|
| committer | Zousar Shaker <[email protected]> | 2021-11-25 14:24:37 -0700 |
| commit | 81dac5b9548d5f300d3a504b0db8a3623a65d2e5 (patch) | |
| tree | 6e3fb718b79d4c6dcfcea0cc89368b2283d1e315 | |
| parent | Fix asio request routing so that a url of "/cas" will route to the service fo... (diff) | |
| download | zen-81dac5b9548d5f300d3a504b0db8a3623a65d2e5.tar.xz zen-81dac5b9548d5f300d3a504b0db8a3623a65d2e5.zip | |
Fix handling of packages/offers in asio mode to match http.sys mode.
| -rw-r--r-- | zenhttp/httpasio.cpp | 7 | ||||
| -rw-r--r-- | zenhttp/httpserver.cpp | 79 | ||||
| -rw-r--r-- | zenhttp/httpsys.cpp | 79 | ||||
| -rw-r--r-- | zenhttp/include/zenhttp/httpserver.h | 2 |
4 files changed, 91 insertions, 76 deletions
diff --git a/zenhttp/httpasio.cpp b/zenhttp/httpasio.cpp index ad0f7fefa..c9432d197 100644 --- a/zenhttp/httpasio.cpp +++ b/zenhttp/httpasio.cpp @@ -318,6 +318,7 @@ private: std::unique_ptr<asio::ip::tcp::socket> m_Socket; std::atomic<uint32_t> m_RequestCounter{0}; uint32_t m_ConnectionId = 0; + Ref<IHttpPackageHandler> m_PackageHandler; RwLock m_ResponsesLock; std::deque<std::unique_ptr<HttpResponse>> m_Responses; @@ -485,9 +486,13 @@ HttpServerConnection::HandleRequest() { HttpAsioServerRequest Request(m_RequestData, *Service, m_RequestData.Body()); + ZEN_TRACE("handle request, connection '{}' request '{}'", m_ConnectionId, m_RequestCounter.load(std::memory_order_relaxed)); - Service->HandleRequest(Request); + if (!HandlePackageOffers(*Service, Request, m_PackageHandler)) + { + Service->HandleRequest(Request); + } if (std::unique_ptr<HttpResponse> Response = std::move(Request.m_Response)) { diff --git a/zenhttp/httpserver.cpp b/zenhttp/httpserver.cpp index f40836c4a..dcf0a2765 100644 --- a/zenhttp/httpserver.cpp +++ b/zenhttp/httpserver.cpp @@ -7,6 +7,7 @@ #include "httpsys.h" #include <zencore/compactbinary.h> +#include <zencore/compactbinarybuilder.h> #include <zencore/compactbinarypackage.h> #include <zencore/iobuffer.h> #include <zencore/logging.h> @@ -657,6 +658,84 @@ TEST_CASE("http.common") } } +bool +HandlePackageOffers(HttpService& Service, HttpServerRequest& Request, Ref<IHttpPackageHandler>& PackageHandlerRef) +{ + if (Request.RequestVerb() == HttpVerb::kPost) + { + if (Request.RequestContentType() == HttpContentType::kCbPackageOffer) + { + // The client is presenting us with a package attachments offer, we need + // to filter it down to the list of attachments we need them to send in + // the follow-up request + + PackageHandlerRef = Service.HandlePackageRequest(Request); + + if (PackageHandlerRef) + { + CbObject OfferMessage = LoadCompactBinaryObject(Request.ReadPayload()); + + std::vector<IoHash> OfferCids; + + for (auto& CidEntry : OfferMessage["offer"]) + { + if (!CidEntry.IsHash()) + { + // Should yield bad request response? + + ZEN_WARN("found invalid entry in offer"); + + continue; + } + + OfferCids.push_back(CidEntry.AsHash()); + } + + ZEN_TRACE("request #{} -> filtering offer of {} entries", Request.RequestId(), OfferCids.size()); + + PackageHandlerRef->FilterOffer(OfferCids); + + ZEN_TRACE("request #{} -> filtered to {} entries", Request.RequestId(), OfferCids.size()); + + CbObjectWriter ResponseWriter; + ResponseWriter.BeginArray("need"); + + for (const IoHash& Cid : OfferCids) + { + ResponseWriter.AddHash(Cid); + } + + ResponseWriter.EndArray(); + + // Emit filter response + Request.WriteResponse(HttpResponseCode::OK, ResponseWriter.Save()); + return true; + } + } + else if (Request.RequestContentType() == HttpContentType::kCbPackage) + { + // Process chunks in package request + + PackageHandlerRef = Service.HandlePackageRequest(Request); + + // TODO: this should really be done in a streaming fashion, currently this emulates + // the intended flow from an API perspective + + if (PackageHandlerRef) + { + PackageHandlerRef->OnRequestBegin(); + + auto CreateBuffer = [&](const IoHash& Cid, uint64_t Size) -> IoBuffer { return PackageHandlerRef->CreateTarget(Cid, Size); }; + + CbPackage Package = ParsePackageMessage(Request.ReadPayload(), CreateBuffer); + + PackageHandlerRef->OnRequestComplete(); + } + } + } + return false; +} + void http_forcelink() { diff --git a/zenhttp/httpsys.cpp b/zenhttp/httpsys.cpp index cdf9e0a39..15d7a9700 100644 --- a/zenhttp/httpsys.cpp +++ b/zenhttp/httpsys.cpp @@ -1131,83 +1131,12 @@ HttpSysTransaction::InvokeRequestHandler(HttpService& Service, IoBuffer Payload) { HttpSysServerRequest& ThisRequest = m_HandlerRequest.emplace(*this, Service, Payload); - if (ThisRequest.RequestVerb() == HttpVerb::kPost) - { - if (ThisRequest.RequestContentType() == HttpContentType::kCbPackageOffer) - { - // The client is presenting us with a package attachments offer, we need - // to filter it down to the list of attachments we need them to send in - // the follow-up request - - m_PackageHandler = Service.HandlePackageRequest(ThisRequest); - - if (m_PackageHandler) - { - CbObject OfferMessage = LoadCompactBinaryObject(Payload); - - std::vector<IoHash> OfferCids; - - for (auto& CidEntry : OfferMessage["offer"]) - { - if (!CidEntry.IsHash()) - { - // Should yield bad request response? - - ZEN_WARN("found invalid entry in offer"); - - continue; - } - - OfferCids.push_back(CidEntry.AsHash()); - } - - ZEN_TRACE("request #{} -> filtering offer of {} entries", ThisRequest.RequestId(), OfferCids.size()); - - m_PackageHandler->FilterOffer(OfferCids); - - ZEN_TRACE("request #{} -> filtered to {} entries", ThisRequest.RequestId(), OfferCids.size()); - - CbObjectWriter ResponseWriter; - ResponseWriter.BeginArray("need"); - - for (const IoHash& Cid : OfferCids) - { - ResponseWriter.AddHash(Cid); - } - - ResponseWriter.EndArray(); - - // Emit filter response - ThisRequest.WriteResponse(HttpResponseCode::OK, ResponseWriter.Save()); - - return ThisRequest; - } - } - else if (ThisRequest.RequestContentType() == HttpContentType::kCbPackage) - { - // Process chunks in package request - - m_PackageHandler = Service.HandlePackageRequest(ThisRequest); - - // TODO: this should really be done in a streaming fashion, currently this emulates - // the intended flow from an API perspective - - if (m_PackageHandler) - { - m_PackageHandler->OnRequestBegin(); - - auto CreateBuffer = [&](const IoHash& Cid, uint64_t Size) -> IoBuffer { return m_PackageHandler->CreateTarget(Cid, Size); }; - - CbPackage Package = ParsePackageMessage(ThisRequest.ReadPayload(), CreateBuffer); - - m_PackageHandler->OnRequestComplete(); - } - } - } - // Default request handling - Service.HandleRequest(ThisRequest); + if (!HandlePackageOffers(Service, ThisRequest, m_PackageHandler)) + { + Service.HandleRequest(ThisRequest); + } return ThisRequest; } diff --git a/zenhttp/include/zenhttp/httpserver.h b/zenhttp/include/zenhttp/httpserver.h index 93ba452c7..088028081 100644 --- a/zenhttp/include/zenhttp/httpserver.h +++ b/zenhttp/include/zenhttp/httpserver.h @@ -269,6 +269,8 @@ private: std::unordered_map<std::string, std::string> m_PatternMap; }; +bool HandlePackageOffers(HttpService& Service, HttpServerRequest& Request, Ref<IHttpPackageHandler>& PackageHandlerRef); + void http_forcelink(); // internal } // namespace zen |