Coverage Report

Created: 2024-09-19 18:47

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