forked from boostorg/beast
fix #397 method enum class is added to represent all known request methods. Functions are provided to convert from strings to and from the method enumeration. The fields container is modified to also work with the enum.
336 lines
8.1 KiB
C++
336 lines
8.1 KiB
C++
//
|
|
// Copyright (c) 2013-2017 Vinnie Falco (vinnie dot falco at gmail dot com)
|
|
//
|
|
// 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)
|
|
//
|
|
|
|
#ifndef BEAST_HTTP_FIELDS_HPP
|
|
#define BEAST_HTTP_FIELDS_HPP
|
|
|
|
#include <beast/config.hpp>
|
|
#include <beast/core/string_view.hpp>
|
|
#include <beast/core/detail/empty_base_optimization.hpp>
|
|
#include <beast/http/verb.hpp>
|
|
#include <beast/http/detail/fields.hpp>
|
|
#include <boost/lexical_cast.hpp>
|
|
#include <boost/optional.hpp>
|
|
#include <algorithm>
|
|
#include <cctype>
|
|
#include <memory>
|
|
#include <string>
|
|
#include <type_traits>
|
|
#include <utility>
|
|
|
|
namespace beast {
|
|
namespace http {
|
|
|
|
/** A container for storing HTTP header fields.
|
|
|
|
This container is designed to store the field value pairs that make
|
|
up the fields and trailers in an HTTP message. Objects of this type
|
|
are iterable, with each element holding the field name and field
|
|
value.
|
|
|
|
Field names are stored as-is, but comparisons are case-insensitive.
|
|
When the container is iterated, the fields are presented in the order
|
|
of insertion. For fields with the same name, the container behaves
|
|
as a `std::multiset`; there will be a separate value for each occurrence
|
|
of the field name.
|
|
|
|
@note Meets the requirements of @b FieldSequence.
|
|
*/
|
|
template<class Allocator>
|
|
class basic_fields :
|
|
#if ! BEAST_DOXYGEN
|
|
private beast::detail::empty_base_optimization<
|
|
typename std::allocator_traits<Allocator>::
|
|
template rebind_alloc<
|
|
detail::basic_fields_base::element>>,
|
|
#endif
|
|
public detail::basic_fields_base
|
|
{
|
|
using alloc_type = typename
|
|
std::allocator_traits<Allocator>::
|
|
template rebind_alloc<
|
|
detail::basic_fields_base::element>;
|
|
|
|
using alloc_traits =
|
|
std::allocator_traits<alloc_type>;
|
|
|
|
using size_type =
|
|
typename std::allocator_traits<Allocator>::size_type;
|
|
|
|
boost::optional<verb> verb_;
|
|
|
|
void
|
|
delete_all();
|
|
|
|
void
|
|
move_assign(basic_fields&, std::false_type);
|
|
|
|
void
|
|
move_assign(basic_fields&, std::true_type);
|
|
|
|
void
|
|
copy_assign(basic_fields const&, std::false_type);
|
|
|
|
void
|
|
copy_assign(basic_fields const&, std::true_type);
|
|
|
|
template<class FieldSequence>
|
|
void
|
|
copy_from(FieldSequence const& fs)
|
|
{
|
|
for(auto const& e : fs)
|
|
insert(e.first, e.second);
|
|
}
|
|
|
|
public:
|
|
/// The type of allocator used.
|
|
using allocator_type = Allocator;
|
|
|
|
/** The value type of the field sequence.
|
|
|
|
Meets the requirements of @b Field.
|
|
*/
|
|
#if BEAST_DOXYGEN
|
|
using value_type = implementation_defined;
|
|
#endif
|
|
|
|
/// A const iterator to the field sequence
|
|
#if BEAST_DOXYGEN
|
|
using iterator = implementation_defined;
|
|
#endif
|
|
|
|
/// A const iterator to the field sequence
|
|
#if BEAST_DOXYGEN
|
|
using const_iterator = implementation_defined;
|
|
#endif
|
|
|
|
/// Default constructor.
|
|
basic_fields() = default;
|
|
|
|
/// Destructor
|
|
~basic_fields();
|
|
|
|
/** Construct the fields.
|
|
|
|
@param alloc The allocator to use.
|
|
*/
|
|
explicit
|
|
basic_fields(Allocator const& alloc);
|
|
|
|
/** Move constructor.
|
|
|
|
The moved-from object becomes an empty field sequence.
|
|
|
|
@param other The object to move from.
|
|
*/
|
|
basic_fields(basic_fields&& other);
|
|
|
|
/** Move assignment.
|
|
|
|
The moved-from object becomes an empty field sequence.
|
|
|
|
@param other The object to move from.
|
|
*/
|
|
basic_fields& operator=(basic_fields&& other);
|
|
|
|
/// Copy constructor.
|
|
basic_fields(basic_fields const&);
|
|
|
|
/// Copy assignment.
|
|
basic_fields& operator=(basic_fields const&);
|
|
|
|
/// Copy constructor.
|
|
template<class OtherAlloc>
|
|
basic_fields(basic_fields<OtherAlloc> const&);
|
|
|
|
/// Copy assignment.
|
|
template<class OtherAlloc>
|
|
basic_fields& operator=(basic_fields<OtherAlloc> const&);
|
|
|
|
/// Returns a const iterator to the beginning of the field sequence.
|
|
const_iterator
|
|
begin() const
|
|
{
|
|
return list_.cbegin();
|
|
}
|
|
|
|
/// Returns a const iterator to the end of the field sequence.
|
|
const_iterator
|
|
end() const
|
|
{
|
|
return list_.cend();
|
|
}
|
|
|
|
/// Returns a const iterator to the beginning of the field sequence.
|
|
const_iterator
|
|
cbegin() const
|
|
{
|
|
return list_.cbegin();
|
|
}
|
|
|
|
/// Returns a const iterator to the end of the field sequence.
|
|
const_iterator
|
|
cend() const
|
|
{
|
|
return list_.cend();
|
|
}
|
|
|
|
/// Returns `true` if the specified field exists.
|
|
bool
|
|
exists(string_view const& name) const
|
|
{
|
|
return set_.find(name, less{}) != set_.end();
|
|
}
|
|
|
|
/// Returns the number of values for the specified field.
|
|
std::size_t
|
|
count(string_view const& name) const;
|
|
|
|
/** Returns an iterator to the case-insensitive matching field name.
|
|
|
|
If more than one field with the specified name exists, the
|
|
first field defined by insertion order is returned.
|
|
*/
|
|
iterator
|
|
find(string_view const& name) const;
|
|
|
|
/** Returns the value for a case-insensitive matching header, or `""`.
|
|
|
|
If more than one field with the specified name exists, the
|
|
first field defined by insertion order is returned.
|
|
*/
|
|
string_view const
|
|
operator[](string_view const& name) const;
|
|
|
|
/// Clear the contents of the basic_fields.
|
|
void
|
|
clear() noexcept;
|
|
|
|
/** Remove a field.
|
|
|
|
If more than one field with the specified name exists, all
|
|
matching fields will be removed.
|
|
|
|
@param name The name of the field(s) to remove.
|
|
|
|
@return The number of fields removed.
|
|
*/
|
|
std::size_t
|
|
erase(string_view const& name);
|
|
|
|
/** Insert a field value.
|
|
|
|
If a field with the same name already exists, the
|
|
existing field is untouched and a new field value pair
|
|
is inserted into the container.
|
|
|
|
@param name The name of the field.
|
|
|
|
@param value A string holding the value of the field.
|
|
*/
|
|
void
|
|
insert(string_view const& name, string_view value);
|
|
|
|
/** Insert a field value.
|
|
|
|
If a field with the same name already exists, the
|
|
existing field is untouched and a new field value pair
|
|
is inserted into the container.
|
|
|
|
@param name The name of the field
|
|
|
|
@param value The value of the field. The object will be
|
|
converted to a string using `boost::lexical_cast`.
|
|
*/
|
|
template<class T>
|
|
typename std::enable_if<
|
|
! std::is_constructible<string_view, T>::value>::type
|
|
insert(string_view name, T const& value)
|
|
{
|
|
insert(name, boost::lexical_cast<std::string>(value));
|
|
}
|
|
|
|
/** Replace a field value.
|
|
|
|
First removes any values with matching field names, then
|
|
inserts the new field value.
|
|
|
|
@param name The name of the field.
|
|
|
|
@param value A string holding the value of the field.
|
|
*/
|
|
void
|
|
replace(string_view const& name, string_view value);
|
|
|
|
/** Replace a field value.
|
|
|
|
First removes any values with matching field names, then
|
|
inserts the new field value.
|
|
|
|
@param name The name of the field
|
|
|
|
@param value The value of the field. The object will be
|
|
converted to a string using `boost::lexical_cast`.
|
|
*/
|
|
template<class T>
|
|
typename std::enable_if<
|
|
! std::is_constructible<string_view, T>::value>::type
|
|
replace(string_view const& name, T const& value)
|
|
{
|
|
replace(name,
|
|
boost::lexical_cast<std::string>(value));
|
|
}
|
|
|
|
#if BEAST_DOXYGEN
|
|
private:
|
|
#endif
|
|
|
|
string_view
|
|
method() const;
|
|
|
|
void
|
|
method(verb v);
|
|
|
|
void
|
|
method(string_view const& s);
|
|
|
|
string_view
|
|
target() const
|
|
{
|
|
return (*this)[":target"];
|
|
}
|
|
|
|
void
|
|
target(string_view const& s)
|
|
{
|
|
return this->replace(":target", s);
|
|
}
|
|
|
|
string_view
|
|
reason() const
|
|
{
|
|
return (*this)[":reason"];
|
|
}
|
|
|
|
void
|
|
reason(string_view const& s)
|
|
{
|
|
return this->replace(":reason", s);
|
|
}
|
|
};
|
|
|
|
/// A typical HTTP header fields container
|
|
using fields =
|
|
basic_fields<std::allocator<char>>;
|
|
|
|
} // http
|
|
} // beast
|
|
|
|
#include <beast/http/impl/fields.ipp>
|
|
|
|
#endif
|