Go to the documentation of this file.
32 namespace multipart_body
71 inline std::vector< string_view_t >
78 std::vector< string_view_t > result;
79 std::vector< string_view_t > tmp_result;
85 auto boundary_pos = body.find( boundary );
86 if( string_view_t::npos == boundary_pos )
92 if( boundary_pos != 0u &&
93 (boundary_pos < eol.size() ||
94 body.substr( boundary_pos - eol.size(), eol.size() ) != eol) )
97 auto remaining_body = body.substr( boundary_pos + boundary.size() );
104 remaining_body = remaining_body.substr( eol.size() );
106 boundary_pos = remaining_body.find( boundary );
107 if( string_view_t::npos == boundary_pos )
111 if( boundary_pos < eol.size() ||
112 remaining_body.substr( boundary_pos - eol.size(), eol.size() ) != eol )
115 tmp_result.push_back(
116 remaining_body.substr( 0u, boundary_pos - eol.size() ) );
118 remaining_body = remaining_body.substr( boundary_pos + boundary.size() );
120 if(
starts_with( remaining_body, last_separator ) )
123 swap( tmp_result, result );
158 namespace parser_details
165 constexpr
char CR =
'\r';
166 constexpr
char LF =
'\n';
191 return from.fragment( from.current_position() );
214 std::string accumulator;
215 auto ch = from.
getch();
216 while( !ch.m_eof && ch.m_ch !=
CR && ch.m_ch !=
LF )
218 accumulator += ch.
m_ch;
225 easy_parser::error_reason_t::unexpected_eof
256 using namespace parser_details;
258 return produce< parsed_part_t >(
259 produce< http_header_fields_t >(
261 produce< http_header_field_t >(
263 [](
auto & f, std::string && v) {
269 [](
auto & f, std::string && v) {
325 }.try_process( source );
342 continue_enumeration,
366 content_type_field_not_found,
368 content_type_field_parse_error,
372 content_type_field_inappropriate_value,
375 illegal_boundary_value,
381 terminated_by_handler,
389 namespace boundary_value_checkers
405 return (ch >=
'0' && ch <=
'9')
406 || ((ch >=
'A' && ch <=
'Z') || (ch >=
'a' && ch <=
'z'))
459 using namespace impl::boundary_value_checkers;
461 if( value.size() >= 1u && value.size() <= 70u )
463 const std::size_t last_index = value.size() - 1u;
464 for( std::size_t i = 0u; i != last_index; ++i )
466 return enumeration_error_t::illegal_boundary_value;
469 return enumeration_error_t::illegal_boundary_value;
472 return enumeration_error_t::illegal_boundary_value;
506 restinio::http_field::content_type );
508 return make_unexpected(
509 enumeration_error_t::content_type_field_not_found );
516 return make_unexpected(
517 enumeration_error_t::content_type_field_parse_error );
519 const auto & media_type = parse_result->media_type;
522 return make_unexpected(
523 enumeration_error_t::content_type_field_inappropriate_value );
525 if( expected_media_subtype &&
528 return make_unexpected(
529 enumeration_error_t::content_type_field_inappropriate_value );
534 parse_result->media_type.parameters,
537 return make_unexpected(
538 enumeration_error_t::content_type_field_inappropriate_value );
542 if( boundary_check_result )
543 return make_unexpected( *boundary_check_result );
546 std::string actual_boundary_mark;
547 actual_boundary_mark.reserve( 2 + boundary->size() );
548 actual_boundary_mark.append(
"--" );
549 actual_boundary_mark.append( boundary->data(), boundary->size() );
566 template<
typename Handler >
570 const std::vector< string_view_t > & parts,
573 std::size_t parts_processed{ 0u };
576 for(
auto current_part : parts )
580 if( !part_parse_result )
590 error = enumeration_error_t::terminated_by_handler;
597 return make_unexpected( *error );
599 return parts_processed;
605 template<
typename,
typename = restinio::utils::metaprogramming::
void_t<> >
608 template<
typename T >
615 decltype(std::declval<T>()(std::declval<parsed_part_t>()))
620 > :
public std::true_type
682 template<
typename Handler >
706 impl::valid_handler_type< std::decay_t<Handler> >::value,
707 "Handler should be callable object, "
708 "should accept parsed_part_t by value, const or rvalue reference, "
709 "and should return handling_result_t" );
714 expected_media_subtype );
720 return make_unexpected(
721 enumeration_error_t::no_parts_found );
725 std::forward<Handler>(handler) );
728 return make_unexpected( boundary.error() );
#define RESTINIO_NODISCARD
RESTINIO_NODISCARD position_t current_position() const noexcept
Get the current position in the stream.
RESTINIO_NODISCARD auto symbol(char expected) noexcept
A factory function to create a clause that expects the speficied symbol, extracts it and then skips i...
RESTINIO_NODISCARD auto token_p() noexcept
A factory function to create a token_producer.
constexpr RESTINIO_NODISCARD bool is_bchar(char ch)
RESTINIO_NODISCARD expected_t< string_view_t, not_found_t > find_first(const parameter_with_mandatory_value_container_t &where, string_view_t what)
A helper function to find the first occurence of a parameter with the specified value.
RESTINIO_NODISCARD expected_t< std::size_t, enumeration_error_t > enumerate_parts_of_request_body(const std::vector< string_view_t > &parts, Handler &&handler)
A function that parses every part of a multipart body and calls a user-provided handler for every par...
handling_result_t
The result to be returned from user-provided handler of parts of multipart body.
constexpr std::size_t N
A special marker that means infinite repetitions.
RESTINIO_NODISCARD character_t getch() noexcept
Get the next character from the input stream.
Information about parsing error.
RESTINIO_NODISCARD bool starts_with(const string_view_t &where, const string_view_t &what) noexcept
nonstd::string_view string_view_t
constexpr RESTINIO_NODISCARD bool is_bcharnospace(char ch)
RESTINIO_NODISCARD expected_t< string_view_t, easy_parser::parse_error_t > try_parse(easy_parser::impl::source_t &from) const noexcept
const std::string & body() const noexcept
Get request body.
RESTINIO_NODISCARD expected_t< parsed_part_t, restinio::easy_parser::parse_error_t > try_parse_part(string_view_t part)
Helper function for parsing content of one part of a multipart body.
RESTINIO_NODISCARD auto ows() noexcept
A factory function to create an OWS clause.
@ content_type_field_not_found
Content-Type field is not found. If Content-Type is absent there is no way to detect 'boundary' param...
An very small, simple and somewhat limited implementation of recursive-descent parser.
A description of parsed content of one part of a multipart body.
A special producer that consumes the rest of the current line in the input stream until CR/LF will be...
RESTINIO_NODISCARD expected_t< typename Producer::result_type, parse_error_t > try_parse(string_view_t from, Producer producer)
Perform the parsing of the specified content by using specified value producer.
RESTINIO_NODISCARD expected_t< std::size_t, enumeration_error_t > enumerate_parts(const request_t &req, Handler &&handler, string_view_t expected_media_type=string_view_t{ "multipart" }, optional_t< string_view_t > expected_media_subtype=nullopt)
A helper function for enumeration of parts of a multipart body.
const nullopt_t nullopt((nullopt_t::init()))
nonstd::expected< T, E > expected_t
Utilities for parsing values of http-fields.
const http_request_header_t & header() const noexcept
Get request header.
A special base class to be used with producers.
bool is_equal_caseless(const char *a, const char *b, std::size_t size) noexcept
Comparator for fields names.
string_view_t body
The body of that part.
A special producer that consumes the whole remaining content from the input stream.
RESTINIO_NODISCARD optional_t< enumeration_error_t > check_boundary_value(string_view_t value)
A helper function for checking the validity of 'boundary' value.
@ continue_enumeration
Enumeration of parts should be continued. If there is another part the user-provided handler will be ...
RESTINIO_NODISCARD expected_t< std::string, enumeration_error_t > detect_boundary_for_multipart_body(const request_t &req, string_view_t expected_media_type, optional_t< string_view_t > expected_media_subtype)
Helper function for parsing Content-Type field and extracting the value of 'boundary' parameter.
RESTINIO_NODISCARD expected_t< std::string, easy_parser::parse_error_t > try_parse(easy_parser::impl::source_t &from) const
A special class to be used as the top level clause in parser.
enumeration_error_t
The result of an attempt to enumerate parts of a multipart body.
RESTINIO_NODISCARD auto to_lower() noexcept
A factory function to create a to_lower_transformer.
Helpers for caseless comparison of strings.
Various string-related algorithms.
void swap(optional< T > &x, optional< T > &y)
The class that implements "input stream".
Stuff related to value of Content-Type HTTP-field.
void putback() noexcept
Return one character back to the input stream.
RESTINIO_NODISCARD std::vector< string_view_t > split_multipart_body(string_view_t body, string_view_t boundary)
Helper function for spliting a multipart body into a serie of separate parts.
RESTINIO_NODISCARD auto make_parser()
A factory function for a parser of a part of multipart message.
http_header_fields_t fields
HTTP-fields local for that part.
RESTINIO_NODISCARD auto custom_consumer(F consumer)
A factory function to create a custom_consumer.
RESTINIO_NODISCARD auto repeat(std::size_t min_occurences, std::size_t max_occurences, Clauses &&... clauses)
A factory function to create repetitor of subclauses.