RESTinio
Loading...
Searching...
No Matches
header_helpers.hpp
Go to the documentation of this file.
1/*
2 restinio
3*/
4
5/*!
6 HTTP-Connection handler routine.
7*/
8
9#pragma once
10
11#include <array>
12#include <numeric>
13
14#include <restinio/buffers.hpp>
15
16namespace restinio
17{
18
19namespace impl
20{
21
22//
23// ct_string_len
24//
25
26//! Compile time c-string length.
27template< std::size_t N >
28inline constexpr std::size_t ct_string_len( const char (&)[N] ) noexcept
29{
30 return N-1;
31}
32
38
39//
40// calculate_approx_buffer_size_for_header()
41//
42
43//! Calculate buffer size that is enough for serializing the buffer.
44inline std::size_t
46 const http_response_header_t & h ) noexcept
47{
48 std::size_t result = 13; // "HTTP/1.1 xxx "
49 result += h.reason_phrase().size() + 2; // 2 is for "\r\n".
50 result += 26; // "Connection: keep-alive\r\n" is also enough for "Connection: close\r\n" (21).
51 result += 20 + 18; // "Content-Length: %llu\r\n" assume size is size_t, and 18 is always ok.
52
53 result += 2; // Final "\r\n\r\n".
54
55 h.for_each_field( [&result](const auto & f) noexcept {
56 result += f.name().size() + 2 + f.value().size() + 2;
57 } );
58
59 return result;
60}
61
62//
63// create_header_string()
64//
65
66//! Creates a string for http response header.
67inline std::string
69 const http_response_header_t & h,
70 content_length_field_presence_t content_length_field_presence =
72 std::size_t buffer_size = 0 )
73{
74 std::string result;
75
76 if( 0 != buffer_size )
77 result.reserve( buffer_size );
78 else
79 result.reserve( calculate_approx_buffer_size_for_header( h ) );
80
81 constexpr const char header_part1[] = "HTTP/";
82 result.append( header_part1, ct_string_len( header_part1 ) );
83
84 result += static_cast<char>( '0' + h.http_major() );
85 result += '.';
86 result += static_cast<char>( '0' + h.http_minor() );
87 result += ' ';
88
89 const auto sc = h.status_code().raw_code();
90
91//FIXME: there should be a check for status_code in range 100..999.
92//May be a special type like bounded_value_t<100,999> must be used in
93//http_response_header_t.
94 result += '0' + ( sc / 100 ) % 10;
95 result += '0' + ( sc / 10 ) % 10;
96 result += '0' + ( sc ) % 10;
97
98 result += ' ';
99 result += h.reason_phrase();
100
101 constexpr const char header_rn[] = "\r\n";
102 result.append( header_rn, ct_string_len( header_rn ) );
103
104 switch( h.connection() )
105 {
106 case http_connection_header_t::keep_alive:
107 {
108 constexpr const char header_part2_1[] = "Connection: keep-alive\r\n";
109 result.append( header_part2_1, ct_string_len( header_part2_1 ) );
110 break;
111 }
112
113 case http_connection_header_t::close:
114 {
115 constexpr const char header_part2_2[] = "Connection: close\r\n";
116 result.append( header_part2_2, ct_string_len( header_part2_2 ) );
117 break;
118 }
119
120 case http_connection_header_t::upgrade:
121 {
122 constexpr const char header_part2_3[] = "Connection: Upgrade\r\n";
123 result.append( header_part2_3, ct_string_len( header_part2_3 ) );
124 break;
125 }
126 }
127
129 content_length_field_presence )
130 {
131 std::array< char, 64 > buf;
132 const auto n =
133 std::snprintf(
134 buf.data(),
135 buf.size(),
136 "Content-Length: %llu\r\n",
137 static_cast< unsigned long long >( h.content_length() ) );
138
139 result.append( buf.data(), static_cast<std::string::size_type>(n) );
140 }
141
142 constexpr const char header_field_sep[] = ": ";
143 h.for_each_field( [&result, header_field_sep, header_rn](const auto & f) {
144 result += f.name();
145 result.append( header_field_sep, ct_string_len( header_field_sep ) );
146 result += f.value();
147 result.append( header_rn, ct_string_len( header_rn ) );
148 } );
149
150 result.append( header_rn, ct_string_len( header_rn ) );
151
152 return result;
153}
154
155inline auto
157{
158 constexpr const char raw_501_response[] =
159 "HTTP/1.1 501 Not Implemented\r\n"
160 "Connection: close\r\n"
161 "Content-Length: 0\r\n"
162 "\r\n";
163
164 writable_items_container_t result;
165 result.emplace_back( raw_501_response );
166 return result;
167}
168
169inline auto
171{
172 constexpr const char raw_504_response[] =
173 "HTTP/1.1 504 Gateway Time-out\r\n"
174 "Connection: close\r\n"
175 "Content-Length: 0\r\n"
176 "\r\n";
177
178 writable_items_container_t result;
179 result.emplace_back( raw_504_response );
180 return result;
181}
182
183} /* namespace impl */
184
185} /* namespace restinio */
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.
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.
auto create_not_implemented_resp()
constexpr std::size_t ct_string_len(const char(&)[N]) noexcept
Compile time c-string length.