Method-matchers for express- and easy_parser-based routers
Before v.0.6.6 a user can specify just one HTTP method for a request-handler, e.g.:
router->http_get(some_route_path, [](auto req, auto params) {...});
...
router->add_handler(
restinio::http_method_lock(),
another_route_path,
[](auto req, auto params) {...});
But this limitation leads to unnecessary complexity in cases where a special HTTP status code should be returned if an illegal method was used for a resource. For example, a server allows to perform HTTP GET, HTTP POST and HTTP DELETE method to a particular route, but all other methods for the same route should be declined with HTTP 405 status code.
A new entity called method-matcher was introduced in v.0.6.6. This entity allows to specify a request handler for a set of HTTP methods. For example:
router->http_get(book_path, [](auto req, auto params) {...});
router->http_post(book_path, [](auto req, auto params) {...});
router->http_delete(book_path, [](auto req, auto params) {...});
// This request handler will be called for a request to "book_path"
// if HTTP method is not GET, POST, nor DELETE.
router->add_handler(
restinio::router::none_of_methods(
restinio::http_method_get(),
restinio::http_method_post(),
restinio::http_method_delete()),
book_path,
[](auto req, auto) {
return req->create_response(restinio::status_method_not_allowed())
.connection_close()
.done();
});
Ready-to-use method-matchers
RESTinio contains several ready-to-use method-matchers those can be split into two groups.
The first group is any-of matchers. They hold a list of HTTP method IDs and allows a method to be handled only if it is present in that list.
The second group is none-of matchers. They also hold a list of HTTP method IDs, but allow to handle a method only if it is not found in that list.
For example:
router->add_handler(
// A request handler will be called only if
// HTTP method is GET, POST or DELETE.
restinio::router::any_of_methods(
restinio::http_method_get(),
restinio::http_method_post(),
restinio::http_method_delete()),
book_path,
[](auto req, auto params) {...});
router->add_handler(
// A request handler will be called for any HTTP method
// except GET, POST or DELETE.
restinio::router::none_of_methods(
restinio::http_method_get(),
restinio::http_method_post(),
restinio::http_method_delete()),
book_path,
[](auto req, auto params) {...});
Those matchers can also be divided into two categories: the first one is matchers with a list of methods fixed at the compile-time, and the second is matchers with a dynamically expandable list of methods:
// This is a fixed size matcher.
restinio::router::any_of_methods(
restinio::http_method_get(),
restinio::http_method_head());
// This is also a fixed size matcher.
restinio::router::none_of_methods(
restinio::http_method_post(),
restinio::http_method_put(),
restinio::http_method_delete());
// This is a dynamic size matcher.
restinio::router::dynamic_any_of_methods_matcher_t matcher1;
matcher1.add(restinio::http_method_get());
if(some_condition)
matcher1.add(restinio::http_method_head());
// This is also a dynamic size matcher.
restinio::router::dynamic_none_of_methods_matcher_t matcher2;
matcher2.add(restinio::http_method_post());
if(some_condition)
matcher2.add(restinio::http_method_put());
if(another_condition)
matcher2.add(restinio::http_method_delete());
The main difference between those categories is the absence of dynamic memory allocation for fixed-size matchers. The size for a fixed-size matcher is automatically calculated by a compiler at the compile-time. Dynamic-size matchers can allocate some memory in add()
methods.
A possibility to make own matchers
There is an interface of method-matchers in RESTinio with name method_matcher_t
in restinio::router
namespace. This interface has just one pure virtual method match()
.
If a user wants to make his/her own matcher type he/she can derive a class from method_matcher_t
and implement match()
method.
Method-matchers can be used for express- and easy_parser-based routers
Method-matchers are router-agnostic entities. So a user can use the same method-matcher for express- or easy_parser-based routers:
// Express-router.
expr_router->add_method(
restinio::router::none_of_methods(
restinio::http_method_get(),
restinio::http_method_post(),
restinio::http_method_delete()),
"/books/:id(\d{1,10})/versions/:version",
[](auto req, auto params) {...});
// Easy_parser-based router.
namespace epr = restinio::router::easy_parser_router;
epr_router->add_method(
restinio::router::none_of_methods(
restinio::http_method_get(),
restinio::http_method_post(),
restinio::http_method_delete()),
epr::path_to_params(
"/books/",
epr::non_negative_decimal_number_p<std::uint64_t>(
epr::expected_digits(1, 10)),
"/versions/",
epr::path_fragment_p()),
[](auto req, auto book_id, const auto & version_id) {...});