13 #include <restinio/impl/include_fmtlib.hpp> 15 #include <restinio/impl/string_caseless_compare.hpp> 17 #include <restinio/exception.hpp> 18 #include <restinio/string_view.hpp> 19 #include <restinio/message_builders.hpp> 20 #include <restinio/request_handler.hpp> 138 if( level_value < -1 || level_value > 9 )
142 RESTINIO_FMT_FORMAT_STRING(
143 "invalid compression level: {}, must be " 144 "an integer value in the range of -1 to 9" ),
157 return std::move(
this->level( level_value ) );
189 if( ( window_bits_value < 8 || window_bits_value > MAX_WBITS ) &&
190 ( 0 != window_bits_value || operation_t::decompress != operation() ) )
194 RESTINIO_FMT_FORMAT_STRING(
195 "invalid window_bits: {}, must be " 196 "an integer value in the range of 8 to {} or " 197 "0 for decompress operation" ),
202 if( 8 == window_bits_value )
203 window_bits_value = 9;
214 return std::move(
this->window_bits( window_bits_value ) );
236 if( mem_level_value < 1 || mem_level_value > MAX_MEM_LEVEL )
240 RESTINIO_FMT_FORMAT_STRING(
241 "invalid compression mem_level: {}, must be " 242 "an integer value in the range of 1 to {}" ),
256 return std::move(
this->mem_level( mem_level_value ) );
276 if( Z_DEFAULT_STRATEGY != strategy_value &&
277 Z_FILTERED != strategy_value &&
278 Z_HUFFMAN_ONLY != strategy_value &&
279 Z_RLE != strategy_value )
283 RESTINIO_FMT_FORMAT_STRING(
284 "invalid compression strategy: {}, must be " 286 "Z_DEFAULT_STRATEGY({}), " 288 "Z_HUFFMAN_ONLY({}), " 306 return std::move(
this->strategy( strategy_value ) );
325 throw exception_t{
"too small reserve buffer size" };
328 m_reserve_buffer_size = size;
337 return std::move(
this->reserve_buffer_size( size ) );
488 m_zlib_stream.zalloc = Z_NULL;
489 m_zlib_stream.zfree = Z_NULL;
490 m_zlib_stream.opaque = Z_NULL;
496 auto current_window_bits = m_params.window_bits();
498 if( params_t::format_t::gzip == m_params.format() )
500 current_window_bits += 16;
503 if( params_t::operation_t::compress == m_params.operation() )
512 m_params.mem_level(),
513 m_params.strategy() );
520 current_window_bits );
523 if( Z_OK != init_result )
527 RESTINIO_FMT_FORMAT_STRING(
528 "Failed to initialize zlib stream: {}, {}" ),
550 if( params_t::operation_t::compress == m_params.operation() )
552 deflateEnd( &m_zlib_stream );
556 inflateEnd( &m_zlib_stream );
576 m_out_buffer.append( input.data(), input.size() );
577 m_write_pos = m_out_buffer.size();
581 if( std::numeric_limits<
decltype( m_zlib_stream.avail_in ) >::max() < input.size() )
585 RESTINIO_FMT_FORMAT_STRING(
586 "input data is too large: {} (max possible: {}), " 587 "try to break large data into pieces" ),
589 std::numeric_limits<
decltype( m_zlib_stream.avail_in ) >::max() ) };
592 if( 0 < input.size() )
594 m_zlib_stream.next_in =
595 reinterpret_cast< Bytef* >(
const_cast<
char* >( input.data() ) );
597 m_zlib_stream.avail_in =
static_cast< uInt >( input.size() );
599 if( params_t::operation_t::compress == m_params.operation() )
601 write_compress_impl( Z_NO_FLUSH );
605 write_decompress_impl( Z_NO_FLUSH );
623 m_zlib_stream.next_in =
nullptr;
624 m_zlib_stream.avail_in =
static_cast< uInt >( 0 );
626 if( params_t::operation_t::compress == m_params.operation() )
628 write_compress_impl( Z_SYNC_FLUSH );
632 write_decompress_impl( Z_SYNC_FLUSH );
645 m_zlib_stream.next_in =
nullptr;
646 m_zlib_stream.avail_in =
static_cast< uInt >( 0 );
648 if( params_t::operation_t::compress == m_params.operation() )
650 write_compress_impl( Z_FINISH );
654 write_decompress_impl( Z_FINISH );
687 const auto data_size = m_write_pos;
688 std::swap( result, m_out_buffer );
690 result.resize( data_size );
703 return params_t::format_t::identity == m_params.format();
710 const char * err_msg =
"<no zlib error description>";
711 if( m_zlib_stream.msg )
712 err_msg = m_zlib_stream.msg;
722 throw exception_t{
"zlib operation is already completed" };
730 m_out_buffer.size() + m_params.reserve_buffer_size() );
737 m_zlib_stream.next_out =
738 reinterpret_cast< Bytef* >(
739 const_cast<
char* >( m_out_buffer.data() + m_write_pos ) );
741 const auto provided_out_buffer_size =
742 m_out_buffer.size() - m_write_pos;
743 m_zlib_stream.avail_out =
744 static_cast<uInt>( provided_out_buffer_size );
746 return provided_out_buffer_size;
759 const auto provided_out_buffer_size = prepare_out_buffer();
761 int operation_result = deflate( &m_zlib_stream, flush );
763 if( !( Z_OK == operation_result ||
764 Z_BUF_ERROR == operation_result ||
765 ( Z_STREAM_END == operation_result && Z_FINISH == flush ) ) )
767 const char * err_msg =
"<no error desc>";
768 if( m_zlib_stream.msg )
769 err_msg = m_zlib_stream.msg;
773 RESTINIO_FMT_FORMAT_STRING(
774 "unexpected result of deflate() (zlib): {}, {}" ),
779 m_write_pos += provided_out_buffer_size - m_zlib_stream.avail_out;
781 if( 0 == m_zlib_stream.avail_out && Z_STREAM_END != operation_result )
791 if( 0 == m_zlib_stream.avail_in )
809 const auto provided_out_buffer_size = prepare_out_buffer();
811 int operation_result = inflate( &m_zlib_stream, flush );
812 if( !( Z_OK == operation_result ||
813 Z_BUF_ERROR == operation_result ||
814 Z_STREAM_END == operation_result ) )
818 RESTINIO_FMT_FORMAT_STRING(
819 "unexpected result of inflate() (zlib): {}, {}" ),
824 m_write_pos += provided_out_buffer_size - m_zlib_stream.avail_out;
826 if( 0 == m_zlib_stream.avail_out && Z_STREAM_END != operation_result )
836 if( Z_STREAM_END == operation_result )
843 if( 0 == m_zlib_stream.avail_in )
899 return z.giveaway_output();
905 return transform( input, make_deflate_compress_params( compression_level ) );
911 return transform( input, make_deflate_decompress_params() );
917 return transform( input, make_gzip_compress_params( compression_level ) );
923 return transform( input, make_gzip_decompress_params() );
931 template <
typename Response_Output_Strategy >
945 throw exception_t{
"operation is not copress" };
952 if(
nullptr == ztransformator )
954 throw exception_t{
"invalid body appender" };
961 std::string result{
"identity" };
965 result.assign(
"deflate" );
969 result.assign(
"gzip" );
982 template <
typename Response_Output_Strategy,
typename Descendant >
1018 template <
typename X_Controlled_Output,
typename Descendant >
1025 using base_type_t::base_type_t;
1134 impl::ensure_valid_transforator( m_ztransformator.get() );
1135 m_ztransformator->flush();
1137 .append_body( m_ztransformator->giveaway_output() )
1330 template <
typename Extra_Data,
typename Handler >
1333 const generic_request_t<Extra_Data> & req,
1334 Handler && handler )
1336 using restinio::impl::is_equal_caseless;
1338 const auto content_encoding =
1339 req.header().get_field_or( restinio::http_field::content_encoding,
"identity" );
1341 if( is_equal_caseless( content_encoding,
"deflate" ) )
1343 return handler( deflate_decompress( req.body() ) );
1345 else if( is_equal_caseless( content_encoding,
"gzip" ) )
1347 return handler( gzip_decompress( req.body() ) );
1349 else if( !is_equal_caseless( content_encoding,
"identity" ) )
1353 RESTINIO_FMT_FORMAT_STRING(
"content-encoding '{}' not supported" ),
1358 return handler( req.body() );
void complete()
Complete zlib transformation operation.
void complete()
Complete zlib transformation operation.
std::unique_ptr< zlib_t > m_ztransformator
std::enable_if< std::is_same< Parameter_Container, query_string_params_t >::value||std::is_same< Parameter_Container, router::route_params_t >::value, std::optional< Value_Type > >::type opt_value(const Parameter_Container ¶ms, string_view_t key)
Gets the value of a parameter specified by key wrapped in std::optional<Value_Type> if parameter exis...
virtual ~body_appender_base_t()
body_appender_base_t & operator=(const body_appender_base_t &)=delete
body_appender_base_t(body_appender_base_t &&ba) noexcept
body_appender_base_t & operator=(body_appender_base_t &&)=delete
body_appender_base_t(const body_appender_base_t &)=delete
Base class for body appenders with restinio or user controlled output.
Base class for body appenders.
body_appender_base_t(const params_t ¶ms, resp_t &resp)
Descendant & append(string_view_t input)
Append a piece of data to response.