Add support for parameter validators

This commit is contained in:
2026-01-15 08:46:12 +01:00
parent 5ce247e014
commit c394535d71
6 changed files with 96 additions and 17 deletions

View File

@@ -1,14 +1,31 @@
#include <art/seafire/routing/match.hxx> #include <art/seafire/routing/match.hxx>
#include <sstream> #include <sstream>
#include <iostream>
#include <vector> #include <vector>
namespace art::seafire::routing namespace art::seafire::routing
{ {
static
std::vector<std::string>
split(std::string const& str, char delim)
{
std::vector<std::string> strings;
std::stringstream input{str};
for (std::string line; std::getline(input, line, delim);) {
strings.emplace_back(std::move(line));
}
return strings;
}
bool bool
match(std::string const& subject, match(std::string const& subject,
std::string const& pattern, std::string const& pattern,
validator_map_t const& validators,
char delim, char delim,
parameters_t& params) parameters_t& params)
{ {
@@ -24,7 +41,7 @@ namespace art::seafire::routing
auto s = subject.begin(); auto s = subject.begin();
auto const send = subject.end(); auto const send = subject.end();
auto match_param = [&]() auto match_param = [&]() -> bool
{ {
// k/kend = local pattern iterators. // k/kend = local pattern iterators.
// //
@@ -35,10 +52,6 @@ namespace art::seafire::routing
auto const kend = p; auto const kend = p;
++p; ++p;
if (k == kend) {
throw std::invalid_argument{"empty parameter name"};
}
// a greedy parameter will eat the rest of the subject. // a greedy parameter will eat the rest of the subject.
// //
bool const greedy{'*' == *k && 1 == std::distance(k, kend)}; bool const greedy{'*' == *k && 1 == std::distance(k, kend)};
@@ -51,13 +64,57 @@ namespace art::seafire::routing
} }
auto const vend = s; auto const vend = s;
tmp_params.map().emplace(std::string{k, kend}, std::string{v, vend}); std::string key{k, kend};
std::string type;
auto parts = split(key, ':');
if (parts.size() == 1) {
key = parts[0];
}
else if (parts.size() == 2) {
key = parts[0];
type = parts[1];
if (type.size() == 0) {
return false;
}
}
else {
return false;
}
if (key.size() == 0) {
return false;
}
std::string value{v, vend};
if (type.size() > 0) {
auto validator = validators.find(type);
if (validator == validators.end()) {
return false;
}
if (!validator->second(value)) {
return false;
}
}
tmp_params.map().emplace(std::move(key), std::move(value));
return true;
}; };
while (p != pend) { while (p != pend) {
if (*p == '{') { if (*p == '{') {
++p; ++p;
match_param();
if (!match_param()) {
return false;
}
continue; continue;
} }

View File

@@ -3,14 +3,21 @@
#include <art/seafire/routing/parameters.hxx> #include <art/seafire/routing/parameters.hxx>
#include <functional>
#include <map>
#include <string> #include <string>
namespace art::seafire::routing namespace art::seafire::routing
{ {
using validator_t = std::function<bool(std::string const&)>;
using validator_map_t = std::map<std::string, validator_t>;
bool bool
match(std::string const&, match(std::string const&,
std::string const&, std::string const&,
validator_map_t const&,
char, char,
parameters_t&); parameters_t&);

View File

@@ -43,10 +43,19 @@ namespace art::seafire::routing
} }
router_t:: router_t::
router_t(common::diagnostics_t& diagnostics, routing_table_t table) router_t(common::diagnostics_t& diagnostics,
: diagnostics_{diagnostics}, rt_{std::move(table)} validator_map_t validators,
routing_table_t table)
: diagnostics_{diagnostics}, validators_{std::move(validators)}, rt_{std::move(table)}
{} {}
validator_map_t const&
router_t::
validators() const
{
return validators_;
}
routing_table_t const& routing_table_t const&
router_t:: router_t::
routing_table() const routing_table() const
@@ -76,7 +85,7 @@ namespace art::seafire::routing
<< " -> path : " << path << " -> path : " << path
; ;
auto result = routing_table().find_route(hostname, path); auto result = routing_table().find_route(hostname, path, validators());
if (!result) { if (!result) {
trace() << "endpoint for [" << path << "] not found"; trace() << "endpoint for [" << path << "] not found";

View File

@@ -2,6 +2,7 @@
#define art__seafire__routing__router_hxx_ #define art__seafire__routing__router_hxx_
#include <art/seafire/routing/diagnostics.hxx> #include <art/seafire/routing/diagnostics.hxx>
#include <art/seafire/routing/match.hxx>
#include <art/seafire/routing/routing-table.hxx> #include <art/seafire/routing/routing-table.hxx>
#include <art/seafire/common/diagnostics.hxx> #include <art/seafire/common/diagnostics.hxx>
@@ -15,7 +16,10 @@ namespace art::seafire::routing
class router_t class router_t
{ {
public: public:
router_t(common::diagnostics_t&, routing_table_t); router_t(common::diagnostics_t&, validator_map_t, routing_table_t);
validator_map_t const&
validators() const;
routing_table_t const& routing_table_t const&
routing_table() const; routing_table() const;
@@ -31,6 +35,7 @@ namespace art::seafire::routing
trace() const; trace() const;
common::diagnostics_t& diagnostics_; common::diagnostics_t& diagnostics_;
validator_map_t validators_;
routing_table_t rt_; routing_table_t rt_;
}; };

View File

@@ -1,7 +1,5 @@
#include <art/seafire/routing/routing-table.hxx> #include <art/seafire/routing/routing-table.hxx>
#include <art/seafire/routing/match.hxx>
namespace art::seafire::routing namespace art::seafire::routing
{ {
@@ -19,18 +17,20 @@ namespace art::seafire::routing
std::optional<routing_table_t::find_result_t> std::optional<routing_table_t::find_result_t>
routing_table_t:: routing_table_t::
find_route(std::string const& host, std::string const& path) const find_route(std::string const& host,
std::string const& path,
validator_map_t const& validators) const
{ {
for (auto const& e : endpoints()) { for (auto const& e : endpoints()) {
host_parameters_t host_params; host_parameters_t host_params;
if (!match(host, e.host(), '.', host_params)) { if (!match(host, e.host(), validators, '.', host_params)) {
continue; continue;
} }
route_parameters_t route_params; route_parameters_t route_params;
if (match(path, e.path(), '/', route_params)) { if (match(path, e.path(), validators, '/', route_params)) {
return find_result_t{ return find_result_t{
std::move(host_params), std::move(host_params),
std::move(route_params), std::move(route_params),

View File

@@ -2,6 +2,7 @@
#define art__seafire__routing__routing_table_hxx_ #define art__seafire__routing__routing_table_hxx_
#include <art/seafire/routing/endpoint.hxx> #include <art/seafire/routing/endpoint.hxx>
#include <art/seafire/routing/match.hxx>
#include <art/seafire/routing/parameters.hxx> #include <art/seafire/routing/parameters.hxx>
#include <art/seafire/routing/route.hxx> #include <art/seafire/routing/route.hxx>
@@ -34,7 +35,7 @@ namespace art::seafire::routing
endpoints() const; endpoints() const;
std::optional<find_result_t> std::optional<find_result_t>
find_route(std::string const&, std::string const&) const; find_route(std::string const&, std::string const&, validator_map_t const&) const;
private: private:
static static