/root/bitcoin/src/httpserver.h
Line | Count | Source (jump to first uncovered line) |
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 | | void WriteReply(int nStatus, std::string_view reply = "") |
133 | 0 | { |
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 | | 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 |