Branch data Line data Source code
1 : : // Copyright (c) 2015-2022 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 <functional>
9 : : #include <optional>
10 : : #include <span>
11 : : #include <string>
12 : :
13 : : namespace util {
14 : : class SignalInterrupt;
15 : : } // namespace util
16 : :
17 : : /**
18 : : * The default value for `-rpcthreads`. This number of threads will be created at startup.
19 : : */
20 : : static const int DEFAULT_HTTP_THREADS=16;
21 : :
22 : : /**
23 : : * The default value for `-rpcworkqueue`. This is the maximum depth of the work queue,
24 : : * we don't allocate this number of work queue items upfront.
25 : : */
26 : : static const int DEFAULT_HTTP_WORKQUEUE=64;
27 : :
28 : : static const int DEFAULT_HTTP_SERVER_TIMEOUT=30;
29 : :
30 : : struct evhttp_request;
31 : : struct event_base;
32 : : class CService;
33 : : class HTTPRequest;
34 : :
35 : : /** Initialize HTTP server.
36 : : * Call this before RegisterHTTPHandler or EventBase().
37 : : */
38 : : bool InitHTTPServer(const util::SignalInterrupt& interrupt);
39 : : /** Start HTTP server.
40 : : * This is separate from InitHTTPServer to give users race-condition-free time
41 : : * to register their handlers between InitHTTPServer and StartHTTPServer.
42 : : */
43 : : void StartHTTPServer();
44 : : /** Interrupt HTTP server threads */
45 : : void InterruptHTTPServer();
46 : : /** Stop HTTP server */
47 : : void StopHTTPServer();
48 : :
49 : : /** Change logging level for libevent. */
50 : : void UpdateHTTPServerLogging(bool enable);
51 : :
52 : : /** Handler for requests to a certain HTTP path */
53 : : typedef std::function<bool(HTTPRequest* req, const std::string &)> HTTPRequestHandler;
54 : : /** Register handler for prefix.
55 : : * If multiple handlers match a prefix, the first-registered one will
56 : : * be invoked.
57 : : */
58 : : void RegisterHTTPHandler(const std::string &prefix, bool exactMatch, const HTTPRequestHandler &handler);
59 : : /** Unregister handler for prefix */
60 : : void UnregisterHTTPHandler(const std::string &prefix, bool exactMatch);
61 : :
62 : : /** Return evhttp event base. This can be used by submodules to
63 : : * queue timers or custom events.
64 : : */
65 : : struct event_base* EventBase();
66 : :
67 : : /** In-flight HTTP request.
68 : : * Thin C++ wrapper around evhttp_request.
69 : : */
70 : : class HTTPRequest
71 : : {
72 : : private:
73 : : struct evhttp_request* req;
74 : : const util::SignalInterrupt& m_interrupt;
75 : : bool replySent;
76 : :
77 : : public:
78 : : explicit HTTPRequest(struct evhttp_request* req, const util::SignalInterrupt& interrupt, bool replySent = false);
79 : : ~HTTPRequest();
80 : :
81 : : enum RequestMethod {
82 : : UNKNOWN,
83 : : GET,
84 : : POST,
85 : : HEAD,
86 : : PUT
87 : : };
88 : :
89 : : /** Get requested URI.
90 : : */
91 : : std::string GetURI() const;
92 : :
93 : : /** Get CService (address:ip) for the origin of the http request.
94 : : */
95 : : CService GetPeer() const;
96 : :
97 : : /** Get request method.
98 : : */
99 : : RequestMethod GetRequestMethod() const;
100 : :
101 : : /** Get the query parameter value from request uri for a specified key, or std::nullopt if the
102 : : * key is not found.
103 : : *
104 : : * If the query string contains duplicate keys, the first value is returned. Many web frameworks
105 : : * would instead parse this as an array of values, but this is not (yet) implemented as it is
106 : : * currently not needed in any of the endpoints.
107 : : *
108 : : * @param[in] key represents the query parameter of which the value is returned
109 : : */
110 : : std::optional<std::string> GetQueryParameter(const std::string& key) const;
111 : :
112 : : /**
113 : : * Get the request header specified by hdr, or an empty string.
114 : : * Return a pair (isPresent,string).
115 : : */
116 : : std::pair<bool, std::string> GetHeader(const std::string& hdr) const;
117 : :
118 : : /**
119 : : * Read request body.
120 : : *
121 : : * @note As this consumes the underlying buffer, call this only once.
122 : : * Repeated calls will return an empty string.
123 : : */
124 : : std::string ReadBody();
125 : :
126 : : /**
127 : : * Write output header.
128 : : *
129 : : * @note call this before calling WriteErrorReply or Reply.
130 : : */
131 : : void WriteHeader(const std::string& hdr, const std::string& value);
132 : :
133 : : /**
134 : : * Write HTTP reply.
135 : : * nStatus is the HTTP status code to send.
136 : : * reply is the body of the reply. Keep it empty to send a standard message.
137 : : *
138 : : * @note Can be called only once. As this will give the request back to the
139 : : * main thread, do not call any other HTTPRequest methods after calling this.
140 : : */
141 [ + - - - : 188037 : void WriteReply(int nStatus, std::string_view reply = "")
+ - ][ - -
+ - - - +
- + - - -
+ - ]
142 : : {
143 : 188004 : WriteReply(nStatus, std::as_bytes(std::span{reply}));
144 : 188004 : }
145 : : void WriteReply(int nStatus, std::span<const std::byte> reply);
146 : : };
147 : :
148 : : /** Get the query parameter value from request uri for a specified key, or std::nullopt if the key
149 : : * is not found.
150 : : *
151 : : * If the query string contains duplicate keys, the first value is returned. Many web frameworks
152 : : * would instead parse this as an array of values, but this is not (yet) implemented as it is
153 : : * currently not needed in any of the endpoints.
154 : : *
155 : : * Helper function for HTTPRequest::GetQueryParameter.
156 : : *
157 : : * @param[in] uri is the entire request uri
158 : : * @param[in] key represents the query parameter of which the value is returned
159 : : */
160 : : std::optional<std::string> GetQueryParameterFromUri(const char* uri, const std::string& key);
161 : :
162 : : /** Event handler closure.
163 : : */
164 [ + - ]: 188006 : class HTTPClosure
165 : : {
166 : : public:
167 : : virtual void operator()() = 0;
168 : 0 : virtual ~HTTPClosure() = default;
169 : : };
170 : :
171 : : /** Event class. This can be used either as a cross-thread trigger or as a timer.
172 : : */
173 : : class HTTPEvent
174 : : {
175 : : public:
176 : : /** Create a new event.
177 : : * deleteWhenTriggered deletes this event object after the event is triggered (and the handler called)
178 : : * handler is the handler to call when the event is triggered.
179 : : */
180 : : HTTPEvent(struct event_base* base, bool deleteWhenTriggered, const std::function<void()>& handler);
181 : : ~HTTPEvent();
182 : :
183 : : /** Trigger the event. If tv is 0, trigger it immediately. Otherwise trigger it after
184 : : * the given time has elapsed.
185 : : */
186 : : void trigger(struct timeval* tv);
187 : :
188 : : bool deleteWhenTriggered;
189 : : std::function<void()> handler;
190 : : private:
191 : : struct event* ev;
192 : : };
193 : :
194 : : #endif // BITCOIN_HTTPSERVER_H
|