RESTinio
Loading...
Searching...
No Matches
uri_helpers.hpp
Go to the documentation of this file.
1/*
2 restinio
3*/
4
9#pragma once
10
12
15
16#include <optional>
17#include <string>
18#include <unordered_map>
19
20namespace restinio
21{
22
23namespace impl
24{
25
26inline const char *
27modified_memchr( int chr , const char * from, const char * to )
28{
29 const char * result = static_cast< const char * >(
30 std::memchr( from, chr, static_cast<std::size_t>(to - from) ) );
31
32 return result ? result : to;
33}
34
35} /* namespace impl */
36
37//
38// query_string_params_t
39//
40
43{
44 public:
45 using parameters_container_t = std::vector< std::pair< string_view_t, string_view_t > >;
46
50 std::unique_ptr< char[] > data_buffer,
51 parameters_container_t parameters )
52 : m_data_buffer{ std::move( data_buffer ) }
53 , m_parameters{ std::move( parameters ) }
54 {}
55
59 std::unique_ptr< char[] > data_buffer,
60 std::optional< string_view_t > tag )
61 : m_data_buffer{ std::move( data_buffer ) }
62 , m_tag{ tag }
63 {}
64
67
70
74 {
75 return find_parameter_with_check( key ).second;
76 }
77
79 bool
80 has( string_view_t key ) const noexcept
81 {
82 return m_parameters.end() != find_parameter( key );
83 }
84
87 std::optional< string_view_t >
88 get_param( string_view_t key ) const noexcept
89 {
90 const auto it = find_parameter( key );
91
92 return m_parameters.end() != it ?
93 std::optional< string_view_t >{ it->second } :
94 std::optional< string_view_t >{ std::nullopt };
95 }
96
98 auto size() const noexcept { return m_parameters.size(); }
99
102 bool empty() const noexcept { return m_parameters.empty(); }
103
106 parameters_container_t::const_iterator
108 {
109 return m_parameters.begin();
110 }
111
112 parameters_container_t::const_iterator
114 {
115 return m_parameters.end();
116 }
118
120
131 auto tag() const noexcept { return m_tag; }
132
133 private:
134 parameters_container_t::const_iterator
136 {
137 return
138 std::find_if(
139 m_parameters.begin(),
140 m_parameters.end(),
141 [&]( const auto p ){
142 return key == p.first;
143 } );
144 }
145
146 parameters_container_t::const_reference
148 {
149 auto it = find_parameter( key );
150
151 if( m_parameters.end() == it )
152 {
153 throw exception_t{
154 fmt::format(
156 "unable to find parameter \"{}\"" ),
157 std::string{ key.data(), key.size() } ) };
158 }
159
160 return *it;
161 }
162
164 std::unique_ptr< char[] > m_data_buffer;
166
168
169 std::optional< string_view_t > m_tag;
170};
171
173template < typename Value_Type >
176{
177 return std::get< Value_Type >( params[ key ] );
178}
179
180namespace parse_query_traits
181{
182
183namespace details
184{
185
196{
197 static string_view_t::size_type
200 string_view_t::size_type start_from ) noexcept
201 {
202 return where.find_first_of( "&;", start_from );
203 }
204};
205
216{
217 static string_view_t::size_type
220 string_view_t::size_type start_from ) noexcept
221 {
222 return where.find_first_of( '&', start_from );
223 }
224};
225
226} /* namespace details */
227
249
267
294
330
331} /* namespace parse_query_traits */
332
339{
341 std::string m_description;
342
343public:
346 {}
351
353 [[nodiscard]]
354 const std::string &
356
358
363 [[nodiscard]]
364 std::string
366};
367
396template< typename Parse_Traits >
397[[nodiscard]]
402{
403 std::unique_ptr< char[] > data_buffer;
405
406 if( !original_query_string.empty() )
407 {
408 // Because query string is not empty a new buffer should be
409 // allocated and query string should be copied to it.
410 data_buffer.reset( new char[ original_query_string.size() ] );
411 std::memcpy(
412 data_buffer.get(),
414 original_query_string.size() );
415
416 // Work with created buffer:
418 data_buffer.get(),
420 };
421 string_view_t::size_type pos{ 0 };
422 const string_view_t::size_type end_pos = work_query_string.size();
423
424 while( pos < end_pos )
425 {
426 const auto eq_pos = work_query_string.find_first_of( '=', pos );
427
428 if( string_view_t::npos == eq_pos )
429 {
430 // Since v.0.4.9 we should check the presence of tag (web beacon)
431 // in query string.
432 // Tag can be the only item in query string.
433 if( pos != 0u )
434 // The query string has illegal format.
435 return make_unexpected( parse_query_failure_t{
436 fmt::format(
438 "invalid format of key-value pairs in query_string, "
439 "no '=' symbol starting from position {}" ),
440 pos )
441 } );
442 else
443 {
444 // Query string contains only tag (web beacon).
446 utils::try_inplace_unescape_percent_encoding< Parse_Traits >(
447 &data_buffer[ pos ],
448 end_pos - pos );
450 return make_unexpected( parse_query_failure_t{
451 std::move(tag_unescape_result.error())
452 } );
453
454 const string_view_t tag = work_query_string.substr(
456
457 return query_string_params_t{ std::move( data_buffer ), tag };
458 }
459 }
460
461 const auto eq_pos_next = eq_pos + 1u;
462 auto separator_pos = Parse_Traits::find_next_separator(
464 if( string_view_t::npos == separator_pos )
466
467 // Handle next pair of parameters found.
469 utils::try_inplace_unescape_percent_encoding< Parse_Traits >(
470 &data_buffer[ pos ],
471 eq_pos - pos );
473 return make_unexpected( parse_query_failure_t{
474 std::move(key_unescape_result.error())
475 } );
476
478 utils::try_inplace_unescape_percent_encoding< Parse_Traits >(
482 return make_unexpected( parse_query_failure_t{
483 std::move(value_unescape_result.error())
484 } );
485
486 parameters.emplace_back(
489
490 pos = separator_pos + 1u;
491 }
492 }
493
495 std::move( data_buffer ),
496 std::move( parameters )
497 };
498}
499
501
517template< typename Parse_Traits = parse_query_traits::restinio_defaults >
518[[nodiscard]]
519query_string_params_t
523{
525 if( !r )
526 throw exception_t{ std::move(r.error().giveout_description()) };
527
528 return std::move(*r);
529}
530
531} /* namespace restinio */
Exception class for all exceptions thrown by RESTinio.
Definition exception.hpp:26
Type that indicates a failure of an attempt of query-string parsing.
std::string giveout_description() noexcept
Get out the value of the description of the failure.
const std::string & description() const noexcept
Get a reference to the description of the failure.
std::string m_description
Description of a failure.
parse_query_failure_t(std::string description)
parse_query_failure_t(utils::unescape_percent_encoding_failure_t &&failure)
Parameters container for query strings parameters.
std::unique_ptr< char[] > m_data_buffer
Shared buffer for string_view of named parameterts names.
query_string_params_t(query_string_params_t &&)=default
query_string_params_t(std::unique_ptr< char[] > data_buffer, std::optional< string_view_t > tag)
Constructor for the case when query string contains only tag (web beacon).
auto tag() const noexcept
Get the tag (web beacon) part.
bool empty() const noexcept
Is there any parameters?
auto size() const noexcept
Get the size of parameters.
parameters_container_t::const_iterator begin() const noexcept
query_string_params_t & operator=(query_string_params_t &&)=default
string_view_t operator[](string_view_t key) const
Get parameter.
parameters_container_t m_parameters
std::vector< std::pair< string_view_t, string_view_t > > parameters_container_t
std::optional< string_view_t > get_param(string_view_t key) const noexcept
Get the value of a parameter if it exists.
query_string_params_t(std::unique_ptr< char[] > data_buffer, parameters_container_t parameters)
Constructor for the case when query string empty of contains a set of key-value pairs.
parameters_container_t::const_iterator find_parameter(string_view_t key) const noexcept
parameters_container_t::const_reference find_parameter_with_check(string_view_t key) const
parameters_container_t::const_iterator end() const noexcept
bool has(string_view_t key) const noexcept
Check parameter.
query_string_params_t(const query_string_params_t &)=delete
std::optional< string_view_t > m_tag
Tag (or web beacon) part.
Type that indicates a failure of unescaping of percent-encoded symbols.
A special wrapper around fmtlib include files.
#define RESTINIO_FMT_FORMAT_STRING(s)
const char * modified_memchr(int chr, const char *from, const char *to)
query_string_params_t parse_query(string_view_t original_query_string)
Parse query key-value parts.
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.
expected_t< query_string_params_t, parse_query_failure_t > try_parse_query(string_view_t original_query_string)
Helper function for parsing query string.
std::string_view string_view_t
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
Helper class to be reused in implementation of query-string parsing traits.
static string_view_t::size_type find_next_separator(string_view_t where, string_view_t::size_type start_from) noexcept
Helper class to be reused in implementation of query-string parsing traits.
static string_view_t::size_type find_next_separator(string_view_t where, string_view_t::size_type start_from) noexcept
Traits for parsing a query string in JavaScript-compatible mode.
Traits for parsing a query string in a very relaxed mode.
Traits for the default RESTinio parser for query string.
Traits for parsing a query string in application/x-www-form-urlencoded mode.
The traits for escaping and unexcaping symbols in JavaScript-compatible mode.
Traits for escaping and unescaping symbols in a query string in very relaxed mode.
The default traits for escaping and unexcaping symbols in a query string.
Traits for escaping and unexcaping symbols in a query string in correspondence with application/x-www...