mirror of
https://github.com/bitcoin/bitcoin.git
synced 2025-02-03 09:56:38 -05:00
Add GetQueryParameter helper function
Easily get the query parameter from the URI, with optional default value.
This commit is contained in:
parent
fff771ee86
commit
a09497614e
4 changed files with 101 additions and 3 deletions
|
@ -95,6 +95,7 @@ BITCOIN_TESTS =\
|
||||||
test/fs_tests.cpp \
|
test/fs_tests.cpp \
|
||||||
test/getarg_tests.cpp \
|
test/getarg_tests.cpp \
|
||||||
test/hash_tests.cpp \
|
test/hash_tests.cpp \
|
||||||
|
test/httpserver_tests.cpp \
|
||||||
test/i2p_tests.cpp \
|
test/i2p_tests.cpp \
|
||||||
test/interfaces_tests.cpp \
|
test/interfaces_tests.cpp \
|
||||||
test/key_io_tests.cpp \
|
test/key_io_tests.cpp \
|
||||||
|
|
|
@ -23,6 +23,7 @@
|
||||||
|
|
||||||
#include <deque>
|
#include <deque>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
#include <optional>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
@ -30,11 +31,12 @@
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
|
|
||||||
#include <event2/thread.h>
|
|
||||||
#include <event2/buffer.h>
|
#include <event2/buffer.h>
|
||||||
#include <event2/bufferevent.h>
|
#include <event2/bufferevent.h>
|
||||||
#include <event2/util.h>
|
#include <event2/http.h>
|
||||||
#include <event2/keyvalq_struct.h>
|
#include <event2/keyvalq_struct.h>
|
||||||
|
#include <event2/thread.h>
|
||||||
|
#include <event2/util.h>
|
||||||
|
|
||||||
#include <support/events.h>
|
#include <support/events.h>
|
||||||
|
|
||||||
|
@ -639,6 +641,37 @@ HTTPRequest::RequestMethod HTTPRequest::GetRequestMethod() const
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::optional<std::string> HTTPRequest::GetQueryParameter(const std::string& key) const
|
||||||
|
{
|
||||||
|
const char* uri{evhttp_request_get_uri(req)};
|
||||||
|
|
||||||
|
return GetQueryParameterFromUri(uri, key);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::optional<std::string> GetQueryParameterFromUri(const char* uri, const std::string& key)
|
||||||
|
{
|
||||||
|
evhttp_uri* uri_parsed{evhttp_uri_parse(uri)};
|
||||||
|
const char* query{evhttp_uri_get_query(uri_parsed)};
|
||||||
|
std::optional<std::string> result;
|
||||||
|
|
||||||
|
if (query) {
|
||||||
|
// Parse the query string into a key-value queue and iterate over it
|
||||||
|
struct evkeyvalq params_q;
|
||||||
|
evhttp_parse_query_str(query, ¶ms_q);
|
||||||
|
|
||||||
|
for (struct evkeyval* param{params_q.tqh_first}; param != nullptr; param = param->next.tqe_next) {
|
||||||
|
if (param->key == key) {
|
||||||
|
result = param->value;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
evhttp_clear_headers(¶ms_q);
|
||||||
|
}
|
||||||
|
evhttp_uri_free(uri_parsed);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
void RegisterHTTPHandler(const std::string &prefix, bool exactMatch, const HTTPRequestHandler &handler)
|
void RegisterHTTPHandler(const std::string &prefix, bool exactMatch, const HTTPRequestHandler &handler)
|
||||||
{
|
{
|
||||||
LogPrint(BCLog::HTTP, "Registering HTTP handler for %s (exactmatch %d)\n", prefix, exactMatch);
|
LogPrint(BCLog::HTTP, "Registering HTTP handler for %s (exactmatch %d)\n", prefix, exactMatch);
|
||||||
|
|
|
@ -5,8 +5,9 @@
|
||||||
#ifndef BITCOIN_HTTPSERVER_H
|
#ifndef BITCOIN_HTTPSERVER_H
|
||||||
#define BITCOIN_HTTPSERVER_H
|
#define BITCOIN_HTTPSERVER_H
|
||||||
|
|
||||||
#include <string>
|
|
||||||
#include <functional>
|
#include <functional>
|
||||||
|
#include <optional>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
static const int DEFAULT_HTTP_THREADS=4;
|
static const int DEFAULT_HTTP_THREADS=4;
|
||||||
static const int DEFAULT_HTTP_WORKQUEUE=16;
|
static const int DEFAULT_HTTP_WORKQUEUE=16;
|
||||||
|
@ -83,6 +84,17 @@ public:
|
||||||
*/
|
*/
|
||||||
RequestMethod GetRequestMethod() const;
|
RequestMethod GetRequestMethod() const;
|
||||||
|
|
||||||
|
/** Get the query parameter value from request uri for a specified key, or std::nullopt if the
|
||||||
|
* key is not found.
|
||||||
|
*
|
||||||
|
* If the query string contains duplicate keys, the first value is returned. Many web frameworks
|
||||||
|
* would instead parse this as an array of values, but this is not (yet) implemented as it is
|
||||||
|
* currently not needed in any of the endpoints.
|
||||||
|
*
|
||||||
|
* @param[in] key represents the query parameter of which the value is returned
|
||||||
|
*/
|
||||||
|
std::optional<std::string> GetQueryParameter(const std::string& key) const;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the request header specified by hdr, or an empty string.
|
* Get the request header specified by hdr, or an empty string.
|
||||||
* Return a pair (isPresent,string).
|
* Return a pair (isPresent,string).
|
||||||
|
@ -115,6 +127,20 @@ public:
|
||||||
void WriteReply(int nStatus, const std::string& strReply = "");
|
void WriteReply(int nStatus, const std::string& strReply = "");
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/** Get the query parameter value from request uri for a specified key, or std::nullopt if the key
|
||||||
|
* is not found.
|
||||||
|
*
|
||||||
|
* If the query string contains duplicate keys, the first value is returned. Many web frameworks
|
||||||
|
* would instead parse this as an array of values, but this is not (yet) implemented as it is
|
||||||
|
* currently not needed in any of the endpoints.
|
||||||
|
*
|
||||||
|
* Helper function for HTTPRequest::GetQueryParameter.
|
||||||
|
*
|
||||||
|
* @param[in] uri is the entire request uri
|
||||||
|
* @param[in] key represents the query parameter of which the value is returned
|
||||||
|
*/
|
||||||
|
std::optional<std::string> GetQueryParameterFromUri(const char* uri, const std::string& key);
|
||||||
|
|
||||||
/** Event handler closure.
|
/** Event handler closure.
|
||||||
*/
|
*/
|
||||||
class HTTPClosure
|
class HTTPClosure
|
||||||
|
|
38
src/test/httpserver_tests.cpp
Normal file
38
src/test/httpserver_tests.cpp
Normal file
|
@ -0,0 +1,38 @@
|
||||||
|
// Copyright (c) 2012-2022 The Bitcoin Core developers
|
||||||
|
// Distributed under the MIT software license, see the accompanying
|
||||||
|
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||||
|
|
||||||
|
#include <httpserver.h>
|
||||||
|
#include <test/util/setup_common.h>
|
||||||
|
|
||||||
|
#include <boost/test/unit_test.hpp>
|
||||||
|
|
||||||
|
BOOST_FIXTURE_TEST_SUITE(httpserver_tests, BasicTestingSetup)
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(test_query_parameters)
|
||||||
|
{
|
||||||
|
std::string uri {};
|
||||||
|
|
||||||
|
// No parameters
|
||||||
|
uri = "localhost:8080/rest/headers/someresource.json";
|
||||||
|
BOOST_CHECK(!GetQueryParameterFromUri(uri.c_str(), "p1").has_value());
|
||||||
|
|
||||||
|
// Single parameter
|
||||||
|
uri = "localhost:8080/rest/endpoint/someresource.json?p1=v1";
|
||||||
|
BOOST_CHECK_EQUAL(GetQueryParameterFromUri(uri.c_str(), "p1").value(), "v1");
|
||||||
|
BOOST_CHECK(!GetQueryParameterFromUri(uri.c_str(), "p2").has_value());
|
||||||
|
|
||||||
|
// Multiple parameters
|
||||||
|
uri = "/rest/endpoint/someresource.json?p1=v1&p2=v2";
|
||||||
|
BOOST_CHECK_EQUAL(GetQueryParameterFromUri(uri.c_str(), "p1").value(), "v1");
|
||||||
|
BOOST_CHECK_EQUAL(GetQueryParameterFromUri(uri.c_str(), "p2").value(), "v2");
|
||||||
|
|
||||||
|
// If the query string contains duplicate keys, the first value is returned
|
||||||
|
uri = "/rest/endpoint/someresource.json?p1=v1&p1=v2";
|
||||||
|
BOOST_CHECK_EQUAL(GetQueryParameterFromUri(uri.c_str(), "p1").value(), "v1");
|
||||||
|
|
||||||
|
// Invalid query string syntax is the same as not having parameters
|
||||||
|
uri = "/rest/endpoint/someresource.json&p1=v1&p2=v2";
|
||||||
|
BOOST_CHECK(!GetQueryParameterFromUri(uri.c_str(), "p1").has_value());
|
||||||
|
}
|
||||||
|
BOOST_AUTO_TEST_SUITE_END()
|
Loading…
Add table
Reference in a new issue