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