RESTinio
Loading...
Searching...
No Matches
express.hpp
Go to the documentation of this file.
1/*
2 restinio
3*/
4
9#pragma once
10
13
15
18
21
22#include <map>
23#include <optional>
24#include <vector>
25
26namespace restinio
27{
28
29namespace router
30{
31
32namespace impl
33{
34
36
37} /* namespace impl */
38
39//
40// route_params_t
41//
42
44
57{
58 public:
60 std::vector< std::pair< string_view_t, string_view_t > >;
62 std::vector< string_view_t >;
63
64 private:
66
67 void
69 std::unique_ptr< char[] > request_target,
70 std::shared_ptr< std::string > key_names_buffer,
72 named_parameters_container_t named_parameters,
73 indexed_parameters_container_t indexed_parameters )
74 {
75 m_request_target = std::move( request_target );
77 m_match = match;
78 m_named_parameters = std::move( named_parameters );
79 m_indexed_parameters = std::move( indexed_parameters );
80 }
81
82 public:
83 route_params_t() = default;
84
87
88 route_params_t( const route_params_t & ) = delete;
90
93
97 {
98 return find_named_parameter_with_check( key ).second;
99 }
100
102 bool
103 has( string_view_t key ) const noexcept
104 {
106 }
107
110 std::optional< string_view_t >
111 get_param( string_view_t key ) const noexcept
112 {
113 const auto it = find_named_parameter( key );
114
115 return m_named_parameters.end() != it ?
116 std::optional< string_view_t >{ it->second } :
117 std::optional< string_view_t >{ std::nullopt };
118 }
119
122 operator [] ( std::size_t i ) const
123 {
124 if( i >= m_indexed_parameters.size() )
125 throw exception_t{
126 fmt::format(
127 RESTINIO_FMT_FORMAT_STRING( "invalid parameter index: {}" ),
128 i )
129 };
130
131 return m_indexed_parameters.at( i );
132 }
133
139
140 private:
141 named_parameters_container_t::const_iterator
143 {
144 return
145 std::find_if(
146 m_named_parameters.begin(),
147 m_named_parameters.end(),
148 [&]( const auto p ){
149 return key == p.first;
150 } );
151 }
152
153 named_parameters_container_t::const_reference
155 {
156 auto it = find_named_parameter( key );
157
158 if( m_named_parameters.end() == it )
159 throw exception_t{
160 fmt::format(
161 RESTINIO_FMT_FORMAT_STRING( "invalid parameter name: {}" ),
162 std::string{ key.data(), key.size() } ) };
163
164 return *it;
165 }
166
168
179 std::unique_ptr< char[] > m_request_target;
180
182 std::shared_ptr< std::string > m_key_names_buffer;
183
186
189
192};
193
194namespace impl
195{
196
197//
198// route_params_accessor_t
199//
200
203{
205 static void
208 std::unique_ptr< char[] > request_target,
209 std::shared_ptr< std::string > key_names_buffer,
213 {
214 rp.match(
215 std::move( request_target ),
216 std::move( key_names_buffer ),
217 match_,
218 std::move( named_parameters ),
219 std::move( indexed_parameters ) );
220 }
221
224 static const auto &
226 {
227 return rp.m_named_parameters;
228 }
229
230 static const auto &
232 {
233 return rp.m_indexed_parameters;
234 }
236};
237
238//
239// route_params_appender_t
240//
241
274
277
278//
279// route_matcher_t
280//
281
283template < typename Regex_Engine = std_regex_engine_t >
285{
286 public:
287 using regex_t = typename Regex_Engine::compiled_regex_t;
288 using match_results_t = typename Regex_Engine::match_results_t;
289
292 http_method_id_t method,
294 std::shared_ptr< std::string > named_params_buffer,
296 : m_route_regex{ std::move( route_regex ) }
299 {
300 assign( m_method_matcher, std::move(method) );
301 }
302
311 template< typename Method_Matcher >
315 std::shared_ptr< std::string > named_params_buffer,
317 : m_route_regex{ std::move( route_regex ) }
320 {
321 assign(
323 std::forward<Method_Matcher>(method_matcher) );
324 }
325
326 route_matcher_t() = default;
328
330 bool
333 route_params_t & parameters ) const
334 {
336 if( Regex_Engine::try_match(
337 target_path.view(),
339 matches ) )
340 {
341 assert( m_param_appender_sequence.size() + 1 >= matches.size() );
342
343 // Data for route_params_t initialization.
344
345 auto captured_params = target_path.giveout_data();
346
347 const string_view_t match{
348 captured_params.get() + Regex_Engine::submatch_begin_pos( matches[0] ),
349 Regex_Engine::submatch_end_pos( matches[0] ) -
350 Regex_Engine::submatch_begin_pos( matches[0] ) } ;
351
354
355 route_params_appender_t param_appender{ named_parameters, indexed_parameters };
356
357 // Std regex and pcre engines handle
358 // trailing groups with empty values differently.
359 // Std despite they are empty includes them in the list of match results;
360 // Pcre on the other hand does not.
361 // So the second for is for pushing empty values
362 std::size_t i = 1;
363 for( ; i < matches.size(); ++i )
364 {
365 const auto & m = matches[ i ];
369 captured_params.get() + Regex_Engine::submatch_begin_pos( m ),
370 Regex_Engine::submatch_end_pos( m ) -
371 Regex_Engine::submatch_begin_pos( m ) } );
372 }
373
374 for( ; i < m_param_appender_sequence.size() + 1; ++i )
375 {
378 string_view_t{ captured_params.get(), 0 } );
379 }
380
381 // Init route parameters.
383 parameters,
384 std::move( captured_params ),
385 m_named_params_buffer, // Do not move (it is used on each match).
386 std::move( match ),
387 std::move( named_parameters ),
388 std::move( indexed_parameters ) );
389
390 return true;
391 }
392
393 return false;
394 }
395
396 inline bool
398 const http_request_header_t & h,
400 route_params_t & parameters ) const
401 {
402 return m_method_matcher->match( h.method() ) &&
403 match_route( target_path, parameters );
404 }
405
406 private:
409
412
414 std::shared_ptr< std::string > m_named_params_buffer;
415
418};
419
420} /* namespace impl */
421
422//
423// generic_express_request_handler_t
424//
441template< typename Extra_Data >
446 >;
447
448//
449// express_request_handler_t
450//
461
462//
463// generic_express_route_entry_t
464//
465
467
472template<
473 typename Regex_Engine,
474 typename Extra_Data_Factory >
476{
477 public:
479 typename Extra_Data_Factory::data_t
480 >;
482 typename Extra_Data_Factory::data_t
483 >;
484
485 private:
489 Regex_Engine >;
490
491 template< typename Method_Matcher >
496 : m_matcher{
498 std::move( matcher_data.m_regex ),
499 std::move( matcher_data.m_named_params_buffer ),
500 std::move( matcher_data.m_param_appender_sequence ) }
501 , m_handler{ std::move( handler ) }
502 {}
503
504 public:
506 const generic_express_route_entry_t & ) = delete;
508 const generic_express_route_entry_t & ) = delete;
509
512 generic_express_route_entry_t && ) = default;
513
516
517 template< typename Method_Matcher >
525 path2regex::path2regex< impl::route_params_appender_t, Regex_Engine >(
527 options ),
528 std::move( handler ) }
529 {}
530
531 template< typename Method_Matcher >
542
545 [[nodiscard]]
546 bool
548 const http_request_header_t & h,
550 route_params_t & params ) const
551 {
552 return m_matcher( h, target_path, params );
553 }
554
556 [[nodiscard]]
559 {
560 return m_handler( std::move( rh ), std::move( rp ) );
561 }
562
563 private:
566};
567
568//
569// express_route_entry_t
570//
577template<
582
583//
584// generic_express_router_t
585//
586
588
611template<
612 typename Regex_Engine,
613 typename Extra_Data_Factory >
615{
616 public:
626 typename Extra_Data_Factory::data_t
627 >;
628
631
632 [[nodiscard]]
635 {
636 impl::target_path_holder_t target_path{ req->header().path() };
637 route_params_t params;
638 for( const auto & entry : m_handlers )
639 {
640 if( entry.match( req->header(), target_path, params ) )
641 {
642 return entry.handle( std::move( req ), std::move( params ) );
643 }
644 }
645
646 // Here: none of the routes matches this handler.
647
649 {
650 // If non matched request handler is set
651 // then call it.
652 return m_non_matched_request_handler( std::move( req ) );
653 }
654
655 return request_not_handled();
656 }
657
660 template< typename Method_Matcher >
661 void
666 {
668 std::forward<Method_Matcher>(method_matcher),
671 std::move( handler ) );
672 }
673
674 template< typename Method_Matcher >
675 void
681 {
682 m_handlers.emplace_back(
683 std::forward<Method_Matcher>(method_matcher),
685 options,
686 std::move( handler ) );
687 }
688
689 void
699
700 void
712
713 void
723
724 void
736
737 void
747
748 void
760
761 void
771
772 void
784
785 void
795
796 void
809
811 void
816
817 private:
821 >;
822
824 std::vector< route_entry_t > m_handlers;
825
828};
829
830//
831// express_router_t
832//
842template<
847
848} /* namespace router */
849
851template < typename Value_Type >
854{
855 return std::get< Value_Type >( params[ key ] );
856}
857
859template < typename Value_Type >
861get( const router::route_params_t & params, std::size_t index )
862{
863 return std::get< Value_Type >( params[ index ] );
864}
865
866} /* namespace restinio */
Exception class for all exceptions thrown by RESTinio.
Definition exception.hpp:26
A type for representation of HTTP method ID.
Options for matching routes.
A single generic express route entry.
Definition express.hpp:476
generic_express_route_entry_t(Method_Matcher &&method_matcher, matcher_init_data_t matcher_data, actual_request_handler_t handler)
Definition express.hpp:492
generic_express_request_handler_t< typename Extra_Data_Factory::data_t > actual_request_handler_t
Definition express.hpp:478
generic_express_route_entry_t & operator=(const generic_express_route_entry_t &)=delete
generic_express_route_entry_t(Method_Matcher &&method_matcher, string_view_t route_path, const path2regex::options_t &options, actual_request_handler_t handler)
Definition express.hpp:518
generic_express_route_entry_t(generic_express_route_entry_t &&)=default
bool match(const http_request_header_t &h, impl::target_path_holder_t &target_path, route_params_t &params) const
Checks if request header matches entry, and if so, set route params.
Definition express.hpp:547
generic_express_route_entry_t(Method_Matcher &&method_matcher, string_view_t route_path, actual_request_handler_t handler)
Definition express.hpp:532
generic_express_route_entry_t & operator=(generic_express_route_entry_t &&)=default
actual_request_handler_t m_handler
Definition express.hpp:565
generic_express_route_entry_t()=default
generic_request_handle_t< typename Extra_Data_Factory::data_t > actual_request_handle_t
Definition express.hpp:481
request_handling_status_t handle(actual_request_handle_t rh, route_params_t rp) const
Calls a handler of given request with given params.
Definition express.hpp:558
generic_express_route_entry_t(const generic_express_route_entry_t &)=delete
impl::route_matcher_t< Regex_Engine > m_matcher
Definition express.hpp:564
Generic Express.js style router.
Definition express.hpp:615
void http_post(string_view_t route_path, const path2regex::options_t &options, actual_request_handler_t handler)
Definition express.hpp:773
void http_get(string_view_t route_path, actual_request_handler_t handler)
Definition express.hpp:714
request_handling_status_t operator()(actual_request_handle_t req) const
Definition express.hpp:634
void http_put(string_view_t route_path, const path2regex::options_t &options, actual_request_handler_t handler)
Definition express.hpp:797
void non_matched_request_handler(non_matched_handler_t nmrh)
Set handler for requests that don't match any route.
Definition express.hpp:812
generic_request_handle_t< typename Extra_Data_Factory::data_t > actual_request_handle_t
Definition express.hpp:617
non_matched_handler_t m_non_matched_request_handler
Handler that is called for requests that don't match any route.
Definition express.hpp:827
void http_head(string_view_t route_path, const path2regex::options_t &options, actual_request_handler_t handler)
Definition express.hpp:749
typename generic_express_route_entry_t< Regex_Engine, Extra_Data_Factory >::actual_request_handler_t actual_request_handler_t
Definition express.hpp:619
void http_delete(string_view_t route_path, const path2regex::options_t &options, actual_request_handler_t handler)
Definition express.hpp:701
void http_delete(string_view_t route_path, actual_request_handler_t handler)
Definition express.hpp:690
std::vector< route_entry_t > m_handlers
A list of existing routes.
Definition express.hpp:824
void add_handler(Method_Matcher &&method_matcher, string_view_t route_path, const path2regex::options_t &options, actual_request_handler_t handler)
Definition express.hpp:676
void http_put(string_view_t route_path, actual_request_handler_t handler)
Definition express.hpp:786
void http_head(string_view_t route_path, actual_request_handler_t handler)
Definition express.hpp:738
void http_post(string_view_t route_path, actual_request_handler_t handler)
Definition express.hpp:762
generic_non_matched_request_handler_t< typename Extra_Data_Factory::data_t > non_matched_handler_t
Definition express.hpp:624
void http_get(string_view_t route_path, const path2regex::options_t &options, actual_request_handler_t handler)
Definition express.hpp:725
void add_handler(Method_Matcher &&method_matcher, string_view_t route_path, actual_request_handler_t handler)
Add handlers.
Definition express.hpp:662
generic_express_router_t(generic_express_router_t &&)=default
A special class that allows to hold a copy of small-size method_matchers or a pointer to dynamically ...
A matcher for a given path.
Definition express.hpp:285
route_matcher_t(Method_Matcher &&method_matcher, regex_t route_regex, std::shared_ptr< std::string > named_params_buffer, param_appender_sequence_t param_appender_sequence)
Definition express.hpp:312
buffered_matcher_holder_t m_method_matcher
HTTP method to match.
Definition express.hpp:408
regex_t m_route_regex
Regex of a given route.
Definition express.hpp:411
param_appender_sequence_t m_param_appender_sequence
Parameters values.
Definition express.hpp:417
bool match_route(target_path_holder_t &target_path, route_params_t &parameters) const
Try to match a given request target with this route.
Definition express.hpp:331
typename Regex_Engine::match_results_t match_results_t
Definition express.hpp:288
bool operator()(const http_request_header_t &h, target_path_holder_t &target_path, route_params_t &parameters) const
Definition express.hpp:397
std::shared_ptr< std::string > m_named_params_buffer
Buffer for named parameters names string views.
Definition express.hpp:414
typename Regex_Engine::compiled_regex_t regex_t
Definition express.hpp:287
route_matcher_t(route_matcher_t &&)=default
route_matcher_t(http_method_id_t method, regex_t route_regex, std::shared_ptr< std::string > named_params_buffer, param_appender_sequence_t param_appender_sequence)
Creates matcher with a given parameters.
Definition express.hpp:291
Helper class for gthering parameters from route.
Definition express.hpp:244
route_params_t::indexed_parameters_container_t & m_indexed_parameters
Definition express.hpp:272
void add_indexed_param(string_view_t value)
Definition express.hpp:265
void add_named_param(string_view_t key, string_view_t value)
Definition express.hpp:259
route_params_t::named_parameters_container_t & m_named_parameters
Definition express.hpp:271
route_params_appender_t(route_params_appender_t &&)=delete
route_params_appender_t & operator=(const route_params_appender_t &)=delete
route_params_appender_t(const route_params_appender_t &)=delete
route_params_appender_t(route_params_t::named_parameters_container_t &named_parameters, route_params_t::indexed_parameters_container_t &indexed_parameters)
Definition express.hpp:246
Helper class for holding a unique instance of char array with target_path value.
Parameters extracted from route.
Definition express.hpp:57
named_parameters_container_t::const_reference find_named_parameter_with_check(string_view_t key) const
Definition express.hpp:154
auto indexed_parameters_size() const noexcept
Definition express.hpp:137
bool has(string_view_t key) const noexcept
Check parameter.
Definition express.hpp:103
void match(std::unique_ptr< char[] > request_target, std::shared_ptr< std::string > key_names_buffer, string_view_t match, named_parameters_container_t named_parameters, indexed_parameters_container_t indexed_parameters)
Definition express.hpp:68
route_params_t(const route_params_t &)=delete
std::unique_ptr< char[] > m_request_target
A raw request target.
Definition express.hpp:179
string_view_t match() const noexcept
Matched route.
Definition express.hpp:92
named_parameters_container_t m_named_parameters
Named params.
Definition express.hpp:188
std::vector< string_view_t > indexed_parameters_container_t
Definition express.hpp:61
route_params_t & operator=(route_params_t &&)=default
auto named_parameters_size() const noexcept
Get number of parameters.
Definition express.hpp:136
indexed_parameters_container_t m_indexed_parameters
Indexed params.
Definition express.hpp:191
route_params_t(route_params_t &&)=default
string_view_t operator[](string_view_t key) const
Get named parameter.
Definition express.hpp:96
std::optional< string_view_t > get_param(string_view_t key) const noexcept
Get the value of a parameter if it exists.
Definition express.hpp:111
std::vector< std::pair< string_view_t, string_view_t > > named_parameters_container_t
Definition express.hpp:59
named_parameters_container_t::const_iterator find_named_parameter(string_view_t key) const noexcept
Definition express.hpp:142
string_view_t m_match
Matched pattern.
Definition express.hpp:185
std::shared_ptr< std::string > m_key_names_buffer
Shared buffer for string_view of named parameterts names.
Definition express.hpp:182
#define RESTINIO_FMT_FORMAT_STRING(s)
Stuff related to method_matchers.
std::vector< param_appender_t< Route_Param_Appender > > param_appender_sequence_t
A sequence of appenders for submatches.
path2regex::param_appender_sequence_t< route_params_appender_t > param_appender_sequence_t
Definition express.hpp:275
std::function< request_handling_status_t(generic_request_handle_t< Extra_Data >) > generic_non_matched_request_handler_t
A generic type of handler for non-matched requests.
std::function< request_handling_status_t( generic_request_handle_t< Extra_Data >, route_params_t) > generic_express_request_handler_t
Type of generic handler for one route.
Definition express.hpp:442
generic_express_request_handler_t< no_extra_data_factory_t::data_t > express_request_handler_t
Type of a handler for one route in the case when there is no extra-data in request object.
Definition express.hpp:459
std::shared_ptr< generic_request_t< Extra_Data > > generic_request_handle_t
An alias for shared-pointer to incoming request.
run_on_this_thread_settings_t< Traits > on_this_thread()
A special marker for the case when http_server must be run on the context of the current thread.
std::string_view string_view_t
constexpr request_handling_status_t request_not_handled() noexcept
request_handling_status_t
Request handling status.
Value_Type get(const router::route_params_t &params, string_view_t key)
Cast named parameter value to a given type.
Definition express.hpp:853
The definition of the non_matched_request_handler type.
The default extra-data-factory to be used in server's traits if a user doesn't specify own one.
Resulting regex and param extraction for a specific route.
Route params private internals accessor.
Definition express.hpp:203
static const auto & named_parameters(const route_params_t &rp) noexcept
Get values containers for all parameters (used in unit tests).
Definition express.hpp:225
static const auto & indexed_parameters(const route_params_t &rp) noexcept
Definition express.hpp:231
static void match(route_params_t &rp, std::unique_ptr< char[] > request_target, std::shared_ptr< std::string > key_names_buffer, string_view_t match_, route_params_t::named_parameters_container_t named_parameters, route_params_t::indexed_parameters_container_t indexed_parameters)
Init parameters with a matched route params.
Definition express.hpp:206
virtual bool match(const http_method_id_t &method) const noexcept=0
Is the specified method can be applied to a route?
Regex engine implementation for using with standard regex implementation.
Implementation of target_path_holder helper class.