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 <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 : 0 : class HTTPClosure 151 : : { 152 : : public: 153 : : virtual void operator()() = 0; 154 : 0 : 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