diff options
| author | Martin Ridgers <[email protected]> | 2021-09-15 09:22:32 +0200 |
|---|---|---|
| committer | Martin Ridgers <[email protected]> | 2021-09-15 09:23:33 +0200 |
| commit | 8f5e773529858223beeecf5d1b69c23991df644e (patch) | |
| tree | 2c360c67e028f5ecd7368212b0adf8b23578ff9d /zenhttp/httpclient.cpp | |
| parent | Use zen::Sleep() in timer.cpp's tests (diff) | |
| parent | Updated function service to new package management API (diff) | |
| download | zen-8f5e773529858223beeecf5d1b69c23991df644e.tar.xz zen-8f5e773529858223beeecf5d1b69c23991df644e.zip | |
Merge main
Diffstat (limited to 'zenhttp/httpclient.cpp')
| -rw-r--r-- | zenhttp/httpclient.cpp | 158 |
1 files changed, 158 insertions, 0 deletions
diff --git a/zenhttp/httpclient.cpp b/zenhttp/httpclient.cpp new file mode 100644 index 000000000..b7df12026 --- /dev/null +++ b/zenhttp/httpclient.cpp @@ -0,0 +1,158 @@ +// Copyright Epic Games, Inc. All Rights Reserved. + +#include <zenhttp/httpclient.h> +#include <zenhttp/httpserver.h> + +#include <zencore/compactbinarybuilder.h> +#include <zencore/compactbinarypackage.h> +#include <zencore/iobuffer.h> +#include <zencore/logging.h> +#include <zencore/sharedbuffer.h> +#include <zencore/stream.h> + +#include "httpshared.h" + +#include <doctest/doctest.h> + +static std::atomic<uint32_t> HttpClientRequestIdCounter{0}; + +namespace zen { + +using namespace std::literals; + +HttpClient::Response +FromCprResponse(cpr::Response& InResponse) +{ + return {.StatusCode = InResponse.status_code}; +} + +////////////////////////////////////////////////////////////////////////// + +HttpClient::HttpClient(std::string_view BaseUri) : m_BaseUri(BaseUri) +{ +} + +HttpClient::~HttpClient() +{ +} + +HttpClient::Response +HttpClient::TransactPackage(std::string_view Url, CbPackage Package) +{ + cpr::Session Sess; + Sess.SetUrl(m_BaseUri + std::string(Url)); + + // First, list of offered chunks for filtering on the server end + + std::vector<IoHash> AttachmentsToSend; + std::span<const CbAttachment> Attachments = Package.GetAttachments(); + + const uint32_t RequestId = ++HttpClientRequestIdCounter; + auto RequestIdString = fmt::to_string(RequestId); + + if (Attachments.empty() == false) + { + CbObjectWriter Writer; + Writer.BeginArray("offer"); + + for (const CbAttachment& Attachment : Attachments) + { + IoHash Hash = Attachment.GetHash(); + + Writer.AddHash(Hash); + } + + Writer.EndArray(); + + MemoryOutStream MemOut; + BinaryWriter MemWriter(MemOut); + Writer.Save(MemWriter); + + Sess.SetHeader( + {{"Content-Type", "application/x-ue-offer"}, {"UE-Session", "123456789012345678901234"}, {"UE-Request", RequestIdString}}); + Sess.SetBody(cpr::Body{(const char*)MemOut.Data(), MemOut.Size()}); + + cpr::Response FilterResponse = Sess.Post(); + + if (FilterResponse.status_code == 200) + { + IoBuffer ResponseBuffer(IoBuffer::Wrap, FilterResponse.text.data(), FilterResponse.text.size()); + CbObject ResponseObject = LoadCompactBinaryObject(ResponseBuffer); + + for (auto& Entry : ResponseObject["need"]) + { + ZEN_ASSERT(Entry.IsHash()); + AttachmentsToSend.push_back(Entry.AsHash()); + } + } + } + + // Prepare package for send + + CbPackage SendPackage; + SendPackage.SetObject(Package.GetObject(), Package.GetObjectHash()); + + for (const IoHash& AttachmentCid : AttachmentsToSend) + { + const CbAttachment* Attachment = Package.FindAttachment(AttachmentCid); + + if (Attachment) + { + SendPackage.AddAttachment(*Attachment); + } + else + { + // This should be an error -- server asked to have something we can't find + } + } + + // Transmit package payload + + CompositeBuffer Message = FormatPackageMessageBuffer(SendPackage); + SharedBuffer FlatMessage = Message.Flatten(); + + Sess.SetHeader( + {{"Content-Type", "application/x-ue-cbpkg"}, {"UE-Session", "123456789012345678901234"}, {"UE-Request", RequestIdString}}); + Sess.SetBody(cpr::Body{(const char*)FlatMessage.GetData(), FlatMessage.GetSize()}); + + cpr::Response FilterResponse = Sess.Post(); + + if (!IsHttpSuccessCode(FilterResponse.status_code)) + { + return FromCprResponse(FilterResponse); + } + + IoBuffer ResponseBuffer(IoBuffer::Clone, FilterResponse.text.data(), FilterResponse.text.size()); + + if (auto It = FilterResponse.header.find("Content-Type"); It != FilterResponse.header.end()) + { + HttpContentType ContentType = ParseContentType(It->second); + + ResponseBuffer.SetContentType(ContentType); + } + + return {.StatusCode = FilterResponse.status_code, .ResponsePayload = ResponseBuffer}; +} + +HttpClient::Response +HttpClient::Delete(std::string_view Url) +{ + ZEN_UNUSED(Url); + return {}; +} + +////////////////////////////////////////////////////////////////////////// + +TEST_CASE("httpclient") +{ + using namespace std::literals; + + SUBCASE("client") {} +} + +void +httpclient_forcelink() +{ +} + +} // namespace zen |