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