Bitcoin Core 31.99.0
P2P Digital Currency
httpserver.h
Go to the documentation of this file.
1// Copyright (c) 2015-present The Bitcoin Core developers
2// Distributed under the MIT software license, see the accompanying
3// file COPYING or http://www.opensource.org/licenses/mit-license.php.
4
5#ifndef BITCOIN_HTTPSERVER_H
6#define BITCOIN_HTTPSERVER_H
7
8#include <atomic>
9#include <deque>
10#include <functional>
11#include <memory>
12#include <optional>
13#include <span>
14#include <stdexcept>
15#include <string>
16#include <vector>
17
18#include <netaddress.h>
19#include <rpc/protocol.h>
20#include <util/byte_units.h>
21#include <util/expected.h>
22#include <util/sock.h>
23#include <util/strencodings.h>
24#include <util/string.h>
25#include <util/threadinterrupt.h>
26#include <util/time.h>
27
28namespace util {
29class SignalInterrupt;
30} // namespace util
31
35static const int DEFAULT_HTTP_THREADS=16;
36
41static const int DEFAULT_HTTP_WORKQUEUE=64;
42
43static const int DEFAULT_HTTP_SERVER_TIMEOUT=30;
44
46 UNKNOWN,
47 GET,
48 POST,
49 HEAD,
50 PUT
51};
52
53namespace http_bitcoin {
54 class HTTPRequest;
55}
57using HTTPRequestHandler = std::function<void(http_bitcoin::HTTPRequest* req, const std::string&)>;
58
63void RegisterHTTPHandler(const std::string &prefix, bool exactMatch, const HTTPRequestHandler &handler);
65void UnregisterHTTPHandler(const std::string &prefix, bool exactMatch);
66
67namespace http_bitcoin {
69
71constexpr size_t MIN_REQUEST_LINE_LENGTH = std::string_view("GET / HTTP/1.0").size();
72
77constexpr size_t MAX_HEADERS_SIZE{8192};
78
80constexpr uint64_t MAX_BODY_SIZE{32_MiB};
81
84struct ContentTooLargeError : std::runtime_error {
85 using std::runtime_error::runtime_error;
86};
87
89{
90public:
96 std::optional<std::string> FindFirst(std::string_view key) const;
101 std::vector<std::string_view> FindAll(std::string_view key) const;
102 void Write(std::string&& key, std::string&& value);
106 void RemoveAll(std::string_view key);
115 std::string Stringify() const;
116
117private:
122 std::vector<std::pair<std::string, std::string>> m_headers;
123};
124
131 uint8_t major{1};
132 uint8_t minor{1};
134};
135
136
138{
139public:
141
144
145 std::string StringifyHeaders() const;
146};
147
148class HTTPRemoteClient;
149
151{
152public:
154 std::string m_target;
157 std::string m_body;
158
160 std::shared_ptr<HTTPRemoteClient> m_client;
161
164
165 explicit HTTPRequest(std::shared_ptr<HTTPRemoteClient> client) : m_client{std::move(client)} {}
167 explicit HTTPRequest() : m_client{} {}
168
182
183 void WriteReply(HTTPStatusCode status, std::span<const std::byte> reply_body = {});
184 void WriteReply(HTTPStatusCode status, std::string_view reply_body_view)
185 {
186 WriteReply(status, std::as_bytes(std::span{reply_body_view}));
187 }
188
189 // These methods reimplement the API from http_libevent::HTTPRequest
190 // for downstream JSONRPC and REST modules.
191 std::string GetURI() const { return m_target; }
192 CService GetPeer() const;
194 std::optional<std::string> GetQueryParameter(std::string_view key) const;
195 std::pair<bool, std::string> GetHeader(std::string_view hdr) const;
196 std::string ReadBody() const { return m_body; }
197 void WriteHeader(std::string&& hdr, std::string&& value);
198};
199
201{
202public:
206 using Id = uint64_t;
207
208 explicit HTTPServer(std::function<void(std::unique_ptr<HTTPRequest>&&)> func)
209 : m_request_dispatcher{std::move(func)} {}
210
211 virtual ~HTTPServer()
212 {
213 Assume(!m_thread_socket_handler.joinable()); // Missing call to JoinSocketsThreads()
214 Assume(m_connected.empty()); // Missing call to DisconnectClients(), or disconnect flags not set
215 Assume(m_listen.empty()); // Missing call to StopListening()
216 }
217
224
228 void StopListening();
229
233 size_t GetListeningSocketCount() const { return m_listen.size(); }
234
238 size_t GetConnectionsCount() const { return m_connected_size.load(std::memory_order_acquire); }
239
243 void StartSocketsThreads();
244
248 void JoinSocketsThreads();
249
254
259
264 void SetRequestHandler(std::function<void(std::unique_ptr<HTTPRequest>&&)> func)
266 {
268 m_request_dispatcher = std::move(func));
269 }
270
278
282 void SetServerTimeout(std::chrono::seconds seconds) { m_rpcservertimeout = seconds; }
283
289
290private:
294 std::vector<std::shared_ptr<Sock>> m_listen;
295
299 std::atomic<Id> m_next_id{0};
300
307 std::vector<std::shared_ptr<HTTPRemoteClient>> m_connected;
308
313 std::atomic_bool m_stop_accepting{false};
314
320 std::atomic_bool m_disconnect_all_clients{false};
321
327 std::atomic<size_t> m_connected_size{0};
328
333 struct IOReadiness {
340
346 std::unordered_map<Sock::EventsPerSock::key_type,
347 std::shared_ptr<HTTPRemoteClient>,
351 };
352
357
363
364 /*
365 * What to do with HTTP requests once received, validated and parsed.
366 * Set in main thread by server start and interrupt but read in
367 * worker threads.
368 */
371 std::function<void(std::unique_ptr<HTTPRequest>&&)> m_request_dispatcher GUARDED_BY(m_request_dispatcher_mutex);
373
378
385 std::unique_ptr<Sock> AcceptConnection(const Sock& listen_sock, CService& addr);
386
390 Id GetNewId();
391
398 void NewSockAccepted(std::unique_ptr<Sock>&& sock, const CService& addr);
399
404 void SocketHandlerConnected(const IOReadiness& io_readiness) const
406
411 void SocketHandlerListening(const Sock::EventsPerSock& events_per_sock);
412
418 IOReadiness GenerateWaitSockets() const;
419
425
433 void MaybeDispatchRequestsFromClient(const std::shared_ptr<HTTPRemoteClient>& client) const
435
442 void DisconnectClients();
443};
444
445std::optional<std::string> GetQueryParameterFromUri(std::string_view uri, std::string_view key);
446
448{
449public:
452
455
457 const std::string m_origin;
458
464 std::vector<std::byte> m_recv_buffer{};
465
470 std::deque<std::unique_ptr<HTTPRequest>> m_req_queue;
471
474 std::atomic_bool m_req_busy{false};
475
482 std::vector<std::byte> m_send_buffer GUARDED_BY(m_send_mutex);
484
493 bool m_send_ready GUARDED_BY(m_send_mutex){false};
494
501
509 std::shared_ptr<Sock> m_sock GUARDED_BY(m_sock_mutex);
510
517 std::atomic_bool m_connection_busy{true};
518
522 std::atomic_bool m_keep_alive{false};
523
529 std::atomic_bool m_disconnect{false};
530
534 std::atomic<SteadySeconds> m_idle_since;
535
536 explicit HTTPRemoteClient(HTTPServer::Id id, const CService& addr, std::unique_ptr<Sock> socket)
537 : m_id(id), m_addr(addr), m_origin(addr.ToStringAddrPort()), m_sock{std::move(socket)}, m_idle_since{Now<SteadySeconds>()} {}
538
539 // Disable copies (should only be used as shared pointers)
542
548 bool ReadRequest(HTTPRequest& req);
549
554 bool MaybeSendBytesFromBuffer() EXCLUSIVE_LOCKS_REQUIRED(!m_send_mutex, !m_sock_mutex);
555};
556
560bool InitHTTPServer();
561
566void StartHTTPServer();
567
570
572void StopHTTPServer();
573} // namespace http_bitcoin
574
575#endif // BITCOIN_HTTPSERVER_H
#define Assume(val)
Assume is the identity function.
Definition: check.h:128
A combination of a network address (CNetAddr) and a (TCP) port.
Definition: netaddress.h:530
A helper class for interruptible sleeps.
RAII helper class that manages a socket and closes it automatically when it goes out of scope.
Definition: sock.h:35
std::unordered_map< std::shared_ptr< const Sock >, Events, HashSharedPtrSock, EqualSharedPtrSock > EventsPerSock
On which socket to wait for what events in WaitMany().
Definition: sock.h:216
void RemoveAll(std::string_view key)
Definition: httpserver.cpp:292
bool Read(util::LineReader &reader)
Definition: httpserver.cpp:300
std::vector< std::string_view > FindAll(std::string_view key) const
Definition: httpserver.cpp:276
std::vector< std::pair< std::string, std::string > > m_headers
Headers can have duplicate field names, so we use a vector of key-value pairs instead of a map.
Definition: httpserver.h:122
std::string Stringify() const
Definition: httpserver.cpp:344
void Write(std::string &&key, std::string &&value)
Definition: httpserver.cpp:287
std::optional< std::string > FindFirst(std::string_view key) const
Definition: httpserver.cpp:266
std::deque< std::unique_ptr< HTTPRequest > > m_req_queue
Requests from a client must be processed in the order in which they were received,...
Definition: httpserver.h:470
std::shared_ptr< Sock > m_sock GUARDED_BY(m_sock_mutex)
Underlying socket.
std::vector< std::byte > m_send_buffer GUARDED_BY(m_send_mutex)
Mutex m_sock_mutex
Mutex that serializes the Send() and Recv() calls on m_sock.
Definition: httpserver.h:500
std::atomic< SteadySeconds > m_idle_since
Timestamp of last send or receive activity, used for -rpcservertimeout.
Definition: httpserver.h:534
const HTTPServer::Id m_id
ID provided by HTTPServer upon connection and instantiation.
Definition: httpserver.h:451
Mutex m_send_mutex
Response data destined for this client.
Definition: httpserver.h:481
HTTPRemoteClient(HTTPServer::Id id, const CService &addr, std::unique_ptr< Sock > socket)
Definition: httpserver.h:536
HTTPRemoteClient(const HTTPRemoteClient &)=delete
const CService m_addr
Remote address of connected client.
Definition: httpserver.h:454
const std::string m_origin
IP:port of connected client, cached for logging purposes.
Definition: httpserver.h:457
bool m_send_ready GUARDED_BY(m_send_mutex)
Set true by worker threads after writing a response to m_send_buffer.
Definition: httpserver.h:493
HTTPRemoteClient & operator=(const HTTPRemoteClient &)=delete
std::string GetURI() const
Definition: httpserver.h:191
HTTPHeaders m_response_headers
Response headers may be set in advance before response body is known.
Definition: httpserver.h:163
HTTPRequestMethod m_method
Definition: httpserver.h:153
std::optional< std::string > GetQueryParameter(std::string_view key) const
Definition: httpserver.cpp:635
std::string ReadBody() const
Definition: httpserver.h:196
HTTPRequest()
Construct with a null client for unit tests.
Definition: httpserver.h:167
bool LoadHeaders(LineReader &reader)
Definition: httpserver.cpp:415
std::pair< bool, std::string > GetHeader(std::string_view hdr) const
Definition: httpserver.cpp:667
void WriteHeader(std::string &&hdr, std::string &&value)
Definition: httpserver.cpp:673
std::shared_ptr< HTTPRemoteClient > m_client
Pointer to the client that made the request so we know who to respond to.
Definition: httpserver.h:160
CService GetPeer() const
Definition: httpserver.cpp:630
bool LoadControlData(LineReader &reader)
Methods that attempt to parse HTTP request fields line-by-line from a receive buffer.
Definition: httpserver.cpp:367
HTTPRequestMethod GetRequestMethod() const
Definition: httpserver.h:193
void WriteReply(HTTPStatusCode status, std::span< const std::byte > reply_body={})
Definition: httpserver.cpp:515
HTTPRequest(std::shared_ptr< HTTPRemoteClient > client)
Definition: httpserver.h:165
void WriteReply(HTTPStatusCode status, std::string_view reply_body_view)
Definition: httpserver.h:184
bool LoadBody(LineReader &reader)
Definition: httpserver.cpp:420
HTTPStatusCode m_status
Definition: httpserver.h:142
std::string StringifyHeaders() const
Definition: httpserver.cpp:357
void NewSockAccepted(std::unique_ptr< Sock > &&sock, const CService &addr)
After a new socket with a client has been created, configure its flags, make a new HTTPRemoteClient a...
Definition: httpserver.cpp:810
void ThreadSocketHandler() EXCLUSIVE_LOCKS_REQUIRED(!m_request_dispatcher_mutex)
Check connected and listening sockets for IO readiness and process them accordingly.
Definition: httpserver.cpp:958
std::function< void(std::unique_ptr< HTTPRequest > &&)> m_request_dispatcher GUARDED_BY(m_request_dispatcher_mutex)
std::vector< std::shared_ptr< Sock > > m_listen
List of listening sockets.
Definition: httpserver.h:294
size_t GetConnectionsCount() const
Get the number of HTTPRemoteClients we are connected to.
Definition: httpserver.h:238
CThreadInterrupt m_interrupt_net
This is signaled when network activity should cease.
Definition: httpserver.h:356
std::atomic_bool m_disconnect_all_clients
Flag used during shutdown.
Definition: httpserver.h:320
void DisconnectClients()
Close underlying socket connections for flagged clients by removing their shared pointer from m_conne...
void StopListening()
Stop listening by closing all listening sockets.
Definition: httpserver.cpp:754
void SocketHandlerListening(const Sock::EventsPerSock &events_per_sock)
Accept incoming connections, one from each read-ready listening socket.
Definition: httpserver.cpp:910
std::vector< std::shared_ptr< HTTPRemoteClient > > m_connected
List of HTTPRemoteClients with connected sockets.
Definition: httpserver.h:307
void SetServerTimeout(std::chrono::seconds seconds)
Set the idle client timeout (-rpcservertimeout)
Definition: httpserver.h:282
IOReadiness GenerateWaitSockets() const
Generate a collection of sockets to check for IO readiness.
Definition: httpserver.cpp:930
std::atomic< Id > m_next_id
The id to assign to the next created connection.
Definition: httpserver.h:299
void StartSocketsThreads()
Start the necessary threads for sockets IO.
Definition: httpserver.cpp:759
size_t GetListeningSocketCount() const
Get the number of sockets the server is bound to and listening on.
Definition: httpserver.h:233
void MaybeDispatchRequestsFromClient(const std::shared_ptr< HTTPRemoteClient > &client) const EXCLUSIVE_LOCKS_REQUIRED(!m_request_dispatcher_mutex)
Try to read HTTPRequests from a client's receive buffer.
Definition: httpserver.cpp:984
void JoinSocketsThreads()
Join (wait for) the threads started by StartSocketsThreads() to exit.
Definition: httpserver.cpp:766
std::chrono::seconds m_rpcservertimeout
Idle timeout after which clients are disconnected.
Definition: httpserver.h:377
HTTPServer(std::function< void(std::unique_ptr< HTTPRequest > &&)> func)
Definition: httpserver.h:208
std::thread m_thread_socket_handler
Thread that sends to and receives from sockets and accepts connections.
Definition: httpserver.h:362
std::unique_ptr< Sock > AcceptConnection(const Sock &listen_sock, CService &addr)
Accept a connection.
Definition: httpserver.cpp:773
void ClearConnectedClients()
Force-remove all remaining clients from m_connected without waiting for graceful disconnection.
std::atomic< size_t > m_connected_size
The number of connected sockets.
Definition: httpserver.h:327
util::Expected< void, std::string > BindAndStartListening(const CService &to)
Bind to a new address:port, start listening and add the listen socket to m_listen.
Definition: httpserver.cpp:678
Id GetNewId()
Generate an id for a newly created connection.
Definition: httpserver.cpp:805
void StopAccepting()
Stop accepting new connections in the I/O loop.
Definition: httpserver.h:277
std::atomic_bool m_stop_accepting
Flag used during shutdown to stop accepting new connections.
Definition: httpserver.h:313
void SetRequestHandler(std::function< void(std::unique_ptr< HTTPRequest > &&)> func) EXCLUSIVE_LOCKS_REQUIRED(!m_request_dispatcher_mutex)
Update the request handler method.
Definition: httpserver.h:264
void DisconnectAllClients()
Start disconnecting clients when possible in the I/O loop.
Definition: httpserver.h:258
void InterruptNet()
Stop network activity.
Definition: httpserver.h:253
void SocketHandlerConnected(const IOReadiness &io_readiness) const EXCLUSIVE_LOCKS_REQUIRED(!m_request_dispatcher_mutex)
Do the read/write for connected sockets that are ready for IO.
Definition: httpserver.cpp:837
uint64_t Id
Each connection is assigned an unique id of this type.
Definition: httpserver.h:206
The util::Expected class provides a standard way for low-level functions to return either error value...
Definition: expected.h:44
Helper class that manages an interrupt flag, and allows a thread or signal to interrupt another threa...
static const int DEFAULT_HTTP_SERVER_TIMEOUT
Definition: httpserver.h:43
void UnregisterHTTPHandler(const std::string &prefix, bool exactMatch)
Unregister handler for prefix.
Definition: httpserver.cpp:248
void RegisterHTTPHandler(const std::string &prefix, bool exactMatch, const HTTPRequestHandler &handler)
Register handler for prefix.
Definition: httpserver.cpp:241
static const int DEFAULT_HTTP_WORKQUEUE
The default value for -rpcworkqueue.
Definition: httpserver.h:41
static const int DEFAULT_HTTP_THREADS
The default value for -rpcthreads.
Definition: httpserver.h:35
std::function< void(http_bitcoin::HTTPRequest *req, const std::string &)> HTTPRequestHandler
Handler for requests to a certain HTTP path.
Definition: httpserver.h:57
HTTPRequestMethod
Definition: httpserver.h:45
util::LineReader reader
constexpr size_t MIN_REQUEST_LINE_LENGTH
Shortest valid request line, used by libevent in evhttp_parse_request_line()
Definition: httpserver.h:71
void StartHTTPServer()
Start HTTP server.
std::optional< std::string > GetQueryParameterFromUri(const std::string_view uri, const std::string_view key)
Definition: httpserver.cpp:642
constexpr uint64_t MAX_BODY_SIZE
Maximum size of an HTTP request body.
Definition: httpserver.h:80
constexpr size_t MAX_HEADERS_SIZE
Maximum size of each headers line in an HTTP request, also the maximum size of all headers total.
Definition: httpserver.h:77
void StopHTTPServer()
Stop HTTP server.
void InterruptHTTPServer()
Interrupt HTTP server threads.
bool InitHTTPServer()
Initialize HTTP server.
const char * prefix
Definition: rest.cpp:1143
bool(* handler)(const std::any &context, HTTPRequest *req, const std::string &strReq)
Definition: rest.cpp:1144
HTTPStatusCode
HTTP status codes.
Definition: protocol.h:11
@ HTTP_INTERNAL_SERVER_ERROR
Definition: protocol.h:20
Thrown when a request body exceeds MAX_BODY_SIZE (or will exceed, in chunked transfer) so the server ...
Definition: httpserver.h:84
Info about which socket has which event ready and a reverse map back to the HTTPRemoteClient that own...
Definition: httpserver.h:333
std::unordered_map< Sock::EventsPerSock::key_type, std::shared_ptr< HTTPRemoteClient >, Sock::HashSharedPtrSock, Sock::EqualSharedPtrSock > httpclients_per_sock
Map of socket -> HTTPRemoteClient.
Definition: httpserver.h:350
Sock::EventsPerSock events_per_sock
Map of socket -> socket events.
Definition: httpserver.h:339
uint8_t major
Default HTTP protocol version 1.1 is used by error responses when a request is unreadable.
Definition: httpserver.h:131
#define WITH_LOCK(cs, code)
Run code while locking a mutex.
Definition: sync.h:299
#define EXCLUSIVE_LOCKS_REQUIRED(...)
Definition: threadsafety.h:49
T Now()
Return the current time point cast to the given precision.
Definition: time.h:135
std::chrono::time_point< std::chrono::steady_clock, std::chrono::seconds > SteadySeconds
Definition: time.h:38