RESTinio
chunked_input_info.hpp
Go to the documentation of this file.
1 /*
2  restinio
3 */
4 
5 /*!
6  * @file
7  * @brief Information about chunked encoded body.
8  * @since v.0.6.9
9  */
10 
11 #pragma once
12 
13 #include <restinio/exception.hpp>
14 #include <restinio/http_headers.hpp>
15 
16 #include <restinio/impl/include_fmtlib.hpp>
17 
18 #include <vector>
19 #include <memory>
20 
21 namespace restinio
22 {
23 
24 //
25 // chunk_ext_param_t
26 //
27 
28 /**
29  * @brief Chunk extension parameter.
30  *
31  * @since v.0.7.0
32  */
34 {
37 };
38 
41 
42 //
43 // chunk_info_t
44 //
45 /*!
46  * @brief Information about one chunk in an incoming request with
47  * chunked encoding.
48  *
49  * In RESTinio v.0.6.9 all chunks are concatenated into the one body.
50  * The information about individual chunks preserved in the form
51  * of vector of chunk_info_t objects. Every object contains
52  * the offset from the begining of the concatenated body and the size
53  * of the chunk. This information allows to extract the corresponding
54  * fragment from the whole body.
55  *
56  * @since v.0.6.9
57  */
59 {
62 
63  /**
64  * @brief Storage of chunk extension parameters
65  *
66  * The instance will be allocated only if chunk has extension's parameters.
67  *
68  * @since v.0.7.0
69  */
71 public:
72  //! Initializing constructor.
74  std::size_t started_at,
75  std::size_t size,
76  chunk_ext_params_unique_ptr_t ext_params )
78  , m_size{ size }
80  {}
81 
82  //! Get the starting offset of chunk.
83  [[nodiscard]]
84  std::size_t
85  started_at() const noexcept { return m_started_at; }
86 
87  //! Get the size of chunk.
88  [[nodiscard]]
89  std::size_t
90  size() const noexcept { return m_size; }
91 
92  //! Extract the chunk value from the whole body.
93  /*!
94  * @attention
95  * This method doesn't check the possibility of the extraction.
96  * An attempt of extraction of chunk from a body that is too small
97  * is undefined behavior.
98  */
99  [[nodiscard]]
102  {
103  return full_body.substr( m_started_at, m_size );
104  }
105 
106  //! Extract the chunk value from the whole body.
107  /*!
108  * A check of possibility of extraction is performed.
109  *
110  * @throw exception_t if @a full_body is too small to hold the chunk.
111  */
112  [[nodiscard]]
115  {
116  if( m_started_at >= full_body.size() ||
117  m_started_at + m_size > full_body.size() )
118  {
119  throw exception_t{
120  fmt::format(
121  RESTINIO_FMT_FORMAT_STRING(
122  "unable to make a chunk (started_at:{}, size: {}) "
123  "from a body with length:{}" ),
124  m_started_at,
125  m_size,
126  full_body.size() )
127  };
128  }
129 
130  return make_string_view_nonchecked( full_body );
131  }
132 
133  /**
134  * @brief Get a list of chunk extension's params.
135  *
136  * In case this chunk has extensions this function returns a valid pointer
137  * to a vector of ext parameters (name-value pairs).
138  *
139  * @code
140  * auto handle_request( restinio::request_t req ) {
141  * const auto * chunked_input = req.chunked_input_info();
142  * if( !chunked_input )
143  * {
144  * return restinio::request_rejected();
145  * }
146  * auto resp = req->create_response()
147  * .append_header_date_field()
148  * .append_header( "Content-Type", "text/plain; charset=utf-8" );
149  *
150  * int i = 0;
151  * for( const auto & ch : chunked_input->chunks() )
152  * {
153  * if( const auto * params = ch.ext_params(); params )
154  * {
155  * resp.append_body(
156  * fmt::format(
157  * FMT_STRING( "Chunk #{} has {} ext param(s)\r\n" ),
158  * i++,
159  * params->size() ) );
160  * }
161  * else
162  * {
163  * resp.append_body(
164  * fmt::format(
165  * FMT_STRING( "Chunk #{} has no ext params\r\n" ),
166  * i++ ) );
167  * }
168  * }
169  * return resp.done();
170  * }
171  * @endcode
172  *
173  * @since v.0.7.0
174  */
176  ext_params() const noexcept
177  {
178  return m_ext_params.get();
179  }
180 };
181 
182 namespace impl
183 {
184 
185 //
186 // chunked_input_info_block_t
187 //
188 /*!
189  * @brief Bunch of data related to chunked input.
190  *
191  * @since v.0.6.9
192  */
194 {
195  //! All non-empty chunks from the input.
197 
198  //! Trailing fields found in the input.
199  /*!
200  * @note
201  * Can be empty.
202  */
204 };
205 
206 } /* namespace impl */
207 
208 //
209 // chunked_input_info_t
210 //
211 /*!
212  * @brief An information about chunks and trailing fields in the
213  * incoming request.
214  *
215  * This information is collected if chunked encoding is used in the
216  * incoming request.
217  *
218  * @since v.0.6.9
219  */
221 {
222  //! Actual data.
224 
225 public:
226  //! Default constructor. Makes empty object.
227  chunked_input_info_t() = default;
228  //! Initializing constructor.
229  /*!
230  * @note
231  * This constrictor is intended to be used inside RESTinio and
232  * can be changed in future versions without any notice.
233  */
236  : m_info{ std::move(info) }
237  {}
238 
239  //! Get the count of chunks.
240  /*!
241  * @retval 0 if there is no chunks in the incoming request.
242  */
243  [[nodiscard]]
244  std::size_t
245  chunk_count() const noexcept { return m_info.m_chunks.size(); }
246 
247  //! Get reference to the description of a chunk by index.
248  /*!
249  * @attention
250  * This method doesn't check the validity of @a index.
251  * An attempt to access non-existent chunk is undefined behavior.
252  */
253  [[nodiscard]]
254  const chunk_info_t &
255  chunk_at_nochecked( std::size_t index ) const noexcept
256  {
257  return m_info.m_chunks[ index ];
258  }
259 
260  //! Get reference to the description of a chunk by index.
261  /*!
262  * @throw std::exception if @a index is invalid.
263  */
264  [[nodiscard]]
265  const chunk_info_t &
266  chunk_at( std::size_t index ) const
267  {
268  return m_info.m_chunks.at( index );
269  }
270 
271  //! Get access to the container with description of chunks.
272  /*!
273  * @note
274  * The actual type of the container is not specified and can
275  * be changed from version to version. But this container
276  * can be sequentially enumerated from begin() to the end().
277  */
278  [[nodiscard]]
279  const auto &
280  chunks() const noexcept
281  {
282  return m_info.m_chunks;
283  }
284 
285  //! Get access to the container with trailing fields.
286  /*!
287  * @note
288  * This can be an empty container if there is no trailing fields
289  * in the incoming request.
290  */
291  [[nodiscard]]
292  const http_header_fields_t &
293  trailing_fields() const noexcept
294  {
295  return m_info.m_trailing_fields;
296  }
297 };
298 
299 //
300 // chunked_input_info_unique_ptr_t
301 //
302 /*!
303  * @brief Alias of unique_ptr for chunked_input_info.
304  *
305  * @since v.0.6.9
306  */
309 
310 } /* namespace restinio */
chunk_info_t(std::size_t started_at, std::size_t size, chunk_ext_params_unique_ptr_t ext_params)
Initializing constructor.
string_view_t make_string_view(string_view_t full_body) const
Extract the chunk value from the whole body.
std::size_t chunk_count() const noexcept
Get the count of chunks.
std::size_t size() const noexcept
Get the size of chunk.
Bunch of data related to chunked input.
Information about one chunk in an incoming request with chunked encoding.
nullable_pointer_t< const chunk_ext_params_t > ext_params() const noexcept
Get a list of chunk extension&#39;s params.
chunk_ext_params_unique_ptr_t m_ext_params
Storage of chunk extension parameters.
impl::chunked_input_info_block_t m_info
Actual data.
std::vector< chunk_info_t > m_chunks
All non-empty chunks from the input.
chunked_input_info_t()=default
Default constructor. Makes empty object.
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
An information about chunks and trailing fields in the incoming request.
std::size_t started_at() const noexcept
Get the starting offset of chunk.
http_header_fields_t m_trailing_fields
Trailing fields found in the input.
const auto & chunks() const noexcept
Get access to the container with description of chunks.
const chunk_info_t & chunk_at_nochecked(std::size_t index) const noexcept
Get reference to the description of a chunk by index.
string_view_t make_string_view_nonchecked(string_view_t full_body) const noexcept
Extract the chunk value from the whole body.
const chunk_info_t & chunk_at(std::size_t index) const
Get reference to the description of a chunk by index.
chunked_input_info_t(impl::chunked_input_info_block_t info)
Initializing constructor.
Chunk extension parameter.
const http_header_fields_t & trailing_fields() const noexcept
Get access to the container with trailing fields.