Skip to content

Commit 18d0ebd

Browse files
committed
Merge 27cfaee into merged_master (Bitcoin PR bitcoin/bitcoin#24098)
2 parents 7381c88 + 27cfaee commit 18d0ebd

File tree

11 files changed

+333
-95
lines changed

11 files changed

+333
-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 24.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 24.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: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
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)
21+
22+
(#24098)

src/Makefile.am

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -219,6 +219,7 @@ BITCOIN_CORE_H = \
219219
psbt.h \
220220
random.h \
221221
randomenv.h \
222+
rest.h \
222223
reverse_iterator.h \
223224
rpc/blockchain.h \
224225
rpc/client.h \

src/Makefile.test.include

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,7 @@ BITCOIN_TESTS =\
9696
test/fs_tests.cpp \
9797
test/getarg_tests.cpp \
9898
test/hash_tests.cpp \
99+
test/httpserver_tests.cpp \
99100
test/i2p_tests.cpp \
100101
test/interfaces_tests.cpp \
101102
test/key_io_tests.cpp \
@@ -118,6 +119,7 @@ BITCOIN_TESTS =\
118119
test/prevector_tests.cpp \
119120
test/raii_event_tests.cpp \
120121
test/random_tests.cpp \
122+
test/rest_tests.cpp \
121123
test/reverselock_tests.cpp \
122124
test/rpc_tests.cpp \
123125
test/sanity_tests.cpp \

src/httpserver.cpp

Lines changed: 35 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,18 +23,20 @@
2323

2424
#include <deque>
2525
#include <memory>
26+
#include <optional>
2627
#include <stdio.h>
2728
#include <stdlib.h>
2829
#include <string>
2930

3031
#include <sys/types.h>
3132
#include <sys/stat.h>
3233

33-
#include <event2/thread.h>
3434
#include <event2/buffer.h>
3535
#include <event2/bufferevent.h>
36-
#include <event2/util.h>
36+
#include <event2/http.h>
3737
#include <event2/keyvalq_struct.h>
38+
#include <event2/thread.h>
39+
#include <event2/util.h>
3840

3941
#include <support/events.h>
4042

@@ -639,6 +641,37 @@ HTTPRequest::RequestMethod HTTPRequest::GetRequestMethod() const
639641
}
640642
}
641643

644+
std::optional<std::string> HTTPRequest::GetQueryParameter(const std::string& key) const
645+
{
646+
const char* uri{evhttp_request_get_uri(req)};
647+
648+
return GetQueryParameterFromUri(uri, key);
649+
}
650+
651+
std::optional<std::string> GetQueryParameterFromUri(const char* uri, const std::string& key)
652+
{
653+
evhttp_uri* uri_parsed{evhttp_uri_parse(uri)};
654+
const char* query{evhttp_uri_get_query(uri_parsed)};
655+
std::optional<std::string> result;
656+
657+
if (query) {
658+
// Parse the query string into a key-value queue and iterate over it
659+
struct evkeyvalq params_q;
660+
evhttp_parse_query_str(query, &params_q);
661+
662+
for (struct evkeyval* param{params_q.tqh_first}; param != nullptr; param = param->next.tqe_next) {
663+
if (param->key == key) {
664+
result = param->value;
665+
break;
666+
}
667+
}
668+
evhttp_clear_headers(&params_q);
669+
}
670+
evhttp_uri_free(uri_parsed);
671+
672+
return result;
673+
}
674+
642675
void RegisterHTTPHandler(const std::string &prefix, bool exactMatch, const HTTPRequestHandler &handler)
643676
{
644677
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;
@@ -83,6 +84,17 @@ class HTTPRequest
8384
*/
8485
RequestMethod GetRequestMethod() const;
8586

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

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

0 commit comments

Comments
 (0)