RESTinio
Loading...
Searching...
No Matches
express.hpp
Go to the documentation of this file.
1/*
2 restinio
3*/
4
8
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
56class route_params_t final
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 );
76 m_key_names_buffer = std::move( key_names_buffer );
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
92 string_view_t match() const noexcept { return m_match; }
93
97 {
98 return find_named_parameter_with_check( key ).second;
99 }
100
102 bool
103 has( string_view_t key ) const noexcept
104 {
105 return m_named_parameters.end() != find_named_parameter( key );
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
136 auto named_parameters_size() const noexcept { return m_named_parameters.size(); }
137 auto indexed_parameters_size() const noexcept { return m_indexed_parameters.size(); }
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
207 route_params_t & rp,
208 std::unique_ptr< char[] > request_target,
209 std::shared_ptr< std::string > key_names_buffer,
210 string_view_t match_,
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 &
225 named_parameters( const route_params_t & rp ) noexcept
226 {
227 return rp.m_named_parameters;
228 }
229
230 static const auto &
231 indexed_parameters( const route_params_t & rp ) noexcept
232 {
233 return rp.m_indexed_parameters;
234 }
235
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,
293 regex_t route_regex,
294 std::shared_ptr< std::string > named_params_buffer,
295 param_appender_sequence_t param_appender_sequence )
296 : m_route_regex{ std::move( route_regex ) }
297 , m_named_params_buffer{ std::move( named_params_buffer ) }
298 , m_param_appender_sequence{ std::move( param_appender_sequence ) }
299 {
300 assign( m_method_matcher, std::move(method) );
301 }
302
311 template< typename Method_Matcher >
313 Method_Matcher && method_matcher,
314 regex_t route_regex,
315 std::shared_ptr< std::string > named_params_buffer,
316 param_appender_sequence_t param_appender_sequence )
317 : m_route_regex{ std::move( route_regex ) }
318 , m_named_params_buffer{ std::move( named_params_buffer ) }
319 , m_param_appender_sequence{ std::move( param_appender_sequence ) }
320 {
321 assign(
323 std::forward<Method_Matcher>(method_matcher) );
324 }
325
326 route_matcher_t() = default;
328
330 bool
332 target_path_holder_t & target_path,
333 route_params_t & parameters ) const
334 {
335 match_results_t matches;
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 ];
367 param_appender,
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 {
377 param_appender,
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,
399 target_path_holder_t & target_path,
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 >
493 Method_Matcher && method_matcher,
494 matcher_init_data_t matcher_data,
496 : m_matcher{
497 std::forward<Method_Matcher>( method_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 >
519 Method_Matcher && method_matcher,
520 string_view_t route_path,
521 const path2regex::options_t & options,
524 std::forward<Method_Matcher>( method_matcher ),
525 path2regex::path2regex< impl::route_params_appender_t, Regex_Engine >(
526 route_path,
527 options ),
528 std::move( handler ) }
529 {}
530
531 template< typename Method_Matcher >
533 Method_Matcher && method_matcher,
534 string_view_t route_path,
537 std::forward<Method_Matcher>( method_matcher ),
538 route_path,
539 path2regex::options_t{},
540 std::move( handler ) }
541 {}
542
545 [[nodiscard]]
546 bool
548 const http_request_header_t & h,
549 impl::target_path_holder_t & target_path,
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<
578 typename Regex_Engine = std_regex_engine_t >
580 Regex_Engine,
582
583//
584// generic_express_router_t
585//
586
588
611template<
612 typename Regex_Engine,
613 typename Extra_Data_Factory >
615{
616 public:
621 Regex_Engine,
622 Extra_Data_Factory
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
663 Method_Matcher && method_matcher,
664 string_view_t route_path,
666 {
668 std::forward<Method_Matcher>(method_matcher),
669 route_path,
671 std::move( handler ) );
672 }
673
674 template< typename Method_Matcher >
675 void
677 Method_Matcher && method_matcher,
678 string_view_t route_path,
679 const path2regex::options_t & options,
681 {
682 m_handlers.emplace_back(
683 std::forward<Method_Matcher>(method_matcher),
684 route_path,
685 options,
686 std::move( handler ) );
687 }
688
689 void
691 string_view_t route_path,
693 {
695 http_method_delete(),
696 route_path,
697 std::move( handler ) );
698 }
699
700 void
702 string_view_t route_path,
703 const path2regex::options_t & options,
705 {
707 http_method_delete(),
708 route_path,
709 options,
710 std::move( handler ) );
711 }
712
713 void
715 string_view_t route_path,
717 {
719 http_method_get(),
720 route_path,
721 std::move( handler ) );
722 }
723
724 void
726 string_view_t route_path,
727 const path2regex::options_t & options,
729 {
731 http_method_get(),
732 route_path,
733 options,
734 std::move( handler ) );
735 }
736
737 void
739 string_view_t route_path,
741 {
743 http_method_head(),
744 route_path,
745 std::move( handler ) );
746 }
747
748 void
750 string_view_t route_path,
751 const path2regex::options_t & options,
753 {
755 http_method_head(),
756 route_path,
757 options,
758 std::move( handler ) );
759 }
760
761 void
763 string_view_t route_path,
765 {
767 http_method_post(),
768 route_path,
769 std::move( handler ) );
770 }
771
772 void
774 string_view_t route_path,
775 const path2regex::options_t & options,
777 {
779 http_method_post(),
780 route_path,
781 options,
782 std::move( handler ) );
783 }
784
785 void
787 string_view_t route_path,
789 {
791 http_method_put(),
792 route_path,
793 std::move( handler ) );
794 }
795
796 void
798 string_view_t route_path,
799 const path2regex::options_t & options,
801 {
803 http_method_put(),
804 route_path,
805 options,
806 std::move( handler ) );
807 }
808
809
811 void
816
817 private:
819 Regex_Engine,
820 Extra_Data_Factory
821 >;
822
824 std::vector< route_entry_t > m_handlers;
825
828};
829
830//
831// express_router_t
832//
842template<
843 typename Regex_Engine = std_regex_engine_t >
845 Regex_Engine,
847
848} /* namespace router */
849
851template < typename Value_Type >
852Value_Type
854{
855 return std::get< Value_Type >( params[ key ] );
856}
857
859template < typename Value_Type >
860Value_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
path2regex::impl::route_regex_matcher_data_t< impl::route_params_appender_t, Regex_Engine > matcher_init_data_t
Definition express.hpp:486
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
generic_express_route_entry_t< Regex_Engine, Extra_Data_Factory > route_entry_t
Definition express.hpp:818
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
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
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 ...
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.
data_t giveout_data() noexcept
Give out the value from holder.
string_view_t view() const noexcept
Get access to the value of target_path.
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
generic_express_router_t< Regex_Engine, no_extra_data_factory_t > express_router_t
A type of express-like router for the case when the default extra-data-factory is specified in the se...
Definition express.hpp:844
generic_express_route_entry_t< Regex_Engine, no_extra_data_factory_t > express_route_entry_t
An alias for a single route entry in the case when the default extra-data-factory is used in server's...
Definition express.hpp:579
std::shared_ptr< generic_request_t< Extra_Data > > generic_request_handle_t
An alias for shared-pointer to incoming request.
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.
http_method_id_t method() const noexcept
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
Regex engine implementation for using with standard regex implementation.
Implementation of target_path_holder helper class.