/ src / httpserver.h
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