/ 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 <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<bool(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 handler closure.
163   */
164  class HTTPClosure
165  {
166  public:
167      virtual void operator()() = 0;
168      virtual ~HTTPClosure() = default;
169  };
170  
171  /** Event class. This can be used either as a cross-thread trigger or as a timer.
172   */
173  class HTTPEvent
174  {
175  public:
176      /** Create a new event.
177       * deleteWhenTriggered deletes this event object after the event is triggered (and the handler called)
178       * handler is the handler to call when the event is triggered.
179       */
180      HTTPEvent(struct event_base* base, bool deleteWhenTriggered, const std::function<void()>& handler);
181      ~HTTPEvent();
182  
183      /** Trigger the event. If tv is 0, trigger it immediately. Otherwise trigger it after
184       * the given time has elapsed.
185       */
186      void trigger(struct timeval* tv);
187  
188      bool deleteWhenTriggered;
189      std::function<void()> handler;
190  private:
191      struct event* ev;
192  };
193  
194  #endif // BITCOIN_HTTPSERVER_H