RESTinio

zlib.hpp
Go to the documentation of this file.
1/*
2 restinio
3*/
4
11#pragma once
12
13#include <restinio/impl/include_fmtlib.hpp>
14
15#include <restinio/impl/string_caseless_compare.hpp>
16
17#include <restinio/exception.hpp>
18#include <restinio/string_view.hpp>
19#include <restinio/message_builders.hpp>
20#include <restinio/request_handler.hpp>
21
22#include <zlib.h>
23
24#include <string>
25#include <cstring>
26
27 namespace restinio
28{
29
30 namespace transforms
31{
32
33 namespace zlib
34{
35
38 constexpr std::size_t default_output_reserve_buffer_size = 256 * 1024;
39
46 constexpr int default_window_bits = MAX_WBITS;
47 constexpr int default_mem_level = MAX_MEM_LEVEL;
48 constexpr int default_strategy = Z_DEFAULT_STRATEGY;
50
51//
52// params_t
53//
54
56/*
57 @since v.0.4.4
58
59 \note There is a special case for compression format: format_t::identity.
60 If this format is set that zlib transformator is transparently copies
61 input to output and so all other params are ignored.
62*/
63 class params_t
64{
65 public:
67 enum class operation_t
68 {
70 compress,
72 decompress
73 };
74
76 enum class format_t
77 {
79 deflate,
81 gzip,
83 /*
84 Means that no compression will be used and no header/trailer will be applied.
85 */
86 identity
87 };
88
90
96 params_t(
98 operation_t op,
100 format_t f,
102 int l = -1 )
103 : m_operation{ op }
104 , m_format{ f }
105 {
106 level( l );
107 }
108
110 params_t()
111 : m_operation{ operation_t::compress }
112 , m_format{ format_t::identity }
113 {
114 level( -1 );
115 }
116
118 operation_t operation() const { return m_operation; }
119
121 format_t format() const { return m_format; }
122
124
127 int level() const { return m_level; }
128
130
135 params_t &
136 level( int level_value ) &
137 {
138 if( level_value < -1 || level_value > 9 )
139 {
140 throw exception_t{
141 fmt::format(
142 "invalid compression level: {}, must be "
143 "an integer value in the range of -1 to 9",
144 level_value ) };
145 }
146
147 m_level = level_value;
148
149 return reference_to_self();
150 }
151
153 params_t &&
154 level( int level_value ) &&
155 {
156 return std::move( this->level( level_value ) );
157 }
158
160 int window_bits() const { return m_window_bits; }
161
163
170 params_t &
171 window_bits( int window_bits_value ) &
172 {
173 // From https://zlib.net/manual.html:
174 // For the current implementation of deflate(),
175 // a windowBits value of 8 (a window size of 256 bytes)
176 // is not supported. As a result, a request for 8 will result in 9
177 // (a 512-byte window). In that case, providing 8 to inflateInit2()
178 // will result in an error when the zlib header with 9 is
179 // checked against the initialization of inflate().
180 // The remedy is to not use 8 with deflateInit2()
181 // with this initialization, or at least in that case use 9
182 // with inflateInit2().
183 // ...
184 // windowBits can also be zero to request that inflate
185 // use the window size in the zlib header of the compressed
186 // stream.
187
188 if( ( window_bits_value < 8 || window_bits_value > MAX_WBITS ) &&
189 ( 0 != window_bits_value || operation_t::decompress != operation() ) )
190 {
191 throw exception_t{
192 fmt::format(
193 "invalid window_bits: {}, must be "
194 "an integer value in the range of 8 to {} or "
195 "0 for decompress operation",
196 window_bits_value,
197 MAX_WBITS ) };
198 }
199
200 if( 8 == window_bits_value )
201 window_bits_value = 9;
202
203 m_window_bits = window_bits_value;
204
205 return reference_to_self();
206 }
207
209 params_t &&
210 window_bits( int window_bits_value ) &&
211 {
212 return std::move( this->window_bits( window_bits_value ) );
213 }
214
216
219 int mem_level() const { return m_mem_level; }
220
222
231 params_t &
232 mem_level( int mem_level_value ) &
233 {
234 if( mem_level_value < 1 || mem_level_value > MAX_MEM_LEVEL )
235 {
236 throw exception_t{
237 fmt::format(
238 "invalid compression mem_level: {}, must be "
239 "an integer value in the range of 1 to {}",
240 mem_level_value,
241 MAX_MEM_LEVEL ) };
242 }
243
244 m_mem_level = mem_level_value;
245
246 return reference_to_self();
247 }
248
250 params_t &&
251 mem_level( int mem_level_value ) &&
252 {
253 return std::move( this->mem_level( mem_level_value ) );
254 }
255
257
260 int strategy() const { return m_strategy; }
261
263
270 params_t &
271 strategy( int strategy_value ) &
272 {
273 if( Z_DEFAULT_STRATEGY != strategy_value &&
274 Z_FILTERED != strategy_value &&
275 Z_HUFFMAN_ONLY != strategy_value &&
276 Z_RLE != strategy_value )
277 {
278 throw exception_t{
279 fmt::format(
280 "invalid compression strategy: {}, must be "
281 "one of: "
282 "Z_DEFAULT_STRATEGY({}), ",
283 "Z_FILTERED({}), ",
284 "Z_HUFFMAN_ONLY({}), ",
285 "Z_RLE({})",
286 strategy_value,
287 Z_DEFAULT_STRATEGY,
288 Z_FILTERED,
289 Z_HUFFMAN_ONLY,
290 Z_RLE ) };
291 }
292
293 m_strategy = strategy_value;
294
295 return reference_to_self();
296 }
297
299 params_t &&
300 strategy( int strategy_value ) &&
301 {
302 return std::move( this->strategy( strategy_value ) );
303 }
304
306
313 std::size_t reserve_buffer_size() const { return m_reserve_buffer_size; }
314
316 params_t &
317 reserve_buffer_size( std::size_t size ) &
318 {
319 if( size < 10UL )
320 {
321 throw exception_t{ "too small reserve buffer size" };
322 }
323
324 m_reserve_buffer_size = size;
325
326 return reference_to_self();
327 }
328
330 params_t &&
331 reserve_buffer_size( std::size_t size ) &&
332 {
333 return std::move( this->reserve_buffer_size( size ) );
334 }
335
336 private:
338 params_t & reference_to_self() { return *this; }
339
341 operation_t m_operation;
342
344 format_t m_format;
345
347
350 int m_level;
351
352 int m_window_bits{ default_window_bits };
353 int m_mem_level{ default_mem_level };
354 int m_strategy{ default_strategy };
355
357 std::size_t m_reserve_buffer_size{ default_output_reserve_buffer_size };
358};
359
379 inline params_t
380 make_deflate_compress_params( int compression_level = -1 )
381{
382 return params_t{
383 params_t::operation_t::compress,
384 params_t::format_t::deflate,
385 compression_level };
386}
387
388 inline params_t
389 make_deflate_decompress_params()
390{
391 return params_t{
392 params_t::operation_t::decompress,
393 params_t::format_t::deflate };
394}
395
396 inline params_t
397 make_gzip_compress_params( int compression_level = -1 )
398{
399 return params_t{
400 params_t::operation_t::compress,
401 params_t::format_t::gzip,
402 compression_level };
403}
404
405 inline params_t
406 make_gzip_decompress_params()
407{
408 return params_t{
409 params_t::operation_t::decompress,
410 params_t::format_t::gzip };
411}
412
413 inline params_t
414 make_identity_params()
415{
416 return params_t{};
417}
419
420//
421// zlib_t
422//
423
425
474 class zlib_t
475{
476 public:
477 zlib_t( const params_t & transformation_params )
478 : m_params{ transformation_params }
479 {
480 if( !is_identity() )
481 {
482 // Setting allocator stuff before initializing
483 // TODO: allocation can be done with user defined allocator.
484 m_zlib_stream.zalloc = Z_NULL;
485 m_zlib_stream.zfree = Z_NULL;
486 m_zlib_stream.opaque = Z_NULL;
487
488 // Track initialization result.
489 int init_result;
490
491 // Compression.
492 auto current_window_bits = m_params.window_bits();
493
494 if( params_t::format_t::gzip == m_params.format() )
495 {
496 current_window_bits += 16;
497 }
498
499 if( params_t::operation_t::compress == m_params.operation() )
500 {
501 // zlib format.
502 init_result =
503 deflateInit2(
504 &m_zlib_stream,
505 m_params.level(),
506 Z_DEFLATED,
507 current_window_bits,
508 m_params.mem_level(),
509 m_params.strategy() );
510 }
511 else
512 {
513 init_result =
514 inflateInit2(
515 &m_zlib_stream,
516 current_window_bits );
517 }
518
519 if( Z_OK != init_result )
520 {
521 throw exception_t{
522 fmt::format(
523 "Failed to initialize zlib stream: {}, {}",
524 init_result,
525 get_error_msg() ) };
526 }
527
528 m_zlib_stream_initialized = true;
529
530 // Reserve initial buffer.
531 inc_buffer();
532 }
533 // else => Nothing to initialize and to reserve.
534 }
535
536 zlib_t( const zlib_t & ) = delete;
537 zlib_t( zlib_t && ) = delete;
538 zlib_t & operator = ( const zlib_t & ) = delete;
539 zlib_t & operator = ( zlib_t && ) = delete;
540
541 ~zlib_t()
542 {
543 if( m_zlib_stream_initialized )
544 {
545 if( params_t::operation_t::compress == m_params.operation() )
546 {
547 deflateEnd( &m_zlib_stream );
548 }
549 else
550 {
551 inflateEnd( &m_zlib_stream );
552 }
553 }
554 }
555
557 const params_t & params() const { return m_params; }
558
560
564 void
565 write( string_view_t input )
566 {
567 ensure_operation_in_not_completed();
568
569 if( is_identity() )
570 {
571 m_out_buffer.append( input.data(), input.size() );
572 m_write_pos = m_out_buffer.size();
573 }
574 else
575 {
576 if( std::numeric_limits< decltype( m_zlib_stream.avail_in ) >::max() < input.size() )
577 {
578 throw exception_t{
579 fmt::format(
580 "input data is too large: {} (max possible: {}), "
581 "try to break large data into pieces",
582 input.size(),
583 std::numeric_limits< decltype( m_zlib_stream.avail_in ) >::max() ) };
584 }
585
586 if( 0 < input.size() )
587 {
588 m_zlib_stream.next_in =
589 reinterpret_cast< Bytef* >( const_cast< char* >( input.data() ) );
590
591 m_zlib_stream.avail_in = static_cast< uInt >( input.size() );
592
593 if( params_t::operation_t::compress == m_params.operation() )
594 {
595 write_compress_impl( Z_NO_FLUSH );
596 }
597 else
598 {
599 write_decompress_impl( Z_NO_FLUSH );
600 }
601 }
602 }
603 }
604
606
610 void
611 flush()
612 {
613 ensure_operation_in_not_completed();
614
615 if( !is_identity() )
616 {
617 m_zlib_stream.next_in = nullptr;
618 m_zlib_stream.avail_in = static_cast< uInt >( 0 );
619
620 if( params_t::operation_t::compress == m_params.operation() )
621 {
622 write_compress_impl( Z_SYNC_FLUSH );
623 }
624 else
625 {
626 write_decompress_impl( Z_SYNC_FLUSH );
627 }
628 }
629 }
630
632 void
633 complete()
634 {
635 ensure_operation_in_not_completed();
636
637 if( !is_identity() )
638 {
639 m_zlib_stream.next_in = nullptr;
640 m_zlib_stream.avail_in = static_cast< uInt >( 0 );
641
642 if( params_t::operation_t::compress == m_params.operation() )
643 {
644 write_compress_impl( Z_FINISH );
645 }
646 else
647 {
648 write_decompress_impl( Z_FINISH );
649 }
650 }
651
652 m_operation_is_complete = true;
653 }
654
656
677 std::string
678 giveaway_output()
679 {
680 std::string result;
681 const auto data_size = m_write_pos;
682 std::swap( result, m_out_buffer );
683 m_write_pos = 0;
684 result.resize( data_size ); // Shrink output data.
685 return result;
686 }
687
689 auto output_size() const { return m_write_pos; }
690
692 bool is_completed() const { return m_operation_is_complete; }
693
694 private:
695 bool is_identity() const
696 {
697 return params_t::format_t::identity == m_params.format();
698 }
699
701 const char *
702 get_error_msg() const
703 {
704 const char * err_msg = "<no zlib error description>";
705 if( m_zlib_stream.msg )
706 err_msg = m_zlib_stream.msg;
707
708 return err_msg;
709 }
710
712 void
713 ensure_operation_in_not_completed() const
714 {
715 if( is_completed() )
716 throw exception_t{ "zlib operation is already completed" };
717 }
718
720 void
721 inc_buffer()
722 {
723 m_out_buffer.resize(
724 m_out_buffer.size() + m_params.reserve_buffer_size() );
725 }
726
728 auto
729 prepare_out_buffer()
730 {
731 m_zlib_stream.next_out =
732 reinterpret_cast< Bytef* >(
733 const_cast< char* >( m_out_buffer.data() + m_write_pos ) );
734
735 const auto provided_out_buffer_size =
736 m_out_buffer.size() - m_write_pos;
737 m_zlib_stream.avail_out =
738 static_cast<uInt>( provided_out_buffer_size );
739
740 return provided_out_buffer_size;
741 }
742
744 /*
745 Data and its size must be already in
746 `m_zlib_stream.next_in`, `m_zlib_stream.avail_in`.
747 */
748 void
749 write_compress_impl( int flush )
750 {
751 while( true )
752 {
753 const auto provided_out_buffer_size = prepare_out_buffer();
754
755 int operation_result = deflate( &m_zlib_stream, flush );
756
757 if( !( Z_OK == operation_result ||
758 Z_BUF_ERROR == operation_result ||
759 ( Z_STREAM_END == operation_result && Z_FINISH == flush ) ) )
760 {
761 const char * err_msg = "<no error desc>";
762 if( m_zlib_stream.msg )
763 err_msg = m_zlib_stream.msg;
764
765 throw exception_t{
766 fmt::format(
767 "unexpected result of deflate() (zlib): {}, {}",
768 operation_result,
769 err_msg ) };
770 }
771
772 m_write_pos += provided_out_buffer_size - m_zlib_stream.avail_out;
773
774 if( 0 == m_zlib_stream.avail_out && Z_STREAM_END != operation_result )
775 {
776 // Looks like not all the output was obtained.
777 // There is a minor chance that it just happened to
778 // occupy exactly the same space that was available,
779 // in that case it would go for a one redundant call to deflate.
780 inc_buffer();
781 continue;
782 }
783
784 if( 0 == m_zlib_stream.avail_in )
785 {
786 // All the input was consumed.
787 break;
788 }
789 }
790 }
791
793 /*
794 Data and its size must be already in
795 `m_zlib_stream.next_in`, `m_zlib_stream.avail_in`.
796 */
797 void
798 write_decompress_impl( int flush )
799 {
800 while( true )
801 {
802 const auto provided_out_buffer_size = prepare_out_buffer();
803
804 int operation_result = inflate( &m_zlib_stream, flush );
805 if( !( Z_OK == operation_result ||
806 Z_BUF_ERROR == operation_result ||
807 Z_STREAM_END == operation_result ) )
808 {
809 throw exception_t{
810 fmt::format(
811 "unexpected result of inflate() (zlib): {}, {}",
812 operation_result,
813 get_error_msg() ) };
814 }
815
816 m_write_pos += provided_out_buffer_size - m_zlib_stream.avail_out;
817
818 if( 0 == m_zlib_stream.avail_out && Z_STREAM_END != operation_result )
819 {
820 // Looks like not all the output was obtained.
821 // There is a minor chance that it just happened to
822 // occupy exactly the same space that was available,
823 // in that case it would go for a one redundant call to deflate.
824 inc_buffer();
825 continue;
826 }
827
828 if( 0 == m_zlib_stream.avail_in )
829 {
830 // All the input was consumed.
831 break;
832 }
833 }
834 }
835
837 const params_t m_params;
838
840
844 bool m_zlib_stream_initialized{ false };
845
847 z_stream m_zlib_stream;
848
850 std::string m_out_buffer;
852 std::size_t m_write_pos{ 0 };
853
854 bool m_operation_is_complete{ false };
855};
856
875
877 inline std::string
878 transform( string_view_t input, const params_t & params )
879{
880 zlib_t z{ params };
881 z.write( input );
882 z.complete();
883
884 return z.giveaway_output();
885}
886
887 inline std::string
888 deflate_compress( string_view_t input, int compression_level = -1 )
889{
890 return transform( input, make_deflate_compress_params( compression_level ) );
891}
892
893 inline std::string
894 deflate_decompress( string_view_t input )
895{
896 return transform( input, make_deflate_decompress_params() );
897}
898
899 inline std::string
900 gzip_compress( string_view_t input, int compression_level = -1 )
901{
902 return transform( input, make_gzip_compress_params( compression_level ) );
903}
904
905 inline std::string
906 gzip_decompress( string_view_t input )
907{
908 return transform( input, make_gzip_decompress_params() );
909}
911
912//
913// body_appender_t
914//
915
916 template < typename Response_Output_Strategy >
917 class body_appender_t
918{
919 body_appender_t() = delete;
920};
921
922 namespace impl
923{
924
926 inline void ensure_is_compression_operation( params_t::operation_t op )
927{
928 if( params_t::operation_t::compress != op )
929 {
930 throw exception_t{ "operation is not copress" };
931 }
932}
933
935 inline void ensure_valid_transforator( zlib_t * ztransformator )
936{
937 if( nullptr == ztransformator )
938 {
939 throw exception_t{ "invalid body appender" };
940 }
941}
942
944 inline std::string content_encoding_token( params_t::format_t f )
945{
946 std::string result{ "identity" };
947
948 if( params_t::format_t::deflate == f )
949 {
950 result.assign( "deflate" );
951 }
952 if( params_t::format_t::gzip == f )
953 {
954 result.assign( "gzip" );
955 }
956
957 return result;
958}
959
960} /* namespace impl */
961
962//
963// body_appender_base_t
964//
965
967 template < typename Response_Output_Strategy, typename Descendant >
968 class body_appender_base_t
969{
970 public:
971 using resp_t = response_builder_t< Response_Output_Strategy >;
972
973 body_appender_base_t( const params_t & params, resp_t & resp )
974 : m_ztransformator{ std::make_unique< zlib_t >( params ) }
975 , m_resp{ resp }
976 {
977 impl::ensure_is_compression_operation(
978 m_ztransformator->params().operation() );
979
980 m_resp.append_header(
981 restinio::http_field::content_encoding,
982 impl::content_encoding_token(
983 m_ztransformator->params().format() ) );
984 }
985
986 body_appender_base_t( const body_appender_base_t & ) = delete;
987 body_appender_base_t & operator = ( const body_appender_base_t & ) = delete;
988 body_appender_base_t & operator = ( body_appender_base_t && ) = delete;
989
990 body_appender_base_t( body_appender_base_t && ba ) noexcept
991 : m_ztransformator{ std::move( ba.m_ztransformator ) }
992 , m_resp{ ba.m_resp }
993 {}
994
995 virtual ~body_appender_base_t() {}
996
997 protected:
998 std::unique_ptr< zlib_t > m_ztransformator;
999 resp_t & m_resp;
1000};
1001
1003 template < typename X_Controlled_Output, typename Descendant >
1004 class x_controlled_output_body_appender_base_t
1005 : public body_appender_base_t< X_Controlled_Output, Descendant >
1006{
1007 public:
1008 using base_type_t = body_appender_base_t< X_Controlled_Output, Descendant >;
1009
1010 using base_type_t::base_type_t;
1011
1013 Descendant &
1014 append( string_view_t input )
1015 {
1016 impl::ensure_valid_transforator( this->m_ztransformator.get() );
1017 this->m_ztransformator->write( input );
1018 return static_cast< Descendant & >( *this );
1019 }
1020
1022 void
1023 complete()
1024 {
1025 impl::ensure_valid_transforator( this->m_ztransformator.get() );
1026
1027 this->m_ztransformator->complete();
1028
1029 this->m_resp.append_body( this->m_ztransformator->giveaway_output() );
1030 }
1031};
1032
1055 template <>
1056 class body_appender_t< restinio_controlled_output_t >
1057 : public x_controlled_output_body_appender_base_t<
1058 restinio_controlled_output_t,
1059 body_appender_t< restinio_controlled_output_t > >
1060{
1061 public:
1062 using base_type_t =
1063 x_controlled_output_body_appender_base_t<
1064 restinio_controlled_output_t,
1065 body_appender_t< restinio_controlled_output_t > >;
1066
1068 auto
1069 size() const
1070 {
1071 impl::ensure_valid_transforator( m_ztransformator.get() );
1072
1073 return m_ztransformator->output_size();
1074 }
1075
1076 using base_type_t::base_type_t;
1077};
1078
1102 template <>
1103 class body_appender_t< user_controlled_output_t > final
1104 : public x_controlled_output_body_appender_base_t<
1105 user_controlled_output_t,
1106 body_appender_t< user_controlled_output_t > >
1107{
1108 public:
1109 using base_type_t =
1110 x_controlled_output_body_appender_base_t<
1111 user_controlled_output_t,
1112 body_appender_t< user_controlled_output_t > >;
1113
1114 using base_type_t::base_type_t;
1115
1116 auto &
1117 flush()
1118 {
1119 impl::ensure_valid_transforator( m_ztransformator.get() );
1120 m_ztransformator->flush();
1121 m_resp
1122 .append_body( m_ztransformator->giveaway_output() )
1123 .flush();
1124
1125 return *this;
1126 }
1127};
1128
1129
1162 template <>
1163 class body_appender_t< chunked_output_t > final
1164 : public body_appender_base_t<
1165 chunked_output_t,
1166 body_appender_t< chunked_output_t > >
1167{
1168 public:
1169 using base_type_t =
1170 body_appender_base_t<
1171 chunked_output_t,
1172 body_appender_t< chunked_output_t > >;
1173
1174 using base_type_t::base_type_t;
1175
1177
1181 auto &
1182 append( string_view_t input )
1183 {
1184 impl::ensure_valid_transforator( m_ztransformator.get() );
1185
1186 m_ztransformator->write( input );
1187 return *this;
1188 }
1189
1192
1197 auto &
1198 make_chunk( string_view_t input = string_view_t{} )
1199 {
1200 append( input ); // m_ztransformator is checked here.
1201
1202 m_ztransformator->flush(); // Flush already compressed data.
1203
1204 // Create a chunk with current output.
1205 m_resp.append_chunk( m_ztransformator->giveaway_output() );
1206
1207 return *this;
1208 }
1209
1212 void
1213 flush()
1214 {
1215 impl::ensure_valid_transforator( m_ztransformator.get() );
1216
1217 if( !m_ztransformator->is_completed() )
1218 {
1219 m_ztransformator->flush();
1220 m_resp.append_chunk( m_ztransformator->giveaway_output() );
1221 }
1222
1223 m_resp.flush();
1224 }
1225
1227 void
1228 complete()
1229 {
1230 impl::ensure_valid_transforator( m_ztransformator.get() );
1231 m_ztransformator->complete();
1232 m_resp.append_chunk( m_ztransformator->giveaway_output() );
1233 }
1234};
1235
1238 template < typename Response_Output_Strategy >
1239body_appender_t< Response_Output_Strategy >
1240 body_appender(
1241 response_builder_t< Response_Output_Strategy > & resp,
1242 const params_t & params )
1243{
1244 return body_appender_t< Response_Output_Strategy >{ params, resp };
1245}
1246
1249 template < typename Response_Output_Strategy >
1250body_appender_t< Response_Output_Strategy >
1251 deflate_body_appender(
1252 response_builder_t< Response_Output_Strategy > & resp,
1253 int compression_level = -1 )
1254{
1255 return body_appender( resp, make_deflate_compress_params( compression_level ) );
1256}
1257
1260 template < typename Response_Output_Strategy >
1261 inline body_appender_t< Response_Output_Strategy >
1262 gzip_body_appender(
1263 response_builder_t< Response_Output_Strategy > & resp,
1264 int compression_level = -1 )
1265{
1266 return body_appender( resp, make_gzip_compress_params( compression_level ) );
1267}
1268
1271 template < typename Response_Output_Strategy >
1272 inline body_appender_t< Response_Output_Strategy >
1273 identity_body_appender(
1274 response_builder_t< Response_Output_Strategy > & resp,
1275 int = -1 )
1276{
1277 return body_appender( resp, make_identity_params() );
1278}
1279
1281
1315 template < typename Extra_Data, typename Handler >
1316 decltype(auto)
1317 handle_body(
1318 const generic_request_t<Extra_Data> & req,
1319 Handler && handler )
1320{
1321 using restinio::impl::is_equal_caseless;
1322
1323 const auto content_encoding =
1324 req.header().get_field_or( restinio::http_field::content_encoding, "identity" );
1325
1326 if( is_equal_caseless( content_encoding, "deflate" ) )
1327 {
1328 return handler( deflate_decompress( req.body() ) );
1329 }
1330 else if( is_equal_caseless( content_encoding, "gzip" ) )
1331 {
1332 return handler( gzip_decompress( req.body() ) );
1333 }
1334 else if( !is_equal_caseless( content_encoding, "identity" ) )
1335 {
1336 throw exception_t{
1337 fmt::format( "content-encoding '{}' not supported", content_encoding ) };
1338 }
1339
1340 return handler( req.body() );
1341}
1342
1343} /* namespace zlib */
1344
1345} /* namespace transforms */
1346
1347} /* namespace restinio */
restinio::exception_t
Exception class for all exceptions thrown by RESTinio.
Definition: exception.hpp:26
restinio::generic_request_t
HTTP Request data.
Definition: request_handler.hpp:201
restinio::generic_request_t::header
const http_request_header_t & header() const noexcept
Get request header.
Definition: request_handler.hpp:256
restinio::generic_request_t::body
const std::string & body() const noexcept
Get request body.
Definition: request_handler.hpp:263
restinio::http_header_fields_t::get_field_or
std::string get_field_or(string_view_t field_name, string_view_t default_value) const
Get field value by field name or default value if the field not found.
Definition: http_headers.hpp:1040
restinio::response_builder_t
Forbid arbitrary response_builder_t instantiations.
Definition: message_builders.hpp:243
restinio::transforms::zlib::body_appender_base_t
Base class for body appenders.
Definition: zlib.hpp:969
restinio::transforms::zlib::body_appender_base_t::m_ztransformator
std::unique_ptr< zlib_t > m_ztransformator
Definition: zlib.hpp:998
restinio::transforms::zlib::body_appender_base_t::body_appender_base_t
body_appender_base_t(body_appender_base_t &&ba) noexcept
Definition: zlib.hpp:990
restinio::transforms::zlib::body_appender_base_t::body_appender_base_t
body_appender_base_t(const body_appender_base_t &)=delete
restinio::transforms::zlib::body_appender_base_t::m_resp
resp_t & m_resp
Definition: zlib.hpp:999
restinio::transforms::zlib::body_appender_base_t::body_appender_base_t
body_appender_base_t(const params_t &params, resp_t &resp)
Definition: zlib.hpp:973
restinio::transforms::zlib::body_appender_base_t::operator=
body_appender_base_t & operator=(const body_appender_base_t &)=delete
restinio::transforms::zlib::body_appender_base_t::~body_appender_base_t
virtual ~body_appender_base_t()
Definition: zlib.hpp:995
restinio::transforms::zlib::body_appender_t< chunked_output_t >
Definition: zlib.hpp:1167
restinio::transforms::zlib::body_appender_t< chunked_output_t >::flush
void flush()
Flushes currently available compressed data with possibly creating new chunk and then flushes target ...
Definition: zlib.hpp:1213
restinio::transforms::zlib::body_appender_t< chunked_output_t >::append
auto & append(string_view_t input)
Append data to be compressed.
Definition: zlib.hpp:1182
restinio::transforms::zlib::body_appender_t< chunked_output_t >::make_chunk
auto & make_chunk(string_view_t input=string_view_t{})
Append data to be compressed and adds current zlib transformator output as a new chunk.
Definition: zlib.hpp:1198
restinio::transforms::zlib::body_appender_t< chunked_output_t >::complete
void complete()
Complete zlib transformation operation.
Definition: zlib.hpp:1228
restinio::transforms::zlib::body_appender_t< restinio_controlled_output_t >
Definition: zlib.hpp:1060
restinio::transforms::zlib::body_appender_t< restinio_controlled_output_t >::size
auto size() const
Get the size of transformed body.
Definition: zlib.hpp:1069
restinio::transforms::zlib::body_appender_t< user_controlled_output_t >
Definition: zlib.hpp:1107
restinio::transforms::zlib::body_appender_t< user_controlled_output_t >::flush
auto & flush()
Definition: zlib.hpp:1117
restinio::transforms::zlib::body_appender_t
Definition: zlib.hpp:918
restinio::transforms::zlib::body_appender_t::body_appender_t
body_appender_t()=delete
restinio::transforms::zlib::params_t
Parameters of performing data transformation with zlib.
Definition: zlib.hpp:64
restinio::transforms::zlib::params_t::m_window_bits
int m_window_bits
Definition: zlib.hpp:352
restinio::transforms::zlib::params_t::strategy
params_t && strategy(int strategy_value) &&
Set compression strategy.
Definition: zlib.hpp:300
restinio::transforms::zlib::params_t::window_bits
params_t && window_bits(int window_bits_value) &&
Set window_bits.
Definition: zlib.hpp:210
restinio::transforms::zlib::params_t::window_bits
params_t & window_bits(int window_bits_value) &
Set window_bits.
Definition: zlib.hpp:171
restinio::transforms::zlib::params_t::format
format_t format() const
Get format.
Definition: zlib.hpp:121
restinio::transforms::zlib::params_t::params_t
params_t()
Default constructor for identiry transformator.
Definition: zlib.hpp:110
restinio::transforms::zlib::params_t::level
params_t && level(int level_value) &&
Set compression level.
Definition: zlib.hpp:154
restinio::transforms::zlib::params_t::window_bits
int window_bits() const
Get window_bits.
Definition: zlib.hpp:160
restinio::transforms::zlib::params_t::format_t
format_t
Formats of compressed data.
Definition: zlib.hpp:77
restinio::transforms::zlib::params_t::format_t::gzip
@ gzip
gzip format
restinio::transforms::zlib::params_t::format_t::deflate
@ deflate
zlib format.
restinio::transforms::zlib::params_t::format_t::identity
@ identity
Identity. With semantics descrobed here: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Ac...
restinio::transforms::zlib::params_t::mem_level
params_t & mem_level(int mem_level_value) &
Set compression mem_level.
Definition: zlib.hpp:232
restinio::transforms::zlib::params_t::m_operation
operation_t m_operation
Transformation type.
Definition: zlib.hpp:341
restinio::transforms::zlib::params_t::mem_level
int mem_level() const
Get compression mem_level.
Definition: zlib.hpp:219
restinio::transforms::zlib::params_t::m_level
int m_level
Compression level.
Definition: zlib.hpp:350
restinio::transforms::zlib::params_t::m_reserve_buffer_size
std::size_t m_reserve_buffer_size
Size initially reserved for buffer.
Definition: zlib.hpp:357
restinio::transforms::zlib::params_t::m_strategy
int m_strategy
Definition: zlib.hpp:354
restinio::transforms::zlib::params_t::m_format
format_t m_format
Format to be used for compressed data.
Definition: zlib.hpp:344
restinio::transforms::zlib::params_t::reserve_buffer_size
params_t & reserve_buffer_size(std::size_t size) &
Set the size initially reserved for buffer.
Definition: zlib.hpp:317
restinio::transforms::zlib::params_t::level
int level() const
Get compression level.
Definition: zlib.hpp:127
restinio::transforms::zlib::params_t::reserve_buffer_size
std::size_t reserve_buffer_size() const
Get the size initially reserved for buffer.
Definition: zlib.hpp:313
restinio::transforms::zlib::params_t::reserve_buffer_size
params_t && reserve_buffer_size(std::size_t size) &&
Set the size initially reserved for buffer.
Definition: zlib.hpp:331
restinio::transforms::zlib::params_t::m_mem_level
int m_mem_level
Definition: zlib.hpp:353
restinio::transforms::zlib::params_t::params_t
params_t(operation_t op, format_t f, int l=-1)
Init constructor.
Definition: zlib.hpp:96
restinio::transforms::zlib::params_t::level
params_t & level(int level_value) &
Set compression level.
Definition: zlib.hpp:136
restinio::transforms::zlib::params_t::reference_to_self
params_t & reference_to_self()
Get the reference to self.
Definition: zlib.hpp:338
restinio::transforms::zlib::params_t::mem_level
params_t && mem_level(int mem_level_value) &&
Set compression mem_level.
Definition: zlib.hpp:251
restinio::transforms::zlib::params_t::strategy
int strategy() const
Get compression strategy.
Definition: zlib.hpp:260
restinio::transforms::zlib::params_t::operation_t
operation_t
Types of transformation.
Definition: zlib.hpp:68
restinio::transforms::zlib::params_t::operation_t::decompress
@ decompress
Decompress input data.
restinio::transforms::zlib::params_t::operation_t::compress
@ compress
Compress the input data.
restinio::transforms::zlib::params_t::operation
operation_t operation() const
Get operation.
Definition: zlib.hpp:118
restinio::transforms::zlib::params_t::strategy
params_t & strategy(int strategy_value) &
Set compression strategy.
Definition: zlib.hpp:271
restinio::transforms::zlib::x_controlled_output_body_appender_base_t
Base class for body appenders with restinio or user controlled output.
Definition: zlib.hpp:1006
restinio::transforms::zlib::x_controlled_output_body_appender_base_t::append
Descendant & append(string_view_t input)
Append a piece of data to response.
Definition: zlib.hpp:1014
restinio::transforms::zlib::x_controlled_output_body_appender_base_t::complete
void complete()
Complete zlib transformation operation.
Definition: zlib.hpp:1023
restinio::transforms::zlib::zlib_t
Zlib transformator.
Definition: zlib.hpp:475
restinio::transforms::zlib::zlib_t::zlib_t
zlib_t(const zlib_t &)=delete
restinio::transforms::zlib::zlib_t::output_size
auto output_size() const
Get current output size.
Definition: zlib.hpp:689
restinio::transforms::zlib::zlib_t::m_zlib_stream_initialized
bool m_zlib_stream_initialized
Flag: was m_zlib_stream initialized properly.
Definition: zlib.hpp:844
restinio::transforms::zlib::zlib_t::inc_buffer
void inc_buffer()
Increment internal buffer for receiving output.
Definition: zlib.hpp:721
restinio::transforms::zlib::zlib_t::m_write_pos
std::size_t m_write_pos
Next write pos in out buffer.
Definition: zlib.hpp:852
restinio::transforms::zlib::zlib_t::m_operation_is_complete
bool m_operation_is_complete
Definition: zlib.hpp:854
restinio::transforms::zlib::zlib_t::is_completed
bool is_completed() const
Is operation complete?
Definition: zlib.hpp:692
restinio::transforms::zlib::zlib_t::write
void write(string_view_t input)
Append input data.
Definition: zlib.hpp:565
restinio::transforms::zlib::zlib_t::write_compress_impl
void write_compress_impl(int flush)
Handle incoming data for compression operation.
Definition: zlib.hpp:749
restinio::transforms::zlib::zlib_t::flush
void flush()
Flush the zlib stream.
Definition: zlib.hpp:611
restinio::transforms::zlib::zlib_t::get_error_msg
const char * get_error_msg() const
Get zlib error message if it exists.
Definition: zlib.hpp:702
restinio::transforms::zlib::zlib_t::ensure_operation_in_not_completed
void ensure_operation_in_not_completed() const
Checks completion flag and throws if operation is is already completed.
Definition: zlib.hpp:713
restinio::transforms::zlib::zlib_t::prepare_out_buffer
auto prepare_out_buffer()
Prepare out buffer for receiving data.
Definition: zlib.hpp:729
restinio::transforms::zlib::zlib_t::m_params
const params_t m_params
Parameters for zlib.
Definition: zlib.hpp:837
restinio::transforms::zlib::zlib_t::m_out_buffer
std::string m_out_buffer
Output buffer.
Definition: zlib.hpp:850
restinio::transforms::zlib::zlib_t::zlib_t
zlib_t(zlib_t &&)=delete
restinio::transforms::zlib::zlib_t::is_identity
bool is_identity() const
Definition: zlib.hpp:695
restinio::transforms::zlib::zlib_t::zlib_t
zlib_t(const params_t &transformation_params)
Definition: zlib.hpp:477
restinio::transforms::zlib::zlib_t::giveaway_output
std::string giveaway_output()
Get current accumulated output data.
Definition: zlib.hpp:678
restinio::transforms::zlib::zlib_t::write_decompress_impl
void write_decompress_impl(int flush)
Handle incoming data for decompression operation.
Definition: zlib.hpp:798
restinio::transforms::zlib::zlib_t::complete
void complete()
Complete the stream.
Definition: zlib.hpp:633
restinio::transforms::zlib::zlib_t::operator=
zlib_t & operator=(const zlib_t &)=delete
restinio::transforms::zlib::zlib_t::params
const params_t & params() const
Get parameters of current transformation.
Definition: zlib.hpp:557
restinio::transforms::zlib::zlib_t::m_zlib_stream
z_stream m_zlib_stream
zlib stream.
Definition: zlib.hpp:847
restinio::transforms::zlib::zlib_t::~zlib_t
~zlib_t()
Definition: zlib.hpp:541
compress
int ZEXPORT compress(Bytef *dest, uLongf *destLen, const Bytef *source, uLong sourceLen)
Definition: compress.c:68
deflateEnd
int ZEXPORT deflateEnd(z_streamp strm)
Definition: deflate.c:1076
deflate
int ZEXPORT deflate(z_streamp strm, int flush)
Definition: deflate.c:763
exception.hpp
include_fmtlib.hpp
A special wrapper around fmtlib include files.
inflate
int ZEXPORT inflate(z_streamp strm, int flush)
Definition: inflate.c:622
inflateEnd
int ZEXPORT inflateEnd(z_streamp strm)
Definition: inflate.c:1277
message_builders.hpp
nonstd::optional_lite::std11::move
T & move(T &t)
Definition: optional.hpp:465
nonstd::optional_lite::swap
void swap(optional< T > &x, optional< T > &y)
Definition: optional.hpp:1705
restinio::impl::is_equal_caseless
bool is_equal_caseless(const char *a, const char *b, std::size_t size) noexcept
Comparator for fields names.
Definition: string_caseless_compare.hpp:40
restinio::transforms::zlib::impl::content_encoding_token
std::string content_encoding_token(params_t::format_t f)
Get token for copression format.
Definition: zlib.hpp:944
restinio::transforms::zlib::impl::ensure_is_compression_operation
void ensure_is_compression_operation(params_t::operation_t op)
Check if operation is a copression, and throw if it is not.
Definition: zlib.hpp:926
restinio::transforms::zlib::impl::ensure_valid_transforator
void ensure_valid_transforator(zlib_t *ztransformator)
Check if a pointer to zlib transformator is valid.
Definition: zlib.hpp:935
restinio::transforms::zlib::make_gzip_compress_params
params_t make_gzip_compress_params(int compression_level=-1)
Definition: zlib.hpp:397
restinio::transforms::zlib::make_gzip_decompress_params
params_t make_gzip_decompress_params()
Definition: zlib.hpp:406
restinio::transforms::zlib::gzip_decompress
std::string gzip_decompress(string_view_t input)
Definition: zlib.hpp:906
restinio::transforms::zlib::default_mem_level
constexpr int default_mem_level
Definition: zlib.hpp:47
restinio::transforms::zlib::transform
std::string transform(string_view_t input, const params_t &params)
Do a specified zlib transformation.
Definition: zlib.hpp:878
restinio::transforms::zlib::make_deflate_compress_params
params_t make_deflate_compress_params(int compression_level=-1)
Definition: zlib.hpp:380
restinio::transforms::zlib::default_strategy
constexpr int default_strategy
Definition: zlib.hpp:48
restinio::transforms::zlib::deflate_decompress
std::string deflate_decompress(string_view_t input)
Definition: zlib.hpp:894
restinio::transforms::zlib::handle_body
decltype(auto) handle_body(const generic_request_t< Extra_Data > &req, Handler &&handler)
Call a handler over a request body.
Definition: zlib.hpp:1317
restinio::transforms::zlib::deflate_compress
std::string deflate_compress(string_view_t input, int compression_level=-1)
Definition: zlib.hpp:888
restinio::transforms::zlib::deflate_body_appender
body_appender_t< Response_Output_Strategy > deflate_body_appender(response_builder_t< Response_Output_Strategy > &resp, int compression_level=-1)
Create body appender with deflate transformation and a given compression level.
Definition: zlib.hpp:1251
restinio::transforms::zlib::gzip_body_appender
body_appender_t< Response_Output_Strategy > gzip_body_appender(response_builder_t< Response_Output_Strategy > &resp, int compression_level=-1)
Create body appender with gzip transformation and a given compression level.
Definition: zlib.hpp:1262
restinio::transforms::zlib::default_output_reserve_buffer_size
constexpr std::size_t default_output_reserve_buffer_size
Default reserve buffer size for zlib transformator.
Definition: zlib.hpp:38
restinio::transforms::zlib::identity_body_appender
body_appender_t< Response_Output_Strategy > identity_body_appender(response_builder_t< Response_Output_Strategy > &resp, int=-1)
Create body appender with gzip transformation and a given compression level.
Definition: zlib.hpp:1273
restinio::transforms::zlib::make_identity_params
params_t make_identity_params()
Definition: zlib.hpp:414
restinio::transforms::zlib::gzip_compress
std::string gzip_compress(string_view_t input, int compression_level=-1)
Definition: zlib.hpp:900
restinio::transforms::zlib::body_appender
body_appender_t< Response_Output_Strategy > body_appender(response_builder_t< Response_Output_Strategy > &resp, const params_t &params)
Create body appender with given zlib transformation parameters.
Definition: zlib.hpp:1240
restinio::transforms::zlib::make_deflate_decompress_params
params_t make_deflate_decompress_params()
Definition: zlib.hpp:389
restinio::transforms::zlib::default_window_bits
constexpr int default_window_bits
Definition: zlib.hpp:46
restinio
Definition: asio_include.hpp:21
restinio::string_view_t
nonstd::string_view string_view_t
Definition: string_view.hpp:19
std
STL namespace.
request_handler.hpp
string_caseless_compare.hpp
Helpers for caseless comparison of strings.
string_view.hpp
restinio::chunked_output_t
Tag type for chunked output response builder.
Definition: message_builders.hpp:622
restinio::restinio_controlled_output_t
Tag type for RESTinio controlled output response builder.
Definition: message_builders.hpp:248
restinio::user_controlled_output_t
Tag type for user controlled output response builder.
Definition: message_builders.hpp:392
z_stream_s
Definition: zlib.h:86
z_stream_s::avail_in
uInt avail_in
Definition: zlib.h:88
z_stream_s::zalloc
alloc_func zalloc
Definition: zlib.h:98
z_stream_s::avail_out
uInt avail_out
Definition: zlib.h:92
z_stream_s::next_in
z_const Bytef * next_in
Definition: zlib.h:87
z_stream_s::zfree
free_func zfree
Definition: zlib.h:99
z_stream_s::opaque
voidpf opaque
Definition: zlib.h:100
z_stream_s::next_out
Bytef * next_out
Definition: zlib.h:91
z_stream_s::msg
z_const char * msg
Definition: zlib.h:95
uInt
unsigned int uInt
Definition: zconf.h:393
MAX_MEM_LEVEL
#define MAX_MEM_LEVEL
Definition: zconf.h:260
MAX_WBITS
#define MAX_WBITS
Definition: zconf.h:270
Bytef
Byte FAR Bytef
Definition: zconf.h:400
zlib.h
Z_HUFFMAN_ONLY
#define Z_HUFFMAN_ONLY
Definition: zlib.h:197
Z_DEFLATED
#define Z_DEFLATED
Definition: zlib.h:209
Z_BUF_ERROR
#define Z_BUF_ERROR
Definition: zlib.h:184
Z_DEFAULT_STRATEGY
#define Z_DEFAULT_STRATEGY
Definition: zlib.h:200
deflateInit2
#define deflateInit2(strm, level, method, windowBits, memLevel, strategy)
Definition: zlib.h:1797
inflateInit2
#define inflateInit2(strm, windowBits)
Definition: zlib.h:1800
Z_STREAM_END
#define Z_STREAM_END
Definition: zlib.h:178
Z_FINISH
#define Z_FINISH
Definition: zlib.h:172
Z_OK
#define Z_OK
Definition: zlib.h:177
Z_SYNC_FLUSH
#define Z_SYNC_FLUSH
Definition: zlib.h:170
Z_NO_FLUSH
#define Z_NO_FLUSH
Definition: zlib.h:168
Z_NULL
#define Z_NULL
Definition: zlib.h:212
Z_FILTERED
#define Z_FILTERED
Definition: zlib.h:196
Z_RLE
#define Z_RLE
Definition: zlib.h:198