37 std::array< char, 64 > buf;
42 "%a, %d %b %Y %H:%M:%S GMT",
45 return std::string{ buf.data() };
58template <
typename Response_Builder >
74 bool should_keep_alive )
84 http_response_header_t &
100 std::string field_name,
101 std::string field_value ) &
112 std::string field_name,
113 std::string field_value ) &&
140 std::string field_value ) &
152 std::string field_value ) &&
163 std::chrono::system_clock::time_point tp =
164 std::chrono::system_clock::now() ) &
173 std::chrono::system_clock::time_point tp =
174 std::chrono::system_clock::now() ) &&
225 throw exception_t{
"done() cannot be called twice" };
232 return static_cast< Response_Builder &
>( *this );
241template <
typename Response_Output_Strategy >
270 using base_type_t::base_type_t;
276 auto size = body.size();
277 return set_body_impl( body, size );
291 auto size = body_part.size();
292 return append_body_impl( body_part, size );
309 response_output_flags{
313 m_header.content_length( m_body_size );
315 if_neccessary_reserve_first_element_for_header();
317 m_response_parts[ 0 ] =
320 write_group_t wg{
std::move( m_response_parts ) };
321 wg.status_line_size( calculate_status_line_size() );
325 wg.after_write_notificator(
std::move( wscb ) );
330 conn->write_response_parts(
332 response_output_flags,
337 throw_done_must_be_called_once();
347 if_neccessary_reserve_first_element_for_header();
351 m_response_parts.resize( 1 );
355 m_response_parts.emplace_back(
std::move( body ) );
358 m_body_size = body_size;
366 if_neccessary_reserve_first_element_for_header();
368 if( 0 < append_size )
370 m_response_parts.emplace_back(
std::move( body_part ) );
371 m_body_size += append_size;
380 if( m_response_parts.empty() )
382 m_response_parts.reserve( 2 );
383 m_response_parts.emplace_back();
387 std::size_t m_body_size{ 0 };
414 using base_type_t::base_type_t;
420 m_header.content_length( content_length );
428 return std::move( this->set_content_length( content_length ) );
435 auto size = body.size();
436 return set_body_impl( body, size );
450 auto size = body_part.size();
455 return append_body_impl( body_part );
507 throw_done_must_be_called_once();
520 std::size_t status_line_size{ 0 };
522 if( !m_header_was_sent )
524 m_should_keep_alive_when_header_was_sent =
525 m_header.should_keep_alive();
527 if_neccessary_reserve_first_element_for_header();
529 m_response_parts[ 0 ] =
532 m_header_was_sent =
true;
533 status_line_size = calculate_status_line_size();
536 if( !m_response_parts.empty() ||
541 response_output_flags{
546 wg.status_line_size( status_line_size );
550 wg.after_write_notificator(
std::move( wscb ) );
553 conn->write_response_parts(
555 response_output_flags,
563 if_neccessary_reserve_first_element_for_header();
567 if( !m_header_was_sent )
568 m_response_parts.resize( 1 );
570 m_response_parts.resize( 0 );
575 m_response_parts.emplace_back(
std::move( body ) );
584 if_neccessary_reserve_first_element_for_header();
586 m_response_parts.emplace_back(
std::move( body_part ) );
593 if( !m_header_was_sent && m_response_parts.empty() )
595 m_response_parts.reserve( 2 );
596 m_response_parts.emplace_back();
602 bool m_header_was_sent{
false };
611 bool m_should_keep_alive_when_header_was_sent{
true };
643 bool should_keep_alive )
650 m_chunks.reserve( 4 );
659 auto size = chunk.size();
662 m_chunks.emplace_back(
std::move( chunk ) );
716 throw_done_must_be_called_once();
729 std::size_t status_line_size{ 0 };
730 if( !m_header_was_sent )
732 status_line_size = calculate_status_line_size();
733 prepare_header_for_sending();
737 m_header_was_sent =
true;
740 response_output_flags{
745 if( !bufs.empty() || wscb )
748 wg.status_line_size( status_line_size );
752 wg.after_write_notificator(
std::move( wscb ) );
755 conn->write_response_parts(
757 response_output_flags,
765 m_should_keep_alive_when_header_was_sent =
766 m_header.should_keep_alive();
768 constexpr const char value[] =
"chunked";
769 if( !m_header.has_field( restinio::http_field::transfer_encoding ) )
772 restinio::http_field::transfer_encoding,
777 auto & current_value =
778 m_header.get_field( restinio::http_field::transfer_encoding );
779 if( std::string::npos == current_value.find( value ) )
781 constexpr const char comma_value[] =
",chunked";
782 m_header.append_field(
783 restinio::http_field::transfer_encoding,
796 std::size_t reserve_size = 2 * m_chunks.size() + 1;
798 if( !m_header_was_sent )
807 bufs.reserve( reserve_size );
809 if( !m_header_was_sent )
830 auto chunk_it = m_chunks.begin();
831 const auto chunk_end = m_chunks.end();
832 if( chunk_it != chunk_end )
837 asio_ns::buffer_size( chunk_it->buf() ) ) );
838 bufs.emplace_back(
std::move( *chunk_it ) );
840 for( ++chunk_it; chunk_it != chunk_end; ++chunk_it )
845 asio_ns::buffer_size( chunk_it->buf() ) ) );
846 bufs.emplace_back(
std::move( *chunk_it ) );
850 const char *
const ending_representation =
"\r\n" "0\r\n\r\n";
851 const char * appendix_begin = ending_representation + 2;
852 const char * appendix_end = appendix_begin;
854 if( !m_chunks.empty() )
867 if( appendix_begin != appendix_end )
871 static_cast<std::size_t
>(appendix_end - appendix_begin)
881 bool m_header_was_sent{
false };
890 bool m_should_keep_alive_when_header_was_sent{
true };
Response_Builder & upcast_reference() noexcept
Response_Builder && append_header(http_field_t field_id, std::string field_value) &&
Add header field.
Response_Builder && append_header(http_header_field_t http_header_field) &&
Add header field.
impl::connection_handle_t m_connection
Response_Builder && append_header(std::string field_name, std::string field_value) &&
Add header field.
Response_Builder & append_header(std::string field_name, std::string field_value) &
Add header field.
Response_Builder & connection_close() &noexcept
Set connection close.
std::size_t calculate_status_line_size() const noexcept
base_response_builder_t(base_response_builder_t &&) noexcept=default
Response_Builder & append_header(http_header_field_t http_header_field) &
Add header field.
Response_Builder & append_header(http_field_t field_id, std::string field_value) &
Add header field.
Response_Builder & connection_keep_alive() &noexcept
Set connection keep-alive.
const http_response_header_t & header() const noexcept
Response_Builder & append_header_date_field(std::chrono::system_clock::time_point tp=std::chrono::system_clock::now()) &
Add header Date field.
const request_id_t m_request_id
Response_Builder && append_header_date_field(std::chrono::system_clock::time_point tp=std::chrono::system_clock::now()) &&
Add header Date field.
base_response_builder_t & operator=(const base_response_builder_t &)=delete
base_response_builder_t(const base_response_builder_t &)=delete
http_response_header_t & header() noexcept
Accessors for header.
Response_Builder && connection_close() &&noexcept
Set connection close.
Response_Builder && connection_keep_alive() &&noexcept
http_response_header_t m_header
void throw_done_must_be_called_once() const
Exception class for all exceptions thrown by RESTinio.
HTTP response header status line.
const std::string & reason_phrase() const noexcept
Chunked transfer encoding output builder.
self_type_t & flush(write_status_cb_t wscb=write_status_cb_t{}) &
Flush ready outgoing data.
self_type_t && flush(write_status_cb_t wscb=write_status_cb_t{}) &&
Flush ready outgoing data.
writable_items_container_t m_chunks
Chunks accumulator.
writable_items_container_t create_bufs(bool add_zero_chunk)
void send_ready_data(const impl::connection_handle_t &conn, response_parts_attr_t response_parts_attr, write_status_cb_t wscb)
response_builder_t(response_builder_t &&)=default
void prepare_header_for_sending()
self_type_t && append_chunk(writable_item_t chunk) &&
Append current chunk.
self_type_t & append_chunk(writable_item_t chunk) &
Append current chunk.
request_handling_status_t done(write_status_cb_t wscb=write_status_cb_t{})
Complete response.
response_builder_t(http_status_line_t status_line, impl::connection_handle_t connection, request_id_t request_id, bool should_keep_alive)
Simple standard response builder.
self_type_t & append_body_impl(writable_item_t &body_part, std::size_t append_size)
writable_items_container_t m_response_parts
self_type_t && append_body(writable_item_t body_part) &&
Append body.
self_type_t & append_body(writable_item_t body_part) &
Append body.
void if_neccessary_reserve_first_element_for_header()
response_builder_t(response_builder_t &&)=default
request_handling_status_t done(write_status_cb_t wscb=write_status_cb_t{})
Complete response.
self_type_t && set_body(writable_item_t body) &&
Set body.
self_type_t & set_body_impl(writable_item_t &body, std::size_t body_size)
self_type_t & set_body(writable_item_t body) &
Set body.
User controlled response output builder.
self_type_t & flush(write_status_cb_t wscb=write_status_cb_t{}) &
Flush ready outgoing data.
writable_items_container_t m_response_parts
Body accumulator.
self_type_t & append_body_impl(writable_item_t &body_part)
self_type_t & set_body(writable_item_t body) &
Set body (part).
response_builder_t(response_builder_t &&)=default
void send_ready_data(const impl::connection_handle_t &conn, response_parts_attr_t response_parts_attr, write_status_cb_t wscb)
self_type_t & set_content_length(std::size_t content_length) &
Manualy set content length.
self_type_t && set_content_length(std::size_t content_length) &&
Manualy set content length.
self_type_t && set_body(writable_item_t body) &&
Set body (part).
self_type_t && flush(write_status_cb_t wscb=write_status_cb_t{}) &&
Flush ready outgoing data.
request_handling_status_t done(write_status_cb_t wscb=write_status_cb_t{})
Complete response.
self_type_t & set_body_impl(writable_item_t &body, std::size_t body_size)
void if_neccessary_reserve_first_element_for_header()
self_type_t && append_body(writable_item_t body_part) &&
Append body.
self_type_t & append_body(writable_item_t body_part) &
Append body.
Forbid arbitrary response_builder_t instantiations.
response_builder_t()=delete
Class for storing the buffers used for streaming body (request/response).
Group of writable items transported to the context of underlying connection as one solid piece.
A special wrapper around fmtlib include files.
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.
std::shared_ptr< connection_base_t > connection_handle_t
Alias for http connection handle.
constexpr std::size_t ct_string_len(const char(&)[N]) noexcept
Compile time c-string length.
std::vector< writable_item_t > writable_items_container_t
unsigned int request_id_t
Request id in scope of single connection.
response_connection_attr_t response_connection_attr(bool should_keep_alive)
request_handling_status_t
Request handling status.
http_field_t
C++ enum that repeats nodejs c-style enum.
std::function< void(const asio_ns::error_code &ec) > write_status_cb_t
An alias for a callback to be invoked after the write operation of a particular group of "buffers".
std::string make_date_field_value(std::time_t t)
Format a timepoint to a string of a propper format.
constexpr const_buffer_t const_buffer(const void *str, std::size_t size) noexcept
RESTINIO_NODISCARD constexpr request_handling_status_t request_accepted() noexcept
response_parts_attr_t
Attribute for parts.
@ final_parts
Final parts (response ands with these parts).
@ not_final_parts
Intermediate parts (more parts of response to follow).
std::tm make_gmtime(std::time_t t)
Tag type for chunked output response builder.
Response output flags for buffers commited to response-coordinator.
Tag type for RESTinio controlled output response builder.
Tag type for user controlled output response builder.