Decoupled RequestContext from MHD_Connection

This will simplify testing of Response utilities.
This commit is contained in:
Veloman Yunkan 2023-12-05 17:48:10 +04:00
parent af228bf45f
commit aee6c23082
4 changed files with 47 additions and 23 deletions

View File

@ -513,6 +513,19 @@ static MHD_Result staticHandlerCallback(void* cls,
cont_cls);
}
namespace
{
MHD_Result add_name_value_pair(void *nvp, enum MHD_ValueKind kind,
const char *key, const char *value)
{
auto& nameValuePairs = *reinterpret_cast<RequestContext::NameValuePairs*>(nvp);
nameValuePairs.push_back({key, value});
return MHD_YES;
}
} // unnamed namespace
MHD_Result InternalServer::handlerCallback(struct MHD_Connection* connection,
const char* fullUrl,
const char* method,
@ -529,7 +542,10 @@ MHD_Result InternalServer::handlerCallback(struct MHD_Connection* connection,
}
const auto url = fullURL2LocalURL(fullUrl, m_rootPrefixOfDecodedURL);
RequestContext request(connection, m_root, url, method, version);
RequestContext::NameValuePairs headers, queryArgs;
MHD_get_connection_values(connection, MHD_HEADER_KIND, add_name_value_pair, &headers);
MHD_get_connection_values(connection, MHD_GET_ARGUMENT_KIND, add_name_value_pair, &queryArgs);
RequestContext request(m_root, url, method, version, headers, queryArgs);
if (m_verbose.load() ) {
request.print_debug_info();

View File

@ -51,11 +51,12 @@ RequestMethod str2RequestMethod(const std::string& method) {
} // unnamed namespace
RequestContext::RequestContext(struct MHD_Connection* connection,
const std::string& _rootLocation, // URI-encoded
RequestContext::RequestContext(const std::string& _rootLocation, // URI-encoded
const std::string& unrootedUrl, // URI-decoded
const std::string& _method,
const std::string& version) :
const std::string& version,
const NameValuePairs& headers,
const NameValuePairs& queryArgs) :
rootLocation(_rootLocation),
url(unrootedUrl),
method(str2RequestMethod(_method)),
@ -64,8 +65,13 @@ RequestContext::RequestContext(struct MHD_Connection* connection,
acceptEncodingGzip(false),
byteRange_()
{
MHD_get_connection_values(connection, MHD_HEADER_KIND, &RequestContext::fill_header, this);
MHD_get_connection_values(connection, MHD_GET_ARGUMENT_KIND, &RequestContext::fill_argument, this);
for ( const auto& kv : headers ) {
add_header(kv.first, kv.second);
}
for ( const auto& kv : queryArgs ) {
add_argument(kv.first, kv.second);
}
try {
acceptEncodingGzip =
@ -82,18 +88,14 @@ RequestContext::RequestContext(struct MHD_Connection* connection,
RequestContext::~RequestContext()
{}
MHD_Result RequestContext::fill_header(void *__this, enum MHD_ValueKind kind,
const char *key, const char *value)
void RequestContext::add_header(const char *key, const char *value)
{
RequestContext *_this = static_cast<RequestContext*>(__this);
_this->headers[lcAll(key)] = value;
return MHD_YES;
this->headers[lcAll(key)] = value;
}
MHD_Result RequestContext::fill_argument(void *__this, enum MHD_ValueKind kind,
const char *key, const char* value)
void RequestContext::add_argument(const char *key, const char* value)
{
RequestContext *_this = static_cast<RequestContext*>(__this);
RequestContext *_this = this;
_this->arguments[key].push_back(value == nullptr ? "" : value);
if ( ! _this->queryString.empty() ) {
_this->queryString += "&";
@ -103,7 +105,6 @@ MHD_Result RequestContext::fill_argument(void *__this, enum MHD_ValueKind kind,
_this->queryString += "=";
_this->queryString += urlEncode(value);
}
return MHD_YES;
}
void RequestContext::print_debug_info() const {

View File

@ -55,12 +55,17 @@ class IndexError: public std::runtime_error {};
class RequestContext {
public: // types
typedef std::vector<std::pair<const char*, const char*>> NameValuePairs;
public: // functions
RequestContext(struct MHD_Connection* connection,
const std::string& rootLocation, // URI-encoded
RequestContext(const std::string& rootLocation, // URI-encoded
const std::string& unrootedUrl, // URI-decoded
const std::string& method,
const std::string& version);
const std::string& version,
const NameValuePairs& headers,
const NameValuePairs& queryArgs);
~RequestContext();
void print_debug_info() const;
@ -151,8 +156,8 @@ class RequestContext {
private: // functions
UserLanguage determine_user_language() const;
static MHD_Result fill_header(void *, enum MHD_ValueKind, const char*, const char*);
static MHD_Result fill_argument(void *, enum MHD_ValueKind, const char*, const char*);
void add_header(const char* name, const char* value);
void add_argument(const char* name, const char* value);
};
template<> std::string RequestContext::get_argument(const std::string& name) const;

View File

@ -8,9 +8,11 @@ namespace
using namespace kiwix;
RequestContext makeHttpGetRequest(const std::string& url)
RequestContext makeHttpGetRequest(const std::string& url,
const RequestContext::NameValuePairs& headers,
const RequestContext::NameValuePairs& queryArgs)
{
return RequestContext(nullptr, "", url, "GET", "1.1");
return RequestContext("", url, "GET", "1.1", headers, queryArgs);
}
std::string getResponseContent(const ContentResponseBlueprint& crb)
@ -23,7 +25,7 @@ std::string getResponseContent(const ContentResponseBlueprint& crb)
TEST(HTTPErrorResponse, shouldBeInEnglishByDefault) {
const RequestContext req = makeHttpGetRequest("/asdf");
const RequestContext req = makeHttpGetRequest("/asdf", {}, {});
HTTPErrorResponse errResp(req, MHD_HTTP_NOT_FOUND,
"404-page-title",
"404-page-heading",