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 <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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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&);
|
||||||
|
|
||||||
|
|||||||
@@ -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";
|
||||||
|
|||||||
@@ -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_;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -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),
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
Reference in New Issue
Block a user