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