mirror of
https://github.com/bitcoin/bitcoin.git
synced 2026-07-26 16:18:47 +02:00
http: Implement HTTPResponse class
HTTP Response message: https://datatracker.ietf.org/doc/html/rfc1945#section-6 Status line (first line of response): https://datatracker.ietf.org/doc/html/rfc1945#section-6.1 Status code definitions: https://datatracker.ietf.org/doc/html/rfc1945#section-9
This commit is contained in:
@@ -808,4 +808,14 @@ std::string HTTPHeaders::Stringify() const
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
std::string HTTPResponse::StringifyHeaders() const
|
||||
{
|
||||
return strprintf("HTTP/%d.%d %d %s\r\n%s",
|
||||
m_version.major,
|
||||
m_version.minor,
|
||||
m_status,
|
||||
HTTPStatusReasonString(m_status),
|
||||
m_headers.Stringify());
|
||||
}
|
||||
} // namespace http_bitcoin
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
#include <span>
|
||||
#include <string>
|
||||
|
||||
#include <rpc/protocol.h>
|
||||
#include <util/strencodings.h>
|
||||
#include <util/string.h>
|
||||
|
||||
@@ -234,6 +235,29 @@ private:
|
||||
*/
|
||||
std::vector<std::pair<std::string, std::string>> m_headers;
|
||||
};
|
||||
|
||||
struct HTTPVersion {
|
||||
/**
|
||||
* Default HTTP protocol version 1.1 is used by error responses
|
||||
* when a request is unreadable.
|
||||
*/
|
||||
/// @{
|
||||
uint8_t major{1};
|
||||
uint8_t minor{1};
|
||||
/// @}
|
||||
};
|
||||
|
||||
|
||||
class HTTPResponse
|
||||
{
|
||||
public:
|
||||
HTTPVersion m_version;
|
||||
|
||||
HTTPStatusCode m_status{HTTP_INTERNAL_SERVER_ERROR};
|
||||
HTTPHeaders m_headers;
|
||||
|
||||
std::string StringifyHeaders() const;
|
||||
};
|
||||
} // namespace http_bitcoin
|
||||
|
||||
#endif // BITCOIN_HTTPSERVER_H
|
||||
|
||||
@@ -20,6 +20,27 @@ enum HTTPStatusCode : int
|
||||
HTTP_SERVICE_UNAVAILABLE = 503,
|
||||
};
|
||||
|
||||
//! Mapping of HTTP status codes to short string explanation.
|
||||
//! Copied from libevent http.c success_phrases[] and client_error_phrases[]
|
||||
inline std::string_view HTTPStatusReasonString(HTTPStatusCode code)
|
||||
{
|
||||
switch (code) {
|
||||
case HTTP_OK: return "OK";
|
||||
case HTTP_NO_CONTENT: return "No Content";
|
||||
case HTTP_BAD_REQUEST: return "Bad Request";
|
||||
case HTTP_UNAUTHORIZED: return "Unauthorized";
|
||||
case HTTP_FORBIDDEN: return "Forbidden";
|
||||
case HTTP_NOT_FOUND: return "Not Found";
|
||||
case HTTP_BAD_METHOD: return "Method Not Allowed";
|
||||
case HTTP_INTERNAL_SERVER_ERROR: return "Internal Server Error";
|
||||
case HTTP_SERVICE_UNAVAILABLE: return "Service Unavailable";
|
||||
}
|
||||
|
||||
// Reason phrases are optional and may be replaced by local variants.
|
||||
// https://httpwg.org/specs/rfc9110.html#rfc.section.15.1
|
||||
return "";
|
||||
}
|
||||
|
||||
//! Bitcoin RPC error codes
|
||||
enum RPCErrorCode
|
||||
{
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
||||
#include <httpserver.h>
|
||||
#include <rpc/protocol.h>
|
||||
#include <test/util/common.h>
|
||||
#include <test/util/setup_common.h>
|
||||
#include <util/string.h>
|
||||
@@ -10,6 +11,7 @@
|
||||
#include <boost/test/unit_test.hpp>
|
||||
|
||||
using http_bitcoin::HTTPHeaders;
|
||||
using http_bitcoin::HTTPResponse;
|
||||
using http_bitcoin::MAX_HEADERS_SIZE;
|
||||
|
||||
BOOST_FIXTURE_TEST_SUITE(httpserver_tests, BasicTestingSetup)
|
||||
@@ -144,4 +146,23 @@ BOOST_AUTO_TEST_CASE(http_headers_tests)
|
||||
BOOST_CHECK_EQUAL(headers.FindFirst("key"), "value");
|
||||
}
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(http_response_tests)
|
||||
{
|
||||
// Typical HTTP 1.1 response headers
|
||||
HTTPHeaders headers{};
|
||||
headers.Write("Content-Length", "41");
|
||||
|
||||
// Response points to headers which already exist because some of them
|
||||
// are set before we even know what the response will be.
|
||||
HTTPResponse res;
|
||||
res.m_version = {.major = 1, .minor = 1};
|
||||
res.m_status = HTTP_OK;
|
||||
res.m_headers = std::move(headers);
|
||||
BOOST_CHECK_EQUAL(
|
||||
res.StringifyHeaders(),
|
||||
"HTTP/1.1 200 OK\r\n"
|
||||
"Content-Length: 41\r\n"
|
||||
"\r\n");
|
||||
}
|
||||
BOOST_AUTO_TEST_SUITE_END()
|
||||
|
||||
Reference in New Issue
Block a user