RESTinio
authorization.hpp
Go to the documentation of this file.
1 /*
2  * RESTinio
3  */
4 
5 /*!
6  * @file
7  * @brief Stuff related to value of Authorization HTTP-field.
8  *
9  * @since v.0.6.7
10  */
11 
12 #pragma once
13 
14 #include <restinio/helpers/http_field_parsers/basics.hpp>
15 
16 #include <iostream>
17 #include <variant>
18 
19 namespace restinio
20 {
21 
22 namespace http_field_parsers
23 {
24 
26 {
27 
29 
30 //
31 // is_token68_char_predicate_t
32 //
33 /*!
34  * @brief A preducate for symbol_producer_template that checks that
35  * a symbol can be used inside token68 from RFC7235.
36  *
37  * @since v.0.6.7
38  */
41 {
43 
44  [[nodiscard]]
45  bool
46  operator()( const char actual ) const noexcept
47  {
48  return base_type_t::operator()(actual)
49  || '-' == actual
50  || '.' == actual
51  || '_' == actual
52  || '~' == actual
53  || '+' == actual
54  || '/' == actual
55  ;
56  }
57 };
58 
59 //
60 // token68_symbol_p
61 //
62 [[nodiscard]]
63 inline auto
65 {
66  return restinio::easy_parser::impl::symbol_producer_template_t<
67  is_token68_char_predicate_t >{};
68 }
69 
70 //
71 // token68_t
72 //
73 /*!
74  * @brief A structure for holding a value of token68 from RFC7235.
75  *
76  * The actual value of token68 is stored as `std::string` inside that
77  * struct.
78  *
79  * @since v.0.6.7
80  */
81 struct token68_t
82 {
84 };
85 
86 inline std::ostream &
87 operator<<( std::ostream & to, const token68_t & v )
88 {
89  return (to << v.value);
90 }
91 
92 //
93 // token68_p
94 //
95 [[nodiscard]]
96 inline auto
98 {
99  return produce< token68_t >(
100  produce< std::string >(
101  repeat( 1, N, token68_symbol_p() >> to_container() ),
102  repeat( 0, N, symbol_p('=') >> to_container() )
103  ) >> &token68_t::value
104  );
105 }
106 
107 } /* authorization_details */
108 
109 //
110 // authorization_value_t
111 //
112 /*!
113  * @brief Tools for working with the value of Authorization HTTP-field.
114  *
115  * This struct represents parsed value of HTTP-field Authorization
116  * (see https://tools.ietf.org/html/rfc7235):
117 @verbatim
118 Authorization = credentials
119 
120 credentials = auth-scheme [ 1*SP ( token68 / [ #auth-param ] ) ]
121 
122 auth-scheme = token
123 
124 auth-param = token BWS "=" BWS ( token / quoted-string )
125 
126 token68 = 1*( ALPHA / DIGIT / "-" / "." / "_" / "~" / "+" / "/" ) *"="
127 @endverbatim
128  *
129  * @since v.0.6.7
130  */
132 {
133  //! An indicator of the source form of the value of a parameter.
134  enum class value_form_t
135  {
136  //! The value of a parameter was specified as token.
137  token,
138  //! The value of a parameter was specified as quoted_string.
140  };
141 
142  //! A storage for the value of a parameter.
144  {
145  //! The value of a parameter.
147  //! How this value was represented: as a token, or a quoted string?
149  };
150 
151  //! A storage for a parameter with a name and a value.
152  struct param_t
153  {
154  //! The name of a parameter.
156  //! The value of a parameter.
158  };
159 
160  //! Type of container for holding parameters.
162 
163  //! Type for holding a value of token68 from RFC7235.
164  using token68_t = authorization_details::token68_t;
165 
166  //! Type for holding a parameter for authorization.
168 
169  //! A value of auth-scheme.
171  //! A parameter for authorization.
172  /*!
173  * @note
174  * It can be empty.
175  */
177 
178  /*!
179  * @brief A factory function for a parser of Authorization value.
180  *
181  * @since v.0.6.7
182  */
183  [[nodiscard]]
184  static auto
186  {
187  using namespace authorization_details;
188 
189  auto token_to_v = []( std::string v ) -> param_value_t {
190  return { std::move(v), value_form_t::token };
191  };
192  auto qstring_to_v = []( std::string v ) -> param_value_t {
193  return { std::move(v), value_form_t::quoted_string };
194  };
195 
196  // NOTE: token68 should consume all input.
197  // So there should not be any symbols after the value.
198  auto token68_seq = sequence(
199  token68_p() >> as_result(),
200  not_clause( any_symbol_p() >> skip() ) );
201  // Parameters list can be empty.
202  auto params_seq = maybe_empty_comma_separated_list_p< param_container_t >(
203  produce< param_t >(
204  token_p() >> to_lower() >> &param_t::name,
205  ows(),
206  symbol('='),
207  ows(),
208  produce< param_value_t >(
209  alternatives(
210  token_p() >> convert( token_to_v ) >> as_result(),
211  quoted_string_p() >> convert( qstring_to_v )
212  >> as_result()
213  )
214  ) >> &param_t::value
215  )
216  ) >> as_result();
217 
218  return produce< authorization_value_t >(
219  token_p() >> to_lower() >> &authorization_value_t::auth_scheme,
220  maybe(
221  repeat( 1, N, space() ),
222  produce< auth_param_t >(
223  alternatives( token68_seq, params_seq )
224  ) >> &authorization_value_t::auth_param
225  )
226  );
227  }
228 
229  /*!
230  * @brief An attempt to parse Authorization HTTP-field.
231  *
232  * @since v.0.6.7
233  */
234  [[nodiscard]]
235  static expected_t<
239  {
240  return restinio::easy_parser::try_parse( what, make_parser() );
241  }
242 };
243 
244 //
245 // Various helpers for dumping values to std::ostream.
246 //
247 inline std::ostream &
249  std::ostream & to,
251 {
252  if(authorization_value_t::value_form_t::token == v.form)
253  to << v.value;
254  else
255  to << '"' << v.value << '"';
256  return to;
257 }
258 
259 inline std::ostream &
261  std::ostream & to,
262  const authorization_value_t::param_t & v )
263 {
264  return (to << v.name << '=' << v.value);
265 }
266 
267 inline std::ostream &
269  std::ostream & to,
271 {
272  struct printer_t
273  {
274  std::ostream & to;
275 
276  void
277  operator()( const authorization_value_t::token68_t & t ) const
278  {
279  to << t;
280  }
281 
282  void
283  operator()( const authorization_value_t::param_container_t & c ) const
284  {
285  bool first = true;
286  to << '{';
287  for( const auto & param : c )
288  {
289  if( !first )
290  to << ", ";
291  else
292  first = false;
293 
294  to << param;
295  }
296  to << '}';
297  }
298  };
299 
300  std::visit( printer_t{ to }, p );
301 
302  return to;
303 }
304 
305 inline std::ostream &
307  std::ostream & to,
308  const authorization_value_t & v )
309 {
310  return (to << v.auth_scheme << ' ' << v.auth_param);
311 }
312 
313 } /* namespace http_field_parsers */
314 
315 } /* namespace restinio */
expected_t< std::optional< string_view_t >, not_found_t > find_first(const parameter_with_optional_value_container_t &where, string_view_t what)
A helper function to find the first occurence of a parameter with the specified value.
Definition: basics.hpp:1740
static expected_t< authorization_value_t, restinio::easy_parser::parse_error_t > try_parse(string_view_t what)
An attempt to parse Authorization HTTP-field.
std::ostream & operator<<(std::ostream &to, const authorization_value_t::auth_param_t &p)
value_form_t
An indicator of the source form of the value of a parameter.
std::ostream & operator<<(std::ostream &to, const authorization_value_t::param_value_t &v)
static auto make_parser()
A factory function for a parser of Authorization value.
std::enable_if< std::is_same< Parameter_Container, query_string_params_t >::value||std::is_same< Parameter_Container, router::route_params_t >::value, std::optional< Value_Type > >::type opt_value(const Parameter_Container &params, string_view_t key)
Gets the value of a parameter specified by key wrapped in std::optional<Value_Type> if parameter exis...
Definition: value_or.hpp:64
A storage for a parameter with a name and a value.
value_form_t form
How this value was represented: as a token, or a quoted string?
The value of a parameter was specified as token.
The value of a parameter was specified as quoted_string.
std::string auth_scheme
A value of auth-scheme.
Tools for working with the value of Authorization HTTP-field.
std::ostream & operator<<(std::ostream &to, const authorization_value_t &v)
std::ostream & operator<<(std::ostream &to, const token68_t &v)
A preducate for symbol_producer_template that checks that a symbol can be used inside token68 from RF...
std::ostream & operator<<(std::ostream &to, const authorization_value_t::param_t &v)
A structure for holding a value of token68 from RFC7235.
auth_param_t auth_param
A parameter for authorization.