mirror of
https://github.com/bitcoin/bitcoin.git
synced 2025-06-26 08:51:55 +02:00
Merge bitcoin/bitcoin#30321: rest: don't copy data when sending binary response
1556d21599a250297d5f20e5249c970340ab08bc rest: don't copy data when sending binary response (Roman Zeyde) Pull request description: Also, change `HTTPRequest::WriteReply` to accept `std::span`. ACKs for top commit: laanwj: re-ACK 1556d21599a250297d5f20e5249c970340ab08bc stickies-v: ACK 1556d21599a250297d5f20e5249c970340ab08bc Tree-SHA512: 3e563d8072f0e1b90b00f85adb140d4e5fef169b6882a837b08d1e8391b64c21bea3c4256c4e2a624ac1fb3d374f12a1cc16dc59b2155ec857728162d1daaceb
This commit is contained in:
commit
b4b9854394
@ -26,6 +26,7 @@
|
|||||||
#include <deque>
|
#include <deque>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <optional>
|
#include <optional>
|
||||||
|
#include <span>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <unordered_map>
|
#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,
|
* Replies must be sent in the main loop in the main http thread,
|
||||||
* this cannot be done from worker threads.
|
* 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);
|
assert(!replySent && req);
|
||||||
if (m_interrupt) {
|
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
|
// Send event to main http thread to send reply message
|
||||||
struct evbuffer* evb = evhttp_request_get_output_buffer(req);
|
struct evbuffer* evb = evhttp_request_get_output_buffer(req);
|
||||||
assert(evb);
|
assert(evb);
|
||||||
evbuffer_add(evb, strReply.data(), strReply.size());
|
evbuffer_add(evb, reply.data(), reply.size());
|
||||||
auto req_copy = req;
|
auto req_copy = req;
|
||||||
HTTPEvent* ev = new HTTPEvent(eventBase, true, [req_copy, nStatus]{
|
HTTPEvent* ev = new HTTPEvent(eventBase, true, [req_copy, nStatus]{
|
||||||
evhttp_send_reply(req_copy, nStatus, nullptr, nullptr);
|
evhttp_send_reply(req_copy, nStatus, nullptr, nullptr);
|
||||||
|
@ -7,6 +7,7 @@
|
|||||||
|
|
||||||
#include <functional>
|
#include <functional>
|
||||||
#include <optional>
|
#include <optional>
|
||||||
|
#include <span>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
namespace util {
|
namespace util {
|
||||||
@ -123,12 +124,16 @@ public:
|
|||||||
/**
|
/**
|
||||||
* Write HTTP reply.
|
* Write HTTP reply.
|
||||||
* nStatus is the HTTP status code to send.
|
* 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
|
* @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.
|
* 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
|
/** Get the query parameter value from request uri for a specified key, or std::nullopt if the key
|
||||||
|
20
src/rest.cpp
20
src/rest.cpp
@ -248,9 +248,8 @@ static bool rest_headers(const std::any& context,
|
|||||||
ssHeader << pindex->GetBlockHeader();
|
ssHeader << pindex->GetBlockHeader();
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string binaryHeader = ssHeader.str();
|
|
||||||
req->WriteHeader("Content-Type", "application/octet-stream");
|
req->WriteHeader("Content-Type", "application/octet-stream");
|
||||||
req->WriteReply(HTTP_OK, binaryHeader);
|
req->WriteReply(HTTP_OK, ssHeader);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -321,9 +320,8 @@ static bool rest_block(const std::any& context,
|
|||||||
|
|
||||||
switch (rf) {
|
switch (rf) {
|
||||||
case RESTResponseFormat::BINARY: {
|
case RESTResponseFormat::BINARY: {
|
||||||
const std::string binaryBlock{block_data.begin(), block_data.end()};
|
|
||||||
req->WriteHeader("Content-Type", "application/octet-stream");
|
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;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -451,9 +449,8 @@ static bool rest_filter_header(const std::any& context, HTTPRequest* req, const
|
|||||||
ssHeader << header;
|
ssHeader << header;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string binaryHeader = ssHeader.str();
|
|
||||||
req->WriteHeader("Content-Type", "application/octet-stream");
|
req->WriteHeader("Content-Type", "application/octet-stream");
|
||||||
req->WriteReply(HTTP_OK, binaryHeader);
|
req->WriteReply(HTTP_OK, ssHeader);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
case RESTResponseFormat::HEX: {
|
case RESTResponseFormat::HEX: {
|
||||||
@ -548,9 +545,8 @@ static bool rest_block_filter(const std::any& context, HTTPRequest* req, const s
|
|||||||
DataStream ssResp{};
|
DataStream ssResp{};
|
||||||
ssResp << filter;
|
ssResp << filter;
|
||||||
|
|
||||||
std::string binaryResp = ssResp.str();
|
|
||||||
req->WriteHeader("Content-Type", "application/octet-stream");
|
req->WriteHeader("Content-Type", "application/octet-stream");
|
||||||
req->WriteReply(HTTP_OK, binaryResp);
|
req->WriteReply(HTTP_OK, ssResp);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
case RESTResponseFormat::HEX: {
|
case RESTResponseFormat::HEX: {
|
||||||
@ -729,9 +725,8 @@ static bool rest_tx(const std::any& context, HTTPRequest* req, const std::string
|
|||||||
DataStream ssTx;
|
DataStream ssTx;
|
||||||
ssTx << TX_WITH_WITNESS(tx);
|
ssTx << TX_WITH_WITNESS(tx);
|
||||||
|
|
||||||
std::string binaryTx = ssTx.str();
|
|
||||||
req->WriteHeader("Content-Type", "application/octet-stream");
|
req->WriteHeader("Content-Type", "application/octet-stream");
|
||||||
req->WriteReply(HTTP_OK, binaryTx);
|
req->WriteReply(HTTP_OK, ssTx);
|
||||||
return true;
|
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
|
// use exact same output as mentioned in Bip64
|
||||||
DataStream ssGetUTXOResponse{};
|
DataStream ssGetUTXOResponse{};
|
||||||
ssGetUTXOResponse << active_height << active_hash << bitmap << outs;
|
ssGetUTXOResponse << active_height << active_hash << bitmap << outs;
|
||||||
std::string ssGetUTXOResponseString = ssGetUTXOResponse.str();
|
|
||||||
|
|
||||||
req->WriteHeader("Content-Type", "application/octet-stream");
|
req->WriteHeader("Content-Type", "application/octet-stream");
|
||||||
req->WriteReply(HTTP_OK, ssGetUTXOResponseString);
|
req->WriteReply(HTTP_OK, ssGetUTXOResponse);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -981,7 +975,7 @@ static bool rest_blockhash_by_height(const std::any& context, HTTPRequest* req,
|
|||||||
DataStream ss_blockhash{};
|
DataStream ss_blockhash{};
|
||||||
ss_blockhash << pblockindex->GetBlockHash();
|
ss_blockhash << pblockindex->GetBlockHash();
|
||||||
req->WriteHeader("Content-Type", "application/octet-stream");
|
req->WriteHeader("Content-Type", "application/octet-stream");
|
||||||
req->WriteReply(HTTP_OK, ss_blockhash.str());
|
req->WriteReply(HTTP_OK, ss_blockhash);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
case RESTResponseFormat::HEX: {
|
case RESTResponseFormat::HEX: {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user