diff options
author | Roman Zeyde <me@romanzey.de> | 2024-06-22 11:46:10 +0300 |
---|---|---|
committer | Roman Zeyde <me@romanzey.de> | 2024-06-26 06:47:30 +0300 |
commit | 1556d21599a250297d5f20e5249c970340ab08bc (patch) | |
tree | 9029a71c29acf707b00fd46cf5336426bce52f9e | |
parent | 538363738e9e30813cf3e76ca4f71c1aaff349e7 (diff) |
rest: don't copy data when sending binary response
Also, change `HTTPRequest::WriteReply` to accept `std::span`.
-rw-r--r-- | src/httpserver.cpp | 5 | ||||
-rw-r--r-- | src/httpserver.h | 9 | ||||
-rw-r--r-- | src/rest.cpp | 20 |
3 files changed, 17 insertions, 17 deletions
diff --git a/src/httpserver.cpp b/src/httpserver.cpp index b1d4dc9234..b6c6db8b35 100644 --- a/src/httpserver.cpp +++ b/src/httpserver.cpp @@ -26,6 +26,7 @@ #include <deque> #include <memory> #include <optional> +#include <span> #include <string> #include <unordered_map> @@ -634,7 +635,7 @@ void HTTPRequest::WriteHeader(const std::string& hdr, const std::string& value) * Replies must be sent in the main loop in the main http thread, * this cannot be done from worker threads. */ -void HTTPRequest::WriteReply(int nStatus, const std::string& strReply) +void HTTPRequest::WriteReply(int nStatus, std::span<const std::byte> reply) { assert(!replySent && req); if (m_interrupt) { @@ -643,7 +644,7 @@ void HTTPRequest::WriteReply(int nStatus, const std::string& strReply) // Send event to main http thread to send reply message struct evbuffer* evb = evhttp_request_get_output_buffer(req); assert(evb); - evbuffer_add(evb, strReply.data(), strReply.size()); + evbuffer_add(evb, reply.data(), reply.size()); auto req_copy = req; HTTPEvent* ev = new HTTPEvent(eventBase, true, [req_copy, nStatus]{ evhttp_send_reply(req_copy, nStatus, nullptr, nullptr); diff --git a/src/httpserver.h b/src/httpserver.h index 9a49877f09..991081bab8 100644 --- a/src/httpserver.h +++ b/src/httpserver.h @@ -7,6 +7,7 @@ #include <functional> #include <optional> +#include <span> #include <string> namespace util { @@ -123,12 +124,16 @@ public: /** * Write HTTP reply. * nStatus is the HTTP status code to send. - * strReply is the body of the reply. Keep it empty to send a standard message. + * reply is the body of the reply. Keep it empty to send a standard message. * * @note Can be called only once. As this will give the request back to the * main thread, do not call any other HTTPRequest methods after calling this. */ - void WriteReply(int nStatus, const std::string& strReply = ""); + void WriteReply(int nStatus, std::string_view reply = "") + { + WriteReply(nStatus, std::as_bytes(std::span{reply.data(), reply.size()})); + } + void WriteReply(int nStatus, std::span<const std::byte> reply); }; /** Get the query parameter value from request uri for a specified key, or std::nullopt if the key diff --git a/src/rest.cpp b/src/rest.cpp index d43018f5af..4abbc4d2ca 100644 --- a/src/rest.cpp +++ b/src/rest.cpp @@ -248,9 +248,8 @@ static bool rest_headers(const std::any& context, ssHeader << pindex->GetBlockHeader(); } - std::string binaryHeader = ssHeader.str(); req->WriteHeader("Content-Type", "application/octet-stream"); - req->WriteReply(HTTP_OK, binaryHeader); + req->WriteReply(HTTP_OK, ssHeader); return true; } @@ -321,9 +320,8 @@ static bool rest_block(const std::any& context, switch (rf) { case RESTResponseFormat::BINARY: { - const std::string binaryBlock{block_data.begin(), block_data.end()}; req->WriteHeader("Content-Type", "application/octet-stream"); - req->WriteReply(HTTP_OK, binaryBlock); + req->WriteReply(HTTP_OK, std::as_bytes(std::span{block_data})); return true; } @@ -451,9 +449,8 @@ static bool rest_filter_header(const std::any& context, HTTPRequest* req, const ssHeader << header; } - std::string binaryHeader = ssHeader.str(); req->WriteHeader("Content-Type", "application/octet-stream"); - req->WriteReply(HTTP_OK, binaryHeader); + req->WriteReply(HTTP_OK, ssHeader); return true; } case RESTResponseFormat::HEX: { @@ -548,9 +545,8 @@ static bool rest_block_filter(const std::any& context, HTTPRequest* req, const s DataStream ssResp{}; ssResp << filter; - std::string binaryResp = ssResp.str(); req->WriteHeader("Content-Type", "application/octet-stream"); - req->WriteReply(HTTP_OK, binaryResp); + req->WriteReply(HTTP_OK, ssResp); return true; } case RESTResponseFormat::HEX: { @@ -729,9 +725,8 @@ static bool rest_tx(const std::any& context, HTTPRequest* req, const std::string DataStream ssTx; ssTx << TX_WITH_WITNESS(tx); - std::string binaryTx = ssTx.str(); req->WriteHeader("Content-Type", "application/octet-stream"); - req->WriteReply(HTTP_OK, binaryTx); + req->WriteReply(HTTP_OK, ssTx); return true; } @@ -900,10 +895,9 @@ static bool rest_getutxos(const std::any& context, HTTPRequest* req, const std:: // use exact same output as mentioned in Bip64 DataStream ssGetUTXOResponse{}; ssGetUTXOResponse << active_height << active_hash << bitmap << outs; - std::string ssGetUTXOResponseString = ssGetUTXOResponse.str(); req->WriteHeader("Content-Type", "application/octet-stream"); - req->WriteReply(HTTP_OK, ssGetUTXOResponseString); + req->WriteReply(HTTP_OK, ssGetUTXOResponse); return true; } @@ -981,7 +975,7 @@ static bool rest_blockhash_by_height(const std::any& context, HTTPRequest* req, DataStream ss_blockhash{}; ss_blockhash << pblockindex->GetBlockHash(); req->WriteHeader("Content-Type", "application/octet-stream"); - req->WriteReply(HTTP_OK, ss_blockhash.str()); + req->WriteReply(HTTP_OK, ss_blockhash); return true; } case RESTResponseFormat::HEX: { |