header_helpers.hpp
Go to the documentation of this file.
/*
restinio
*/
#pragma once
#include <array>
#include <numeric>
#include <restinio/buffers.hpp>
namespace restinio
{
namespace impl
{
//
// ct_string_len
//
template< std::size_t N >
inline constexpr std::size_t ct_string_len( const char (&)[N] ) noexcept
{
return N-1;
}
enum class content_length_field_presence_t : std::uint8_t
{
add_content_length,
skip_content_length
};
//
// calculate_approx_buffer_size_for_header()
//
inline std::size_t
calculate_approx_buffer_size_for_header(
const http_response_header_t & h ) noexcept
{
std::size_t result = 13; // "HTTP/1.1 xxx "
result += h.reason_phrase().size() + 2; // 2 is for "\r\n".
result += 26; // "Connection: keep-alive\r\n" is also enough for "Connection: close\r\n" (21).
result += 20 + 18; // "Content-Length: %llu\r\n" assume size is size_t, and 18 is always ok.
result += 2; // Final "\r\n\r\n".
h.for_each_field( [&result](const auto & f) noexcept {
result += f.name().size() + 2 + f.value().size() + 2;
} );
return result;
}
//
// create_header_string()
//
inline std::string
create_header_string(
const http_response_header_t & h,
content_length_field_presence_t content_length_field_presence =
content_length_field_presence_t::add_content_length,
std::size_t buffer_size = 0 )
{
std::string result;
if( 0 != buffer_size )
result.reserve( buffer_size );
else
result.reserve( calculate_approx_buffer_size_for_header( h ) );
constexpr const char header_part1[] = "HTTP/";
result.append( header_part1, ct_string_len( header_part1 ) );
result += static_cast<char>( '0' + h.http_major() );
result += '.';
result += static_cast<char>( '0' + h.http_minor() );
result += ' ';
const auto sc = h.status_code().raw_code();
//FIXME: there should be a check for status_code in range 100..999.
//May be a special type like bounded_value_t<100,999> must be used in
//http_response_header_t.
result += '0' + ( sc / 100 ) % 10;
result += '0' + ( sc / 10 ) % 10;
result += '0' + ( sc ) % 10;
result += ' ';
result += h.reason_phrase();
constexpr const char header_rn[] = "\r\n";
result.append( header_rn, ct_string_len( header_rn ) );
switch( h.connection() )
{
case http_connection_header_t::keep_alive:
{
constexpr const char header_part2_1[] = "Connection: keep-alive\r\n";
result.append( header_part2_1, ct_string_len( header_part2_1 ) );
break;
}
case http_connection_header_t::close:
{
constexpr const char header_part2_2[] = "Connection: close\r\n";
result.append( header_part2_2, ct_string_len( header_part2_2 ) );
break;
}
case http_connection_header_t::upgrade:
{
constexpr const char header_part2_3[] = "Connection: Upgrade\r\n";
result.append( header_part2_3, ct_string_len( header_part2_3 ) );
break;
}
}
if( content_length_field_presence_t::add_content_length ==
content_length_field_presence )
{
std::array< char, 64 > buf;
const auto n =
std::snprintf(
buf.data(),
buf.size(),
"Content-Length: %llu\r\n",
static_cast< unsigned long long >( h.content_length() ) );
result.append( buf.data(), static_cast<std::string::size_type>(n) );
}
constexpr const char header_field_sep[] = ": ";
h.for_each_field( [&result, header_field_sep, header_rn](const auto & f) {
result += f.name();
result.append( header_field_sep, ct_string_len( header_field_sep ) );
result += f.value();
result.append( header_rn, ct_string_len( header_rn ) );
} );
result.append( header_rn, ct_string_len( header_rn ) );
return result;
}
inline auto
create_not_implemented_resp()
{
constexpr const char raw_501_response[] =
"HTTP/1.1 501 Not Implemented\r\n"
"Connection: close\r\n"
"Content-Length: 0\r\n"
"\r\n";
writable_items_container_t result;
result.emplace_back( raw_501_response );
return result;
}
inline auto
create_timeout_resp()
{
constexpr const char raw_504_response[] =
"HTTP/1.1 504 Gateway Time-out\r\n"
"Connection: close\r\n"
"Content-Length: 0\r\n"
"\r\n";
writable_items_container_t result;
result.emplace_back( raw_504_response );
return result;
}
} /* namespace impl */
} /* namespace restinio */
buffers.hpp
restinio::http_header_fields_t::for_each_field
void for_each_field(Lambda &&lambda) const noexcept(noexcept(lambda(std::declval< const http_header_field_t & >())))
Enumeration of fields.
Definition: http_headers.hpp:1361
restinio::http_status_code_t::raw_code
constexpr auto raw_code() const noexcept
Definition: http_headers.hpp:2003
restinio::easy_parser::N
constexpr std::size_t N
A special marker that means infinite repetitions.
Definition: easy_parser.hpp:455
restinio::impl::calculate_approx_buffer_size_for_header
std::size_t calculate_approx_buffer_size_for_header(const http_response_header_t &h) noexcept
Calculate buffer size that is enough for serializing the buffer.
Definition: header_helpers.hpp:45
restinio::impl::create_header_string
std::string create_header_string(const http_response_header_t &h, content_length_field_presence_t content_length_field_presence=content_length_field_presence_t::add_content_length, std::size_t buffer_size=0)
Creates a string for http response header.
Definition: header_helpers.hpp:68
restinio::impl::create_timeout_resp
auto create_timeout_resp()
Definition: header_helpers.hpp:170
restinio::impl::create_not_implemented_resp
auto create_not_implemented_resp()
Definition: header_helpers.hpp:156
restinio::impl::content_length_field_presence_t
content_length_field_presence_t
Definition: header_helpers.hpp:34
restinio::impl::content_length_field_presence_t::skip_content_length
@ skip_content_length
restinio::impl::content_length_field_presence_t::add_content_length
@ add_content_length
restinio::impl::ct_string_len
constexpr std::size_t ct_string_len(const char(&)[N]) noexcept
Compile time c-string length.
Definition: header_helpers.hpp:28
restinio
Definition: asio_include.hpp:21
restinio::writable_items_container_t
std::vector< writable_item_t > writable_items_container_t
Definition: buffers.hpp:668
restinio::http_connection_header_t::close
@ close
restinio::http_connection_header_t::upgrade
@ upgrade
restinio::http_connection_header_t::keep_alive
@ keep_alive
restinio::http_header_common_t::http_major
std::uint16_t http_major() const noexcept
Http version.
Definition: http_headers.hpp:1585
restinio::http_header_common_t::connection
http_connection_header_t connection() const
Get the value of 'connection' header field.
Definition: http_headers.hpp:1626
restinio::http_header_common_t::content_length
std::uint64_t content_length() const noexcept
Length of body of an http-message.
Definition: http_headers.hpp:1603
restinio::http_header_common_t::http_minor
std::uint16_t http_minor() const noexcept
Definition: http_headers.hpp:1593
restinio::http_response_header_t
Resp header.
Definition: http_headers.hpp:2338
restinio::http_response_header_t::status_code
http_status_code_t status_code() const noexcept
Definition: http_headers.hpp:2348
restinio::http_response_header_t::reason_phrase
const std::string & reason_phrase() const noexcept
Definition: http_headers.hpp:2356