diff options
| author | Dan Engelbrecht <[email protected]> | 2024-03-26 13:28:07 +0100 |
|---|---|---|
| committer | GitHub Enterprise <[email protected]> | 2024-03-26 13:28:07 +0100 |
| commit | 66cf5342b2fe8bd3f2961dc70b9c302bf4de12bf (patch) | |
| tree | 16dfe666651653f03342dd502e85bbfecd4448c2 /src | |
| parent | remove redundant json11 includes (diff) | |
| download | zen-66cf5342b2fe8bd3f2961dc70b9c302bf4de12bf.tar.xz zen-66cf5342b2fe8bd3f2961dc70b9c302bf4de12bf.zip | |
add filter to projectstore entries request (#25)
* Add HttpServerRequest::Decode to decode http request parameters
* Add support to filter projectstore `entries` request using the `fieldfilter` where the wanted fields are comma (,) delimited
* Add support for responding with compressed payloads for projectstore `entries` requests by adding AcceptType `compressed-binary` to the request header
* Add support for responding with compressed payloads for projectstore `files` requests by adding AcceptType `compressed-binary` to the request header
* Add support for responding with compressed payloads for projectstore `chunkinfo` requests by adding AcceptType `compressed-binary` to the request header
Diffstat (limited to 'src')
| -rw-r--r-- | src/zenhttp/httpserver.cpp | 34 | ||||
| -rw-r--r-- | src/zenhttp/include/zenhttp/httpserver.h | 2 | ||||
| -rw-r--r-- | src/zenserver/projectstore/httpprojectstore.cpp | 71 |
3 files changed, 101 insertions, 6 deletions
diff --git a/src/zenhttp/httpserver.cpp b/src/zenhttp/httpserver.cpp index dcbeac907..adb3128bf 100644 --- a/src/zenhttp/httpserver.cpp +++ b/src/zenhttp/httpserver.cpp @@ -530,6 +530,40 @@ HttpServerRequest::WriteResponse(HttpResponseCode ResponseCode, HttpContentType WriteResponse(ResponseCode, ContentType, Buffers); } +std::string +HttpServerRequest::Decode(std::string_view PercentEncodedString) +{ + size_t Length = PercentEncodedString.length(); + std::string Decoded; + Decoded.reserve(Length); + size_t Offset = 0; + while (Offset < Length) + { + char C = PercentEncodedString[Offset]; + if (C == '%' && (Offset <= (Length - 3))) + { + std::string_view CharHash(&PercentEncodedString[Offset + 1], 2); + uint8_t DecodedChar = 0; + if (ParseHexBytes(CharHash, &DecodedChar)) + { + Decoded.push_back((char)DecodedChar); + Offset += 3; + } + else + { + Decoded.push_back(C); + Offset++; + } + } + else + { + Decoded.push_back(C); + Offset++; + } + } + return Decoded; +} + HttpServerRequest::QueryParams HttpServerRequest::GetQueryParams() { diff --git a/src/zenhttp/include/zenhttp/httpserver.h b/src/zenhttp/include/zenhttp/httpserver.h index 1089dd221..7b87cb84b 100644 --- a/src/zenhttp/include/zenhttp/httpserver.h +++ b/src/zenhttp/include/zenhttp/httpserver.h @@ -62,6 +62,8 @@ public: } }; + static std::string Decode(std::string_view PercentEncodedString); + virtual bool TryGetRanges(HttpRanges&) { return false; } QueryParams GetQueryParams(); diff --git a/src/zenserver/projectstore/httpprojectstore.cpp b/src/zenserver/projectstore/httpprojectstore.cpp index 260f60cfe..e8a748c4c 100644 --- a/src/zenserver/projectstore/httpprojectstore.cpp +++ b/src/zenserver/projectstore/httpprojectstore.cpp @@ -6,6 +6,7 @@ #include <zencore/compactbinarybuilder.h> #include <zencore/compactbinarypackage.h> +#include <zencore/compactbinaryutil.h> #include <zencore/filesystem.h> #include <zencore/fmtutils.h> #include <zencore/logging.h> @@ -626,7 +627,15 @@ HttpProjectService::HandleFilesRequest(HttpRouterRequest& Req) std::pair<HttpResponseCode, std::string> Result = m_ProjectStore->GetProjectFiles(ProjectId, OplogId, FilterClient, ResponsePayload); if (Result.first == HttpResponseCode::OK) { - return HttpReq.WriteResponse(HttpResponseCode::OK, ResponsePayload); + if (HttpReq.AcceptContentType() == HttpContentType::kCompressedBinary) + { + CompositeBuffer Payload = CompressedBuffer::Compress(ResponsePayload.GetBuffer()).GetCompressed(); + return HttpReq.WriteResponse(HttpResponseCode::OK, HttpContentType::kCompressedBinary, Payload); + } + else + { + return HttpReq.WriteResponse(HttpResponseCode::OK, ResponsePayload); + } } else { @@ -661,7 +670,15 @@ HttpProjectService::HandleChunkInfosRequest(HttpRouterRequest& Req) std::pair<HttpResponseCode, std::string> Result = m_ProjectStore->GetProjectChunkInfos(ProjectId, OplogId, ResponsePayload); if (Result.first == HttpResponseCode::OK) { - return HttpReq.WriteResponse(HttpResponseCode::OK, ResponsePayload); + if (HttpReq.AcceptContentType() == HttpContentType::kCompressedBinary) + { + CompositeBuffer Payload = CompressedBuffer::Compress(ResponsePayload.GetBuffer()).GetCompressed(); + return HttpReq.WriteResponse(HttpResponseCode::OK, HttpContentType::kCompressedBinary, Payload); + } + else + { + return HttpReq.WriteResponse(HttpResponseCode::OK, ResponsePayload); + } } else { @@ -1369,7 +1386,28 @@ HttpProjectService::HandleOpLogEntriesRequest(HttpRouterRequest& Req) if (FoundLog->OplogCount() > 0) { + std::unordered_set<std::string> FieldNamesFilter; + auto FilterObject = [&FieldNamesFilter](CbObjectView& Object) -> CbObject { + CbObject RewrittenOp = RewriteCbObject(Object, [&FieldNamesFilter](CbObjectWriter&, CbFieldView Field) -> bool { + if (FieldNamesFilter.contains(std::string(Field.GetName()))) + { + return false; + } + + return true; + }); + + return RewrittenOp; + }; + HttpServerRequest::QueryParams Params = HttpReq.GetQueryParams(); + if (auto FieldFilter = HttpServerRequest::Decode(Params.GetValue("fieldfilter")); !FieldFilter.empty()) + { + ForEachStrTok(FieldFilter, ',', [&](std::string_view FieldName) { + FieldNamesFilter.insert(std::string(FieldName)); + return true; + }); + } if (auto OpKey = Params.GetValue("opkey"); !OpKey.empty()) { @@ -1378,7 +1416,14 @@ HttpProjectService::HandleOpLogEntriesRequest(HttpRouterRequest& Req) if (Op.has_value()) { - Response << "entry"sv << Op.value(); + if (FieldNamesFilter.empty()) + { + Response << "entry"sv << Op.value(); + } + else + { + Response << "entry"sv << FilterObject(Op.value()); + } } else { @@ -1389,13 +1434,27 @@ HttpProjectService::HandleOpLogEntriesRequest(HttpRouterRequest& Req) { Response.BeginArray("entries"sv); - FoundLog->IterateOplog([&Response](CbObjectView Op) { Response << Op; }); + if (FieldNamesFilter.empty()) + { + FoundLog->IterateOplog([&Response](CbObjectView Op) { Response << Op; }); + } + else + { + FoundLog->IterateOplog([this, &Response, &FilterObject](CbObjectView Op) { Response << FilterObject(Op); }); + } Response.EndArray(); } } - - return HttpReq.WriteResponse(HttpResponseCode::OK, Response.Save()); + if (HttpReq.AcceptContentType() == HttpContentType::kCompressedBinary) + { + CompositeBuffer Payload = CompressedBuffer::Compress(Response.Save().GetBuffer()).GetCompressed(); + return HttpReq.WriteResponse(HttpResponseCode::OK, HttpContentType::kCompressedBinary, Payload); + } + else + { + return HttpReq.WriteResponse(HttpResponseCode::OK, Response.Save()); + } } void |