RESTinio
Toggle main menu visibility
Loading...
Searching...
No Matches
restinio
impl
parser_callbacks.ipp
Go to the documentation of this file.
1
/*
2
restinio
3
*/
4
5
/**
6
* @brief A helper function to get the pointer to a context object.
7
*/
8
[[nodiscard]]
inline
restinio
::
impl
::
http_parser_ctx_t
*
9
get_http_parser_ctx
( llhttp_t * parser )
10
{
11
return
reinterpret_cast
< restinio::impl::http_parser_ctx_t * >(
12
parser->data );
13
}
14
15
/*!
16
Callbacks used with http parser.
17
*/
18
19
inline
int
20
restinio_url_cb
( llhttp_t * parser,
const
char
* at, size_t length )
21
{
22
try
23
{
24
auto
* ctx = get_http_parser_ctx( parser );
25
26
ctx->m_header.append_request_target( at, length );
27
28
if
( ctx->m_header.request_target().length() >
29
ctx->m_limits.max_url_size() )
30
{
31
return
-1;
32
}
33
}
34
catch
(
const
std::exception & )
35
{
36
return
-1;
37
}
38
39
return
0;
40
}
41
42
inline
int
43
restinio_header_field_cb
( llhttp_t * parser,
const
char
*at, size_t length )
44
{
45
try
46
{
47
auto
* ctx = get_http_parser_ctx( parser );
48
49
// Maybe there are too many fields?
50
if
( ctx->m_total_field_count == ctx->m_limits.max_field_count() )
51
{
52
return
-1;
53
}
54
55
if
( ctx->m_current_field_name.size() + length >
56
ctx->m_limits.max_field_name_size() )
57
{
58
return
-1;
59
}
60
61
ctx->m_current_field_name.append( at, length );
62
}
63
catch
(
const
std::exception & )
64
{
65
return
-1;
66
}
67
68
return
0;
69
}
70
71
inline
int
72
restinio_header_field_complete_cb
( llhttp_t * parser )
73
{
74
try
75
{
76
auto
* ctx = get_http_parser_ctx( parser );
77
78
auto
& fields = ctx->m_leading_headers_completed
79
? ctx->m_chunked_info_block.m_trailing_fields
80
: ctx->m_header;
81
82
// Note: moving `ctx->m_current_field_name`
83
// also cleans the placeholder, so it
84
// becomes ready to accumulating next field.
85
fields.add_field(
86
std::move( ctx->m_current_field_name ),
87
std::string{} );
88
89
// At this point the number of parsed fields can be incremented.
90
ctx->m_total_field_count += 1u;
91
}
92
catch
(
const
std::exception & )
93
{
94
return
-1;
95
}
96
97
return
0;
98
}
99
100
101
inline
void
102
append_last_field_accessor
( http_header_fields_t & fields, string_view_t value )
103
{
104
fields.append_last_field( value );
105
}
106
107
inline
int
108
restinio_header_value_cb
( llhttp_t * parser,
const
char
*at, size_t length )
109
{
110
try
111
{
112
auto
* ctx = get_http_parser_ctx( parser );
113
114
http_header_fields_t & fields = ctx->m_leading_headers_completed
115
? ctx->m_chunked_info_block.m_trailing_fields
116
: ctx->m_header;
117
118
if
( ctx->m_last_value_total_size + length >=
119
ctx->m_limits.max_field_value_size() )
120
{
121
return
-1;
122
}
123
124
ctx->m_last_value_total_size += length;
125
126
append_last_field_accessor( fields, std::string{ at, length } );
127
}
128
catch
(
const
std::exception & )
129
{
130
return
-1;
131
}
132
133
return
0;
134
}
135
136
inline
int
137
restinio_header_value_complete_cb
( llhttp_t * parser )
138
{
139
// Reset value size counter for the next time.
140
get_http_parser_ctx( parser )->m_last_value_total_size = 0;
141
return
0;
142
}
143
144
inline
int
145
restinio_headers_complete_cb
( llhttp_t * parser )
146
{
147
auto
* ctx = get_http_parser_ctx( parser );
148
// Next time header_name/header_value callback should store
149
// values of trailing fields.
150
ctx->m_leading_headers_completed =
true
;
151
152
if
( ULLONG_MAX != parser->content_length &&
153
0 < parser->content_length )
154
{
155
// Maximum body size can be checked right now.
156
if
( parser->content_length > ctx->m_limits.max_body_size() )
157
{
158
return
-1;
159
}
160
161
try
162
{
163
ctx->m_body.reserve(
164
::restinio::utils::impl::uint64_to_size_t(
165
parser->content_length) );
166
}
167
catch
(
const
std::exception & )
168
{
169
return
-1;
170
}
171
}
172
173
return
0;
174
}
175
176
177
inline
int
178
restinio_body_cb
( llhttp_t * parser,
const
char
*at, size_t length )
179
{
180
try
181
{
182
auto
* ctx = get_http_parser_ctx( parser );
183
184
// The total size of the body should be checked.
185
const
auto
total_length =
static_cast
<std::uint64_t>(
186
ctx->m_body.size() ) + length;
187
if
( total_length > ctx->m_limits.max_body_size() )
188
{
189
return
-1;
190
}
191
192
ctx->m_body.append( at, length );
193
}
194
catch
(
const
std::exception & )
195
{
196
return
-1;
197
}
198
199
return
0;
200
}
201
202
inline
int
203
restinio_chunk_header_cb
( llhttp_t * parser )
204
{
205
try
206
{
207
// In on_chunk_header callback parser->content_length contains
208
// the size of the next chunk.
209
// If that size is 0 then it is the last chunk and it should be
210
// ignored.
211
if
( 0u != parser->content_length )
212
{
213
auto
* ctx = get_http_parser_ctx( parser );
214
215
// Store an info about the new chunk.
216
// If there will be an error at the next stage of parsing
217
// the incoming request the whole request's data will be dropped.
218
// So there is no need to care about that new item in m_chunks.
219
ctx->m_chunked_info_block.m_chunks.emplace_back(
220
ctx->m_body.size(),
221
::restinio::utils::impl::uint64_to_size_t(parser->content_length),
222
std::move( ctx->m_chunk_ext_params ) );
223
}
224
}
225
catch
(
const
std::exception & )
226
{
227
return
-1;
228
}
229
230
return
0;
231
}
232
233
inline
int
234
restinio_chunk_complete_cb
( llhttp_t *
/*parser*/
)
235
{
236
// There is nothing to do.
237
return
0;
238
}
239
240
template
<
typename
Http_Methods >
241
int
242
restinio_message_complete_cb
( llhttp_t * parser )
243
{
244
auto
* ctx = get_http_parser_ctx( parser );
245
246
ctx->m_message_complete =
true
;
247
ctx->m_header.method( Http_Methods::from_nodejs( parser->method ) );
248
249
if
( 0 == llhttp_get_upgrade( parser ) )
250
{
251
ctx->m_header.should_keep_alive( 0 != llhttp_should_keep_alive( parser ) );
252
}
253
else
254
{
255
ctx->m_header.connection( http_connection_header_t::upgrade );
256
}
257
258
return
HPE_PAUSED;
259
}
260
261
/*!
262
* @name Chunked encoding callbacks.
263
*
264
* @since v.0.7.0
265
*/
266
/// @{
267
inline
int
268
restinio_chunk_extension_name_cb
( llhttp_t * parser,
const
char
* at, size_t length )
269
{
270
try
271
{
272
auto
* ctx = get_http_parser_ctx( parser );
273
274
if
( !ctx->m_chunk_ext_params )
275
{
276
ctx->m_chunk_ext_params = std::make_unique<chunk_ext_params_t>();
277
}
278
279
auto
* ext_params = ctx->m_chunk_ext_params.get();
280
281
// Maybe there are too many fields?
282
if
( ext_params->size() == ctx->m_limits.max_field_count() )
283
{
284
return
-1;
285
}
286
287
if
( ctx->m_current_field_name.size() + length >
288
ctx->m_limits.max_field_name_size() )
289
{
290
return
-1;
291
}
292
293
ctx->m_current_field_name.append( at, length );
294
}
295
catch
(
const
std::exception & )
296
{
297
return
-1;
298
}
299
300
return
0;
301
}
302
303
inline
int
304
restinio_chunk_extension_name_complete_cb
( llhttp_t * parser )
305
{
306
try
307
{
308
auto
* ctx = get_http_parser_ctx( parser );
309
auto
* ext_params = ctx->m_chunk_ext_params.get();
310
311
ext_params->emplace_back(
312
chunk_ext_param_t{ std::move( ctx->m_current_field_name ), {} } );
313
}
314
catch
(
const
std::exception & )
315
{
316
return
-1;
317
}
318
319
return
0;
320
}
321
322
inline
int
323
restinio_chunk_extension_value_cb
( llhttp_t * parser,
const
char
* at, size_t length )
324
{
325
try
326
{
327
auto
* ctx = get_http_parser_ctx( parser );
328
auto
& value_receiver_str =
329
ctx->m_chunk_ext_params->back().m_value;
330
331
if
( value_receiver_str.size() + length >
332
ctx->m_limits.max_field_value_size() )
333
{
334
return
-1;
335
}
336
337
value_receiver_str.append( at, length );
338
}
339
catch
(
const
std::exception & )
340
{
341
return
-1;
342
}
343
344
return
0;
345
}
346
347
inline
int
348
restinio_chunk_extension_value_complete_cb
( llhttp_t *
/*parser*/
)
349
{
350
// There is nothing to do.
351
return
0;
352
}
353
/// @}
get_http_parser_ctx
restinio::impl::http_parser_ctx_t * get_http_parser_ctx(llhttp_t *parser)
A helper function to get the pointer to a context object.
Definition
parser_callbacks.ipp:9
restinio_header_field_complete_cb
int restinio_header_field_complete_cb(llhttp_t *parser)
Definition
parser_callbacks.ipp:72
restinio_body_cb
int restinio_body_cb(llhttp_t *parser, const char *at, size_t length)
Definition
parser_callbacks.ipp:178
restinio_url_cb
int restinio_url_cb(llhttp_t *parser, const char *at, size_t length)
Definition
parser_callbacks.ipp:20
restinio_message_complete_cb
int restinio_message_complete_cb(llhttp_t *parser)
Definition
parser_callbacks.ipp:242
restinio_header_value_cb
int restinio_header_value_cb(llhttp_t *parser, const char *at, size_t length)
Definition
parser_callbacks.ipp:108
restinio_chunk_extension_name_complete_cb
int restinio_chunk_extension_name_complete_cb(llhttp_t *parser)
Definition
parser_callbacks.ipp:304
restinio_chunk_extension_name_cb
int restinio_chunk_extension_name_cb(llhttp_t *parser, const char *at, size_t length)
Definition
parser_callbacks.ipp:268
restinio_chunk_extension_value_cb
int restinio_chunk_extension_value_cb(llhttp_t *parser, const char *at, size_t length)
Definition
parser_callbacks.ipp:323
restinio_chunk_complete_cb
int restinio_chunk_complete_cb(llhttp_t *)
Definition
parser_callbacks.ipp:234
append_last_field_accessor
void append_last_field_accessor(http_header_fields_t &fields, string_view_t value)
Definition
parser_callbacks.ipp:102
restinio_chunk_header_cb
int restinio_chunk_header_cb(llhttp_t *parser)
Definition
parser_callbacks.ipp:203
restinio_header_value_complete_cb
int restinio_header_value_complete_cb(llhttp_t *parser)
Definition
parser_callbacks.ipp:137
restinio_chunk_extension_value_complete_cb
int restinio_chunk_extension_value_complete_cb(llhttp_t *)
Definition
parser_callbacks.ipp:348
restinio_headers_complete_cb
int restinio_headers_complete_cb(llhttp_t *parser)
Definition
parser_callbacks.ipp:145
restinio_header_field_cb
int restinio_header_field_cb(llhttp_t *parser, const char *at, size_t length)
Definition
parser_callbacks.ipp:43
Generated by
1.17.0