2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
42#include "express/dispatcher/RouterDispatcher.h"
44#include "core/socket/stream/SocketConnection.h"
45#include "express/Controller.h"
46#include "express/Request.h"
47#include "express/Response.h"
48#include "express/Route.h"
49#include "express/dispatcher/regex_utils.h"
50#include "web/http/server/SocketContext.h"
52#ifndef DOXYGEN_SHOULD_SKIP_THIS
54#include "log/Logger.h"
59#include <unordered_map>
74 return oldStrictRouting;
86 return oldCaseInsensitiveRouting;
95 bool dispatched =
false;
100 std::string_view mountPath;
101 std::string_view mountQueryString;
103 const std::unordered_map<std::string, std::string> requiredQueryPairs =
parseQuery(mountQueryString
);
105 std::string_view requestPath;
106 std::string_view requestQueryString;
108 const std::unordered_map<std::string, std::string> requestQueryPairs =
parseQuery(requestQueryString
);
115 if (mountPath.empty()) {
120 bool pathMatches =
false;
121 if (absoluteMountPath.find(
':') != std::string::npos) {
122 if (regex.mark_count() == 0) {
123 LOG(TRACE) <<
"RouterDispatcher: precompiled regex";
129 LOG(TRACE) <<
"RouterDispatcher: using precompiled regex";
138 const bool requestMatched = (pathMatches && queryMatches);
141 <<
" HTTP Express: router -> " << (requestMatched ?
"MATCH" :
"NO MATCH");
145 LOG(TRACE) <<
" AbsoluteMountPath: " << absoluteMountPath;
149 if (requestMatched) {
151 std::size_t consumedLength = 0;
152 if (absoluteMountPath.find(
':') != std::string::npos) {
154 std::cmatch regexMatches;
155 auto [regex, names] =
157 if (!std::regex_search(requestPath.begin(), requestPath.end(), regexMatches, regex)) {
160 consumedLength =
static_cast<std::size_t>(regexMatches.length(0));
163 consumedLength = mountPath.size();
167 std::string_view remainderPath{};
168 if (requestPath.size() > consumedLength) {
169 remainderPath = requestPath.substr(consumedLength);
170 if (!remainderPath.empty() && remainderPath.front() ==
'/') {
171 remainderPath.remove_prefix(1);
176 const std::string previousPathBackup = req
.path;
177 req
.path = remainderPath.empty() ?
"/" : (
"/" + std::string(remainderPath));
179 req
.queries.insert(requestQueryPairs.begin(), requestQueryPairs.end());
184 dispatched = route
.dispatch(controller
, absoluteMountPath
);
189 LOG(TRACE) <<
"Express: R - Dispatched";
194 LOG(TRACE) <<
"Express: R - NextRouter called - breaking dispatching";
200 req
.path = previousPathBackup;
210 std::list<std::string>
212 std::list<std::string> collectedRoutes;
215 collectedRoutes.splice(
216 collectedRoutes.end(),
220 return collectedRoutes;
const std::string & getConnectionName() const
SocketConnection * getSocketConnection() const
const std::shared_ptr< Request > & getRequest()
bool setStrictRouting(bool strictRouting)
bool getStrictRouting() const
bool getCaseInsensitiveRouting() const
const std::shared_ptr< Response > & getResponse()
web::http::CiStringMap< std::string > queries
web::http::server::SocketContext * getSocketContext() const
bool dispatch(Controller &controller, const std::string &parentMountPath)
std::list< std::string > getRoute(const std::string &parentMountPath, bool strictRouting) const
bool setCaseInsensitiveRouting(bool caseInsensitiveRouting)
std::list< std::string > getRoutes(const std::string &parentMountPath, const MountPoint &mountPoint, bool strictRouting) const override
bool getCaseInsensitiveRouting() const
bool dispatch(express::Controller &controller, const std::string &parentMountPath, const express::MountPoint &mountPoint) override
std::list< std::string > getRoutes(const std::string &parentMountPath, const MountPoint &mountPoint) const
bool setStrictRouting(bool strictRouting)
std::list< express::Route > & getRoutes()
std::vector< std::string > names
std::list< express::Route > routes
bool caseInsensitiveRouting
bool getStrictRouting() const
bool matchAndFillParams(const std::regex &rx, const std::vector< std::string > &names, std::string_view reqPath, RequestLike &req)
bool querySupersetMatches(const std::unordered_map< std::string, std::string > &rq, const std::unordered_map< std::string, std::string > &need)
void splitPathAndQuery(std::string_view url, std::string_view &path, std::string_view &query)
bool boundaryPrefix(std::string_view path, std::string_view base, bool caseInsensitive)
std::pair< std::regex, std::vector< std::string > > compileParamRegex(std::string_view mountPath, bool isPrefix, bool strictRouting, bool caseInsensitive)
std::unordered_map< std::string, std::string > parseQuery(std::string_view qs)
std::string_view trimOneTrailingSlash(std::string_view s)
std::string relativeMountPath