httpserver.h
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 <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<void(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 void WriteReply(int nStatus, std::string_view reply = "") 142 { 143 WriteReply(nStatus, std::as_bytes(std::span{reply})); 144 } 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 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