diff options
| author | Stefan Boberg <[email protected]> | 2021-09-02 13:02:19 +0200 |
|---|---|---|
| committer | Stefan Boberg <[email protected]> | 2021-09-02 13:02:19 +0200 |
| commit | 6e28d78ff51bc2078830ef495cb0e27e8a868794 (patch) | |
| tree | aabf1ea25b3eb42c523c0a5aa35de34b3d920db5 /zencore/httpserver.cpp | |
| parent | Introduced support for compressed buffer attachments (diff) | |
| download | zen-6e28d78ff51bc2078830ef495cb0e27e8a868794.tar.xz zen-6e28d78ff51bc2078830ef495cb0e27e8a868794.zip | |
Initial implementation of CbPackage HTTP response writing
Diffstat (limited to 'zencore/httpserver.cpp')
| -rw-r--r-- | zencore/httpserver.cpp | 107 |
1 files changed, 68 insertions, 39 deletions
diff --git a/zencore/httpserver.cpp b/zencore/httpserver.cpp index eaa8bdfcd..587eab279 100644 --- a/zencore/httpserver.cpp +++ b/zencore/httpserver.cpp @@ -273,49 +273,78 @@ HttpServerRequest::~HttpServerRequest() void HttpServerRequest::WriteResponse(HttpResponse HttpResponseCode, CbPackage Data) { - // TODO: implement efficient version of this which can send package attachment - // payloads directly from disk - ZEN_UNUSED(HttpResponseCode, Data); - ZEN_NOT_IMPLEMENTED(); + const std::span<const CbAttachment>& Attachments = Data.GetAttachments(); + + struct CbPackageHeader + { + uint32_t HeaderMagic; + uint32_t AttachmentCount; + uint32_t Reserved1; + uint32_t Reserved2; + }; + + static constinit uint32_t kMagic = 0xaa77aacc; + + struct CbAttachmentEntry + { + uint64_t AttachmentSize; + uint32_t Reserved1; + IoHash AttachmentHash; + }; + + std::vector<IoBuffer> ResponseBuffers; + ResponseBuffers.reserve(3 + Attachments.size()); // TODO: may want to use an additional fudge factor here to avoid growing since each + // attachment is likely to consist of several buffers + + uint64_t TotalAttachmentsSize = 0; + + // Fixed size header + + CbPackageHeader Hdr{.HeaderMagic = kMagic, .AttachmentCount = gsl::narrow<uint32_t>(Attachments.size())}; + + ResponseBuffers.push_back(IoBufferBuilder::MakeCloneFromMemory(&Hdr, sizeof Hdr)); + + // Attachment metadata array + + IoBuffer AttachmentMetadataBuffer = IoBuffer{sizeof(CbAttachmentEntry) * (Attachments.size() + /* root */ 1)}; + + CbAttachmentEntry* AttachmentInfo = reinterpret_cast<CbAttachmentEntry*>(AttachmentMetadataBuffer.MutableData()); + + ResponseBuffers.push_back(AttachmentMetadataBuffer); // Attachment metadata + + // Root object + + IoBuffer RootIoBuffer = Data.GetObject().GetBuffer().AsIoBuffer(); + ResponseBuffers.push_back(RootIoBuffer); // Root object + + *AttachmentInfo++ = {.AttachmentSize = RootIoBuffer.Size(), .AttachmentHash = Data.GetObjectHash()}; + + // Attachment payloads + + for (const CbAttachment& Attachment : Attachments) + { + CompressedBuffer AttachmentBuffer = Attachment.AsCompressedBinary(); + CompositeBuffer Compressed = AttachmentBuffer.GetCompressed(); + + *AttachmentInfo++ = {.AttachmentSize = AttachmentBuffer.GetCompressedSize(), + .AttachmentHash = IoHash::FromBLAKE3(AttachmentBuffer.GetRawHash())}; + + for (const SharedBuffer& Segment : Compressed.GetSegments()) + { + ResponseBuffers.push_back(Segment.AsIoBuffer()); + TotalAttachmentsSize += Segment.GetSize(); + } + } + + return WriteResponse(HttpResponseCode, HttpContentType::kCbPackage, ResponseBuffers); } void HttpServerRequest::WriteResponse(HttpResponse HttpResponseCode, CbObject Data) { -#if 0 - struct Visitor : public ICbVisitor - { - virtual void SetName(std::string_view Name) override { OutText << '\'' << Name << "': "; } - virtual void BeginObject() override { OutText << "{ "; } - virtual void EndObject() override { OutText << "}"; } - virtual void BeginArray() override { OutText << "[ "; } - virtual void EndArray() override { OutText << " ]"; } - - virtual void VisitNull() override { OutText << "null"; } - virtual void VisitBinary(SharedBuffer Value) override { ZEN_UNUSED(Value); } - virtual void VisitString(std::string_view Value) override { ZEN_UNUSED(Value); } - virtual void VisitInteger(int64_t Value) override { OutText << Value; } - virtual void VisitInteger(uint64_t Value) override { OutText << Value; } - virtual void VisitFloat(float Value) override { ZEN_UNUSED(Value); } - virtual void VisitDouble(double Value) override { ZEN_UNUSED(Value); } - virtual void VisitBool(bool Value) override { OutText << Value; } - virtual void VisitCbAttachment(const IoHash& Value) override { ZEN_UNUSED(Value); } - virtual void VisitBinaryAttachment(const IoHash& Value) override { ZEN_UNUSED(Value); } - virtual void VisitHash(const IoHash& Value) override { ZEN_UNUSED(Value); } - virtual void VisitUuid(const Guid& Value) override { ZEN_UNUSED(Value); } - virtual void VisitObjectId(const Oid& Value) override { ZEN_UNUSED(Value); } - virtual void VisitDateTime(DateTime Value) override { ZEN_UNUSED(Value); } - virtual void VisitTimeSpan(TimeSpan Value) override { ZEN_UNUSED(Value); } - - ExtendableStringBuilder<256> OutText; - } _; - // Data.CreateRefIterator().VisitFields(_); - return WriteResponse(HttpResponseCode, HttpContentType::kJSON, _.OutText); -#else SharedBuffer Buf = Data.GetBuffer(); - std::array<IoBuffer, 1> buffers{IoBufferBuilder::MakeCloneFromMemory(Buf.GetData(), Buf.GetSize())}; - return WriteResponse(HttpResponseCode, HttpContentType::kCbObject, buffers); -#endif + std::array<IoBuffer, 1> Buffers{IoBufferBuilder::MakeCloneFromMemory(Buf.GetData(), Buf.GetSize())}; + return WriteResponse(HttpResponseCode, HttpContentType::kCbObject, Buffers); } void @@ -327,8 +356,8 @@ HttpServerRequest::WriteResponse(HttpResponse HttpResponseCode, HttpContentType void HttpServerRequest::WriteResponse(HttpResponse HttpResponseCode, HttpContentType ContentType, IoBuffer Blob) { - std::array<IoBuffer, 1> buffers{Blob}; - return WriteResponse(HttpResponseCode, ContentType, buffers); + std::array<IoBuffer, 1> Buffers{Blob}; + return WriteResponse(HttpResponseCode, ContentType, Buffers); } HttpServerRequest::QueryParams |