Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
90 changes: 90 additions & 0 deletions include/boost/http_proto/multipart_form_sink.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
//
// Copyright (c) 2025 Mohammad Nejati
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
// Official repository: https://github.com/cppalliance/http_proto
//

#ifndef BOOST_HTTP_PROTO_MULTIPART_FORM_SINK_HPP
#define BOOST_HTTP_PROTO_MULTIPART_FORM_SINK_HPP

#include <boost/capy/file.hpp>
#include <boost/http_proto/sink.hpp>

#include <boost/optional.hpp>
#include <boost/variant2.hpp>

#include <vector>

namespace boost {
namespace http_proto {

class BOOST_HTTP_PROTO_SYMBOL_VISIBLE multipart_form_sink
: public http_proto::sink
{
public:
struct file_field
{
std::string name;
std::string path;
};

struct text_field
{
std::string data;
};

struct part
{
std::string name;
variant2::variant<text_field, file_field> content;
boost::optional<std::string> content_type;
};

BOOST_HTTP_PROTO_DECL
explicit
multipart_form_sink(
core::string_view boundary);

BOOST_HTTP_PROTO_DECL
boost::span<part const>
parts() const noexcept;

private:
BOOST_HTTP_PROTO_DECL
results
on_write(
buffers::const_buffer b,
bool more) override;

void
parse(
bool match,
core::string_view b,
system::error_code& ec);

enum class state
{
preamble,
post_boundary0,
post_boundary1,
post_boundary2,
header,
content,
finished
};

state state_ = state::preamble;
std::string needle_;
std::string leftover_;
std::string header_;
capy::file file_;
std::vector<part> parts_;
};

} // http_proto
} // boost

#endif
74 changes: 74 additions & 0 deletions include/boost/http_proto/rfc/content_disposition_rule.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
//
// Copyright (c) 2025 Mohammad Nejati
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
// Official repository: https://github.com/cppalliance/http_proto
//

#ifndef BOOST_HTTP_PROTO_RFC_CONTENT_DISPOSITION_RULE_HPP
#define BOOST_HTTP_PROTO_RFC_CONTENT_DISPOSITION_RULE_HPP

#include <boost/http_proto/detail/config.hpp>
#include <boost/http_proto/rfc/parameter.hpp>
#include <boost/url/grammar/range_rule.hpp>

namespace boost {
namespace http_proto {

namespace implementation_defined {
struct content_disposition_rule_t
{
struct value_type
{
core::string_view type;
grammar::range<parameter> params;
};

BOOST_HTTP_PROTO_DECL
system::result<value_type>
parse(
char const*& it,
char const* end) const noexcept;
};
} // implementation_defined

/** Rule matching content-disposition

@par Value Type
@code
struct value_type
{
core::string_view type;
grammar::range< parameter > params;
};
@endcode

@par Example
@code
@endcode

@par BNF
@code
content-disposition = disposition-type *( OWS ";" OWS disposition-parm )

disposition-type = token
disposition-parm = token "=" ( token / quoted-string )
@endcode

@par Specification
@li <a href="https://www.rfc-editor.org/rfc/rfc6266#section-4.1"
>4.1. Grammar (rfc6266)</a>
@li <a href="https://www.rfc-editor.org/rfc/rfc7230#section-3.2.6"
>3.2.6. Field Value Components (rfc7230)</a>

@see
@ref quoted_token_view.
*/
BOOST_INLINE_CONSTEXPR implementation_defined::content_disposition_rule_t content_disposition_rule{};

} // http_proto
} // boost

#endif
42 changes: 42 additions & 0 deletions include/boost/http_proto/rfc/parameter.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
#include <boost/http_proto/detail/config.hpp>
#include <boost/http_proto/rfc/quoted_token_view.hpp>
#include <boost/system/result.hpp>
#include <boost/url/grammar/range_rule.hpp>

namespace boost {
namespace http_proto {
Expand Down Expand Up @@ -48,6 +49,18 @@ struct parameter_rule_t
char const*) const noexcept ->
system::result<value_type>;
};

struct parameters_rule_t
{
using value_type = grammar::range<parameter>;

BOOST_HTTP_PROTO_DECL
auto
parse(
char const*&,
char const*) const noexcept ->
system::result<value_type>;
};
} // implementation_defined

/** Rule matching parameter
Expand Down Expand Up @@ -75,6 +88,35 @@ struct parameter_rule_t
*/
BOOST_INLINE_CONSTEXPR implementation_defined::parameter_rule_t parameter_rule{};

//------------------------------------------------

/** Rule matching parameters

@par Value Type
@code
using value_type = grammar::range< parameter >;
@endcode

@par Example
@code
@endcode

@par BNF
@code
parameters = *( OWS ";" OWS parameter )
parameter = token "=" ( token / quoted-string )
@endcode

@par Specification
@li <a href="https://www.rfc-editor.org/rfc/rfc7231#section-3.1.1.1"
>3.1.1.1. Media Type (rfc7231)</a>

@see
@ref parameter,
@ref parameter_rule.
*/
BOOST_INLINE_CONSTEXPR implementation_defined::parameters_rule_t parameters_rule{};

} // http_proto
} // boost

Expand Down
4 changes: 0 additions & 4 deletions include/boost/http_proto/rfc/quoted_token_view.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -50,10 +50,6 @@ class quoted_token_view final
: string_view_base(s)
, n_(n)
{
BOOST_ASSERT(s.size() >= 2);
BOOST_ASSERT(s.front() == '\"');
BOOST_ASSERT(s.back() == '\"');
BOOST_ASSERT(n_ <= s_.size() - 2);
}

public:
Expand Down
Loading
Loading