1
\$\begingroup\$

If you want all the code in a buildable format from the last 10 or so posts. You can find it here:

The PathMatcher object allows you to register paths with named sections of the path. But there are other vaiables available in the reuest. I want to make all the variables available to the lambda in a logic way.

So I have a wrapper class that Implements the PyntHttp interface and uses the PathMatcher to check if a request has a handler. If it does then we combine the header parameters query parameters and path match parameters into the variables() object to be used by the lambda:

HTTPHandler.h

#ifndef THORSANVIL_NISSE_NISSEHTTP_HTTP_HANDLER_H
#define THORSANVIL_NISSE_NISSEHTTP_HTTP_HANDLER_H
#include "NisseHTTPConfig.h"
#include "PyntHTTP.h"
#include "PathMatcher.h"
#include "Util.h"
#include <string_view>
namespace ThorsAnvil::Nisse::NisseHTTP
{
class HeaderRequest;
class HTTPHandler: public PyntHTTP
{
 using HTTPAction = std::function<void(Request& request, Response& response)>;
 PathMatcher pathMatcher;
 std::vector<HTTPAction> actions;
 public:
 virtual void processRequest(Request& request, Response& response);
 void addPath(std::string const& path, HTTPAction&& action);
 private:
 std::string normalize(std::string_view path);
 void addHeaders(RequestVariables& var, HeaderRequest const& headers);
 void addQueryParam(RequestVariables& var, std::string_view query);
 void addPathMatch(RequestVariables& var, Match const& matches);
};
}
#endif

HTTPHandler.cpp

#include "HTTPHandler.h"
#include "Request.h"
#include "Response.h"
using namespace ThorsAnvil::Nisse::NisseHTTP;
std::string HTTPHandler::normalize(std::string_view path)
{
 return std::string(path);
}
void HTTPHandler::processRequest(Request& request, Response& response)
{
 std::string path = normalize(request.getUrl().pathname());
 if (!pathMatcher.findMatch(path, request, response)) {
 response.setStatus(404);
 }
}
void HTTPHandler::addHeaders(RequestVariables& var, HeaderRequest const& headers)
{
 for (auto const& head: headers) {
 var[head.first] = head.second.back();
 }
}
void HTTPHandler::addQueryParam(RequestVariables& var, std::string_view query)
{
 // Add URL paramets to the variables object.
 if (query.size() == 0) {
 return;
 }
 // Remove the first ? or &
 query.remove_prefix(1);
 std::smatch queryParamMatch;
 std::regex queryParamExpr{"([^=]*)=([^&]*)&"};
 std::string queryStr(query);
 queryStr += "&";
 while (std::regex_search(queryStr, queryParamMatch, queryParamExpr))
 {
 var[queryParamMatch[1].str()] = queryParamMatch[2].str();
 queryStr = queryParamMatch.suffix().str();
 }
}
void HTTPHandler::addPathMatch(RequestVariables& var, Match const& matches)
{
 for (auto const& match: matches) {
 var[match.first] = match.second;
 }
}
void HTTPHandler::addPath(std::string const& path, HTTPAction&& action)
{
 actions.emplace_back(std::move(action));
 pathMatcher.addPath(path, [&, actionId = actions.size() - 1](Match const& matches, Request& request, Response& response)
 {
 // Get the variable object
 RequestVariables& var = request.variables();
 addHeaders(var, request.headers());
 addQueryParam(var, request.getUrl().query());
 addPathMatch(var, matches);
 actions[actionId](request, response);
 });
}

Hello World

We can now simplify the Hello World handler to:

 // Processes HTTP connection on port.
 ThorsAnvil::Nisse::NisseHTTP::HTTPHandler http;
 http.addPath("/HW-Length{Who}.html", [](ThorsAnvil::Nisse::NisseHTTP::Request& request, ThorsAnvil::Nisse::NisseHTTP::Response& response)
 {
 std::string who = request.variables()["Who"];
 std::string page = R"(
<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN">
<html>
<head><title>Nisse server 1.1</title></head>
<body>Hello world: )" + who + R"(</body>
</html>
)";
 ThorsAnvil::Nisse::NisseHTTP::HeaderResponse header;
 response.addHeaders(header, page.size()) << page;
 });
 http.addPath("/HW-Chunked{Who}.html", [](ThorsAnvil::Nisse::NisseHTTP::Request& request, ThorsAnvil::Nisse::NisseHTTP::Response& response)
 {
 ThorsAnvil::Nisse::NisseHTTP::HeaderResponse header;
 response.addHeaders(header, ThorsAnvil::Nisse::NisseHTTP::Encoding::Chunked) << R"(
<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN">
<html>
<head><title>Nisse server 1.1</title></head>
<body>Hello world: )" << request.variables()["Who"] << R"(</body>
</html>
)";
 });
asked Oct 21, 2024 at 18:22
\$\endgroup\$

0

Know someone who can answer? Share a link to this question via email, Twitter, or Facebook.

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.