Skip to content

Commit

Permalink
-implemented new route path masks; allow to register route paths type…
Browse files Browse the repository at this point in the history
… safely with compile time strings on C++20;

-removed rx strings, now regexp routes are specified with routeRegex method;
  • Loading branch information
kamchatka-volcano committed Aug 22, 2024
1 parent 75f5f79 commit fe46998
Show file tree
Hide file tree
Showing 20 changed files with 1,013 additions and 375 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/build_and_test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ jobs:
- uses: ilammy/msvc-dev-cmd@v1

- name: Configure CMake
run: cmake -B ${{github.workspace}}/build -DENABLE_TESTS=ON --preset="${{ matrix.config.cmake-preset }}"
run: cmake -B ${{github.workspace}}/build -DENABLE_TESTS=ON -DENABLE_TESTS_CPP20=ON --preset="${{ matrix.config.cmake-preset }}"

- name: Build
run: cmake --build ${{github.workspace}}/build
Expand Down
4 changes: 2 additions & 2 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ include(external/seal_lake)
SealLake_Bundle(
NAME whaleroute_sfun
GIT_REPOSITORY https://github.com/kamchatka-volcano/sfun.git
GIT_TAG v5.1.0
GIT_TAG develop
DIRECTORIES
include/sfun
DESTINATION include/whaleroute/external
Expand All @@ -18,4 +18,4 @@ SealLake_HeaderOnlyLibrary(
COMPILE_FEATURES cxx_std_17
)

SealLake_OptionalSubProjects(tests)
SealLake_OptionalSubProjects(tests tests_cpp20)
16 changes: 8 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -183,7 +183,7 @@ class Router : public whaleroute::RequestRouter<Request, Response>{
};
auto router = Router{};
router.route(whaleroute::rx{".*"}, Request::Method::GET).process(const Request& request, Response&)){
router.route(whaleroute::Regex{".*"}, Request::Method::GET).process(const Request& request, Response&)){
log(request);
});
router.route("/").process([](const Request&, Response& response)){
Expand Down Expand Up @@ -214,7 +214,7 @@ void authorize(const Request& request, Response&, Context& ctx)
ctx.isAuthorized = true;
}

router.route(whaleroute::rx{".*"}, Request::Method::POST).process(authorize);
router.route(whaleroute::Regex{".*"}, Request::Method::POST).process(authorize);
router.route("/").process([](const Request&, Response& response, const Context& ctx)){
if (ctx.isAuthorized)
response.send("HTTP/1.1 200 OK\r\n\r\n");
Expand Down Expand Up @@ -275,7 +275,7 @@ struct RouteMatcher<Request::Method, Context> {
The `route` method of the Router can accept a regular expression instead of a string to specify the path of the route:

```c++
router.route(whaleroute::rx{"/.*"}, Request::Method::GET).set("HTTP/1.1 200 OK\r\n\r\n");
router.route(whaleroute::Regex{"/.*"}, Request::Method::GET).set("HTTP/1.1 200 OK\r\n\r\n");
```
Currently, the regular expressions use the standard C++ library with ECMAScript grammar.
Expand All @@ -288,7 +288,7 @@ void showPage(int pageNumber, const Request&, Response& response)
{
response.send("page" + std::to_string(pageNumber));
}
router.route(whaleroute::rx{"/page/(\\d+)"}, Request::Method::GET).process(showPage);
router.route(whaleroute::Regex{"/page/(\\d+)"}, Request::Method::GET).process(showPage);
```

The conversion of strings from the capturing groups to the parameters of the request processor is performed using the
Expand All @@ -312,7 +312,7 @@ void showPage(PageNumber pageNumber, const Request&, Response& response)
{
response.send("page" + std::to_string(pageNumber.value));
}
router.route(whaleroute::rx{"/page/(\\d+)"}, Request::Method::GET).process(showPage);
router.route(whaleroute::Regex{"/page/(\\d+)"}, Request::Method::GET).process(showPage);
```
When the regular expression of a route is set dynamically, you may need to capture an arbitrary number of parameters. In
Expand All @@ -327,8 +327,8 @@ void showBook(const RouteParameters<>& bookIds, const Request&, Response& respon
if (bookIds.value.size() == 2)
response.send("book" + std::to_string(bookIds.value.at(0)) + std::to_string(bookIds.value.at(1)));
}
router.route(whaleroute::rx{"/book/(\\d+)/(\\d+)"}, Request::Method::GET).process(showBook);
router.route(whaleroute::rx{"/book/(\\d+)"}, Request::Method::GET).process(showBook);
router.route(whaleroute::Regex{"/book/(\\d+)/(\\d+)"}, Request::Method::GET).process(showBook);
router.route(whaleroute::Regex{"/book/(\\d+)"}, Request::Method::GET).process(showBook);
```

If capturing the string array is more suitable for your request processor, you can use `RouteParameters` with a specific
Expand All @@ -339,7 +339,7 @@ void showPage(const RouteParameters<1>& pageNumber, const Request&, Response& re
{
response.send("page" + pageNumber.value().at(0));
}
router.route(whaleroute::rx{"/page/(\\d+)"}, Request::Method::GET).process(showPage);
router.route(whaleroute::Regex{"/page/(\\d+)"}, Request::Method::GET).process(showPage);
```
#### Trailing slash matching
Expand Down
25 changes: 24 additions & 1 deletion include/whaleroute/requestprocessor.h
Original file line number Diff line number Diff line change
Expand Up @@ -139,7 +139,7 @@ auto readRouteParams(const std::vector<std::string>& routeParams)
return params;
}
else {
if (paramsSize > routeParams.size())
if (paramsSize != routeParams.size())
return RouteParameterCountMismatch{paramsSize, static_cast<int>(routeParams.size())};

return makeParams<ParamsTuple>(routeParams);
Expand Down Expand Up @@ -177,6 +177,7 @@ constexpr int getParamsCount()
}

template<
auto checkParam,
typename TResponseConverter,
typename TRequestProcessor,
typename TRequest,
Expand Down Expand Up @@ -216,6 +217,28 @@ void invokeRequestProcessor(
}
}
else {
if constexpr (!std::is_same_v<decltype(checkParam), std::nullptr_t>) {

constexpr auto paramsTuple =
sfun::decay_tuple_t<sfun::to_type_id_tuple_t<decltype(args.template slice<0, paramsCount>())>>{};
constexpr auto isAnyRouteParameters = std::tuple_size_v<decltype(paramsTuple)> == 1 &&
std::is_base_of_v<detail::RouteParameters,
typename std::tuple_element_t<0, decltype(paramsTuple)>::type>;

if constexpr (!isAnyRouteParameters) {
constexpr auto requestProcessorParams = sfun::type_list{paramsTuple};
if constexpr (std::is_same_v<decltype(checkParam), int>){
static_assert(
requestProcessorParams.size() == checkParam,
"Request processor has a mismatched number of route parameters and route's regular expression capture groups.");
}
else {
static_assert(
requestProcessorParams == checkParam,
"Request processor can't be invoked with route parameters");
}
}
}
auto paramsResult = readRouteParams<decltype(args), paramsCount>(routeParams);
auto paramsResultVisitor = sfun::overloaded{
[&](const RouteParameterError& error)
Expand Down
Loading

0 comments on commit fe46998

Please sign in to comment.