Skip to content

Commit 624727f

Browse files
committed
merge bitcoin#24098: Use query parameters to control resource loading
1 parent 9a35783 commit 624727f

File tree

11 files changed

+332
-95
lines changed

11 files changed

+332
-95
lines changed

doc/REST-interface.md

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -47,18 +47,24 @@ The HTTP request and response are both handled entirely in-memory.
4747
With the /notxdetails/ option JSON response will only contain the transaction hash instead of the complete transaction details. The option only affects the JSON response.
4848

4949
#### Blockheaders
50-
`GET /rest/headers/<COUNT>/<BLOCK-HASH>.<bin|hex|json>`
50+
`GET /rest/headers/<BLOCK-HASH>.<bin|hex|json>?count=<COUNT=5>`
5151

5252
Given a block hash: returns <COUNT> amount of blockheaders in upward direction.
5353
Returns empty if the block doesn't exist or it isn't in the active chain.
5454

55+
*Deprecated (but not removed) since 23.0:*
56+
`GET /rest/headers/<COUNT>/<BLOCK-HASH>.<bin|hex|json>`
57+
5558
#### Blockfilter Headers
56-
`GET /rest/blockfilterheaders/<FILTERTYPE>/<COUNT>/<BLOCK-HASH>.<bin|hex|json>`
59+
`GET /rest/blockfilterheaders/<FILTERTYPE>/<BLOCK-HASH>.<bin|hex|json>?count=<COUNT=5>`
5760

5861
Given a block hash: returns <COUNT> amount of blockfilter headers in upward
5962
direction for the filter type <FILTERTYPE>.
6063
Returns empty if the block doesn't exist or it isn't in the active chain.
6164

65+
*Deprecated (but not removed) since 23.0:*
66+
`GET /rest/blockfilterheaders/<FILTERTYPE>/<COUNT>/<BLOCK-HASH>.<bin|hex|json>`
67+
6268
#### Blockfilters
6369
`GET /rest/blockfilter/<FILTERTYPE>/<BLOCK-HASH>.<bin|hex|json>`
6470

doc/release-notes-24098.md

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
Notable changes
2+
===============
3+
4+
Updated REST APIs
5+
-----------------
6+
7+
- The `/headers/` and `/blockfilterheaders/` endpoints have been updated to use
8+
a query parameter instead of path parameter to specify the result count. The
9+
count parameter is now optional, and defaults to 5 for both endpoints. The old
10+
endpoints are still functional, and have no documented behaviour change.
11+
12+
For `/headers`, use
13+
`GET /rest/headers/<BLOCK-HASH>.<bin|hex|json>?count=<COUNT=5>`
14+
instead of
15+
`GET /rest/headers/<COUNT>/<BLOCK-HASH>.<bin|hex|json>` (deprecated)
16+
17+
For `/blockfilterheaders/`, use
18+
`GET /rest/blockfilterheaders/<FILTERTYPE>/<BLOCK-HASH>.<bin|hex|json>?count=<COUNT=5>`
19+
instead of
20+
`GET /rest/blockfilterheaders/<FILTERTYPE>/<COUNT>/<BLOCK-HASH>.<bin|hex|json>` (deprecated)

src/Makefile.am

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -302,6 +302,7 @@ BITCOIN_CORE_H = \
302302
psbt.h \
303303
random.h \
304304
randomenv.h \
305+
rest.h \
305306
rpc/blockchain.h \
306307
rpc/client.h \
307308
rpc/evo_util.h \

src/Makefile.test.include

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -121,6 +121,7 @@ BITCOIN_TESTS =\
121121
test/getarg_tests.cpp \
122122
test/governance_validators_tests.cpp \
123123
test/hash_tests.cpp \
124+
test/httpserver_tests.cpp \
124125
test/i2p_tests.cpp \
125126
test/interfaces_tests.cpp \
126127
test/key_io_tests.cpp \
@@ -156,6 +157,7 @@ BITCOIN_TESTS =\
156157
test/raii_event_tests.cpp \
157158
test/random_tests.cpp \
158159
test/ratecheck_tests.cpp \
160+
test/rest_tests.cpp \
159161
test/reverselock_tests.cpp \
160162
test/rpc_tests.cpp \
161163
test/sanity_tests.cpp \

src/httpserver.cpp

Lines changed: 35 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,15 +21,17 @@
2121

2222
#include <cstdio>
2323
#include <deque>
24+
#include <optional>
2425
#include <string>
2526

2627
#include <sys/types.h>
2728

28-
#include <event2/thread.h>
2929
#include <event2/buffer.h>
3030
#include <event2/bufferevent.h>
31-
#include <event2/util.h>
31+
#include <event2/http.h>
3232
#include <event2/keyvalq_struct.h>
33+
#include <event2/thread.h>
34+
#include <event2/util.h>
3335

3436
#include <support/events.h>
3537

@@ -670,6 +672,37 @@ HTTPRequest::RequestMethod HTTPRequest::GetRequestMethod() const
670672
}
671673
}
672674

675+
std::optional<std::string> HTTPRequest::GetQueryParameter(const std::string& key) const
676+
{
677+
const char* uri{evhttp_request_get_uri(req)};
678+
679+
return GetQueryParameterFromUri(uri, key);
680+
}
681+
682+
std::optional<std::string> GetQueryParameterFromUri(const char* uri, const std::string& key)
683+
{
684+
evhttp_uri* uri_parsed{evhttp_uri_parse(uri)};
685+
const char* query{evhttp_uri_get_query(uri_parsed)};
686+
std::optional<std::string> result;
687+
688+
if (query) {
689+
// Parse the query string into a key-value queue and iterate over it
690+
struct evkeyvalq params_q;
691+
evhttp_parse_query_str(query, &params_q);
692+
693+
for (struct evkeyval* param{params_q.tqh_first}; param != nullptr; param = param->next.tqe_next) {
694+
if (param->key == key) {
695+
result = param->value;
696+
break;
697+
}
698+
}
699+
evhttp_clear_headers(&params_q);
700+
}
701+
evhttp_uri_free(uri_parsed);
702+
703+
return result;
704+
}
705+
673706
void RegisterHTTPHandler(const std::string &prefix, bool exactMatch, const HTTPRequestHandler &handler)
674707
{
675708
LogPrint(BCLog::HTTP, "Registering HTTP handler for %s (exactmatch %d)\n", prefix, exactMatch);

src/httpserver.h

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,9 @@
55
#ifndef BITCOIN_HTTPSERVER_H
66
#define BITCOIN_HTTPSERVER_H
77

8-
#include <string>
98
#include <functional>
9+
#include <optional>
10+
#include <string>
1011

1112
static const int DEFAULT_HTTP_THREADS=4;
1213
static const int DEFAULT_HTTP_WORKQUEUE=16;
@@ -82,6 +83,17 @@ class HTTPRequest
8283
*/
8384
RequestMethod GetRequestMethod() const;
8485

86+
/** Get the query parameter value from request uri for a specified key, or std::nullopt if the
87+
* key is not found.
88+
*
89+
* If the query string contains duplicate keys, the first value is returned. Many web frameworks
90+
* would instead parse this as an array of values, but this is not (yet) implemented as it is
91+
* currently not needed in any of the endpoints.
92+
*
93+
* @param[in] key represents the query parameter of which the value is returned
94+
*/
95+
std::optional<std::string> GetQueryParameter(const std::string& key) const;
96+
8597
/**
8698
* Get the request header specified by hdr, or an empty string.
8799
* Return a pair (isPresent,string).
@@ -114,6 +126,20 @@ class HTTPRequest
114126
void WriteReply(int nStatus, const std::string& strReply = "");
115127
};
116128

129+
/** Get the query parameter value from request uri for a specified key, or std::nullopt if the key
130+
* is not found.
131+
*
132+
* If the query string contains duplicate keys, the first value is returned. Many web frameworks
133+
* would instead parse this as an array of values, but this is not (yet) implemented as it is
134+
* currently not needed in any of the endpoints.
135+
*
136+
* Helper function for HTTPRequest::GetQueryParameter.
137+
*
138+
* @param[in] uri is the entire request uri
139+
* @param[in] key represents the query parameter of which the value is returned
140+
*/
141+
std::optional<std::string> GetQueryParameterFromUri(const char* uri, const std::string& key);
142+
117143
/** Event handler closure.
118144
*/
119145
class HTTPClosure

0 commit comments

Comments
 (0)