You've already forked libart-seafire-routing
Add support for parameter validators
This commit is contained in:
@@ -1,14 +1,31 @@
|
||||
#include <art/seafire/routing/match.hxx>
|
||||
|
||||
#include <sstream>
|
||||
#include <iostream>
|
||||
#include <vector>
|
||||
|
||||
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
|
||||
match(std::string const& subject,
|
||||
std::string const& pattern,
|
||||
validator_map_t const& validators,
|
||||
char delim,
|
||||
parameters_t& params)
|
||||
{
|
||||
@@ -24,7 +41,7 @@ namespace art::seafire::routing
|
||||
auto s = subject.begin();
|
||||
auto const send = subject.end();
|
||||
|
||||
auto match_param = [&]()
|
||||
auto match_param = [&]() -> bool
|
||||
{
|
||||
// k/kend = local pattern iterators.
|
||||
//
|
||||
@@ -35,10 +52,6 @@ namespace art::seafire::routing
|
||||
auto const kend = p;
|
||||
++p;
|
||||
|
||||
if (k == kend) {
|
||||
throw std::invalid_argument{"empty parameter name"};
|
||||
}
|
||||
|
||||
// a greedy parameter will eat the rest of the subject.
|
||||
//
|
||||
bool const greedy{'*' == *k && 1 == std::distance(k, kend)};
|
||||
@@ -51,13 +64,57 @@ namespace art::seafire::routing
|
||||
}
|
||||
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) {
|
||||
if (*p == '{') {
|
||||
++p;
|
||||
match_param();
|
||||
|
||||
if (!match_param()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
@@ -3,14 +3,21 @@
|
||||
|
||||
#include <art/seafire/routing/parameters.hxx>
|
||||
|
||||
#include <functional>
|
||||
#include <map>
|
||||
#include <string>
|
||||
|
||||
namespace art::seafire::routing
|
||||
{
|
||||
|
||||
using validator_t = std::function<bool(std::string const&)>;
|
||||
|
||||
using validator_map_t = std::map<std::string, validator_t>;
|
||||
|
||||
bool
|
||||
match(std::string const&,
|
||||
std::string const&,
|
||||
validator_map_t const&,
|
||||
char,
|
||||
parameters_t&);
|
||||
|
||||
|
||||
@@ -43,10 +43,19 @@ namespace art::seafire::routing
|
||||
}
|
||||
|
||||
router_t::
|
||||
router_t(common::diagnostics_t& diagnostics, routing_table_t table)
|
||||
: diagnostics_{diagnostics}, rt_{std::move(table)}
|
||||
router_t(common::diagnostics_t& diagnostics,
|
||||
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&
|
||||
router_t::
|
||||
routing_table() const
|
||||
@@ -76,7 +85,7 @@ namespace art::seafire::routing
|
||||
<< " -> path : " << path
|
||||
;
|
||||
|
||||
auto result = routing_table().find_route(hostname, path);
|
||||
auto result = routing_table().find_route(hostname, path, validators());
|
||||
|
||||
if (!result) {
|
||||
trace() << "endpoint for [" << path << "] not found";
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
#define art__seafire__routing__router_hxx_
|
||||
|
||||
#include <art/seafire/routing/diagnostics.hxx>
|
||||
#include <art/seafire/routing/match.hxx>
|
||||
#include <art/seafire/routing/routing-table.hxx>
|
||||
|
||||
#include <art/seafire/common/diagnostics.hxx>
|
||||
@@ -15,7 +16,10 @@ namespace art::seafire::routing
|
||||
class router_t
|
||||
{
|
||||
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() const;
|
||||
@@ -31,6 +35,7 @@ namespace art::seafire::routing
|
||||
trace() const;
|
||||
|
||||
common::diagnostics_t& diagnostics_;
|
||||
validator_map_t validators_;
|
||||
routing_table_t rt_;
|
||||
|
||||
};
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
#include <art/seafire/routing/routing-table.hxx>
|
||||
|
||||
#include <art/seafire/routing/match.hxx>
|
||||
|
||||
namespace art::seafire::routing
|
||||
{
|
||||
|
||||
@@ -19,18 +17,20 @@ namespace art::seafire::routing
|
||||
|
||||
std::optional<routing_table_t::find_result_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()) {
|
||||
host_parameters_t host_params;
|
||||
|
||||
if (!match(host, e.host(), '.', host_params)) {
|
||||
if (!match(host, e.host(), validators, '.', host_params)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
route_parameters_t route_params;
|
||||
|
||||
if (match(path, e.path(), '/', route_params)) {
|
||||
if (match(path, e.path(), validators, '/', route_params)) {
|
||||
return find_result_t{
|
||||
std::move(host_params),
|
||||
std::move(route_params),
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
#define art__seafire__routing__routing_table_hxx_
|
||||
|
||||
#include <art/seafire/routing/endpoint.hxx>
|
||||
#include <art/seafire/routing/match.hxx>
|
||||
#include <art/seafire/routing/parameters.hxx>
|
||||
#include <art/seafire/routing/route.hxx>
|
||||
|
||||
@@ -34,7 +35,7 @@ namespace art::seafire::routing
|
||||
endpoints() const;
|
||||
|
||||
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:
|
||||
static
|
||||
|
||||
Reference in New Issue
Block a user