SNode.C
Loading...
Searching...
No Matches
RouterDispatcher.cpp
Go to the documentation of this file.
1/*
2 * SNode.C - A Slim Toolkit for Network Communication
3 * Copyright (C) Volker Christian <me@vchrist.at>
4 * 2020, 2021, 2022, 2023, 2024, 2025, 2026
5 *
6 * This program is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU Lesser General Public License as published
8 * by the Free Software Foundation, either version 3 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public License
17 * along with this program. If not, see <http://www.gnu.org/licenses/>.
18 */
19
20/*
21 * MIT License
22 *
23 * Permission is hereby granted, free of charge, to any person obtaining a copy
24 * of this software and associated documentation files (the "Software"), to deal
25 * in the Software without restriction, including without limitation the rights
26 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
27 * copies of the Software, and to permit persons to whom the Software is
28 * furnished to do so, subject to the following conditions:
29 *
30 * The above copyright notice and this permission notice shall be included in
31 * all copies or substantial portions of the Software.
32 *
33 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
34 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
35 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
36 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
37 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
38 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
39 * THE SOFTWARE.
40 */
41
42#include "express/dispatcher/RouterDispatcher.h"
43
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"
51
52#ifndef DOXYGEN_SHOULD_SKIP_THIS
53
54#include "log/Logger.h"
55
56#include <unordered_map>
57
58#endif /* DOXYGEN_SHOULD_SKIP_THIS */
59
60namespace express::dispatcher {
61
63 return routes;
64 }
65
66 bool RouterDispatcher::dispatch(express::Controller& controller, //
67 const express::MountPoint& mountPoint,
68 [[maybe_unused]] bool strictRoutingUnused,
69 [[maybe_unused]] bool caseInsensitiveRoutingUnused,
70 [[maybe_unused]] bool mergeParamsUnused) {
71 LOG(TRACE) << "======================= ROUTER DISPATCH =======================";
73 LOG(TRACE) << " Request Method: " << controller.getRequest()->method;
74 LOG(TRACE) << " Request Url: " << controller.getRequest()->url;
75 LOG(TRACE) << " Request Path: " << controller.getRequest()->path;
76 LOG(TRACE) << " Mountpoint Method: " << mountPoint.method;
77 LOG(TRACE) << " Mountpoint Path: " << mountPoint.relativeMountPath;
78 LOG(TRACE) << " StrictRouting: " << this->strictRouting;
79 LOG(TRACE) << " CaseInsensitiveRouting: " << this->caseInsensitiveRouting;
80 LOG(TRACE) << " MergeParams: " << this->mergeParams;
81
82 bool dispatched = false;
83
84 const bool methodMatchesResult = methodMatches(controller.getRequest()->method, mountPoint.method);
85
86 if (methodMatchesResult && (controller.getFlags() & Controller::NEXT) == 0) {
88 controller, mountPoint.relativeMountPath, mountPoint, regex, names, this->strictRouting, this->caseInsensitiveRouting);
89
90 if (match.requestMatched) {
91 LOG(TRACE) << "----------------------- ROUTER MATCH -----------------------";
92
93 dispatched = true;
94
95 if (!match.decodeError) {
96 express::Request& request = *controller.getRequest();
97 request.queries.insert(match.requestQueryPairs.begin(), match.requestQueryPairs.end());
98
99 // Express-style mount path stripping is only applied for use()
100 const ScopedPathStrip pathStrip(request, match.isPrefix, match.consumedLength);
101 const ScopedParams scopedParams(request, match.params, this->mergeParams);
102
103 for (Route& route : routes) {
104 dispatched = route.dispatch(controller, this->strictRouting, this->caseInsensitiveRouting, this->mergeParams);
105
106 if (dispatched || controller.nextRouterCalled()) {
107 break;
108 }
109 }
110 } else {
111 controller.getResponse()->sendStatus(400);
112 }
113 } else {
114 LOG(TRACE) << "----------------------- ROUTER NOMATCH -----------------------";
115 }
116 } else {
117 LOG(TRACE) << "----------------------- ROUTER NOMATCH -----------------------";
118 }
119
120 return dispatched;
121 }
122
123 std::list<std::string> RouterDispatcher::getRoutes(const std::string& parentMountPath, const MountPoint& mountPoint) const {
124 return getRoutes(parentMountPath, mountPoint, false);
125 }
126
127 std::list<std::string>
128 RouterDispatcher::getRoutes(const std::string& parentMountPath, const MountPoint& mountPoint, bool strictRouting) const {
129 std::list<std::string> collectedRoutes;
130
131 for (const Route& route : routes) {
132 collectedRoutes.splice(collectedRoutes.end(),
133 route.getRoute(parentMountPath + "$" + mountPoint.relativeMountPath + "$", strictRouting));
134 }
135
136 return collectedRoutes;
137 }
138
140 this->strictRouting = strictRouting;
141
142 return *this;
143 }
144
146 return strictRouting;
147 }
148
150 this->caseInsensitiveRouting = caseInsensitiveRouting;
151
152 return *this;
153 }
154
158
160 this->mergeParams = mergeParams;
161
162 return *this;
163 }
164
166 return mergeParams;
167 }
168
169} // namespace express::dispatcher
const std::string & getConnectionName() const
SocketConnection * getSocketConnection() const
const std::shared_ptr< Request > & getRequest() const
const std::shared_ptr< Response > & getResponse() const
bool nextRouterCalled() const
std::string url
Definition Request.h:98
std::string method
Definition Request.h:97
std::map< std::string, std::string > queries
Definition Request.h:103
std::string path
Definition Request.h:79
void sendStatus(int state, const std::string &html={})
Definition Response.cpp:95
web::http::server::SocketContext * getSocketContext() const
Definition Response.cpp:68
std::list< std::string > getRoute(const std::string &parentMountPath, bool strictRouting) const
Definition Route.cpp:98
bool dispatch(Controller &controller, bool strictRouting, bool caseInsensitiveRouting, bool mergeParams)
Definition Route.cpp:82
std::list< std::string > getRoutes(const std::string &parentMountPath, const MountPoint &mountPoint, bool strictRouting) const override
RouterDispatcher & setMergeParams(bool mergeParams)
std::list< std::string > getRoutes(const std::string &parentMountPath, const MountPoint &mountPoint) const
RouterDispatcher & setCaseInsensitiveRouting(bool caseInsensitiveRouting)
std::list< express::Route > & getRoutes()
std::list< express::Route > routes
bool dispatch(express::Controller &controller, const express::MountPoint &mountPoint, bool strictRoutingUnused, bool caseInsensitiveRoutingUnused, bool mergeParamsUnused) override
RouterDispatcher & setStrictRouting(bool strictRouting)
ScopedParams(express::Request &req, const std::map< std::string, std::string > &params, bool mergeWithParent)
ScopedPathStrip(express::Request &req, bool enabled, std::size_t consumedLength)
MountMatchResult matchMountPoint(express::Controller &controller, const std::string &absoluteMountPath, const express::MountPoint &mountPoint, std::regex &cachedRegex, std::vector< std::string > &cachedNames, bool strictRouting, bool caseInsensitiveRouting)
bool methodMatches(std::string_view requestMethod, const std::string &mountMethod)
std::string method
Definition MountPoint.h:56
std::string relativeMountPath
Definition MountPoint.h:57
std::map< std::string, std::string > params
Definition regex_utils.h:83
std::unordered_map< std::string, std::string > requestQueryPairs
Definition regex_utils.h:84