@@ -2,7 +2,6 @@ use std::io::Write;
2
2
3
3
use bytes:: { BufMut , Bytes , BytesMut } ;
4
4
use codecs:: encoding:: { CharacterDelimitedEncoder , Framer , Serializer } ;
5
- use flate2:: write:: { GzEncoder , ZlibEncoder } ;
6
5
use futures:: { future, FutureExt , SinkExt } ;
7
6
use http:: {
8
7
header:: { HeaderName , HeaderValue , AUTHORIZATION } ,
@@ -23,7 +22,7 @@ use crate::{
23
22
sinks:: util:: {
24
23
self ,
25
24
http:: { BatchedHttpSink , HttpEventEncoder , RequestConfig } ,
26
- BatchConfig , Buffer , Compression , RealtimeSizeBasedDefaultBatchSettings ,
25
+ BatchConfig , Buffer , Compression , Compressor , RealtimeSizeBasedDefaultBatchSettings ,
27
26
TowerRequestConfig , UriSerde ,
28
27
} ,
29
28
tls:: { TlsConfig , TlsSettings } ,
@@ -375,24 +374,21 @@ impl util::http::HttpSink for HttpSink {
375
374
builder = builder. header ( "Content-Type" , content_type) ;
376
375
}
377
376
378
- match self . compression {
379
- Compression :: Gzip ( level) => {
380
- builder = builder. header ( "Content-Encoding" , "gzip" ) ;
381
-
382
- let buffer = BytesMut :: new ( ) ;
383
- let mut w = GzEncoder :: new ( buffer. writer ( ) , level. as_flate2 ( ) ) ;
384
- w. write_all ( & body) . expect ( "Writing to Vec can't fail" ) ;
385
- body = w. finish ( ) . expect ( "Writing to Vec can't fail" ) . into_inner ( ) ;
386
- }
387
- Compression :: Zlib ( level) => {
388
- builder = builder. header ( "Content-Encoding" , "deflate" ) ;
389
-
390
- let buffer = BytesMut :: new ( ) ;
391
- let mut w = ZlibEncoder :: new ( buffer. writer ( ) , level. as_flate2 ( ) ) ;
392
- w. write_all ( & body) . expect ( "Writing to Vec can't fail" ) ;
393
- body = w. finish ( ) . expect ( "Writing to Vec can't fail" ) . into_inner ( ) ;
394
- }
395
- Compression :: None => { }
377
+ let compression = self . compression ;
378
+
379
+ if compression. is_compressed ( ) {
380
+ builder = builder. header (
381
+ "Content-Encoding" ,
382
+ compression
383
+ . content_encoding ( )
384
+ . expect ( "Encoding should be specified." ) ,
385
+ ) ;
386
+
387
+ let mut compressor = Compressor :: from ( compression) ;
388
+ compressor
389
+ . write_all ( & body)
390
+ . expect ( "Writing to Vec can't fail." ) ;
391
+ body = compressor. finish ( ) . expect ( "Writing to Vec can't fail." ) ;
396
392
}
397
393
398
394
let headers = builder
@@ -477,12 +473,12 @@ mod tests {
477
473
encoding:: FramingConfig , JsonSerializerConfig , NewlineDelimitedEncoderConfig ,
478
474
TextSerializerConfig ,
479
475
} ;
480
- use flate2:: read:: MultiGzDecoder ;
476
+ use flate2:: { read:: MultiGzDecoder , read :: ZlibDecoder } ;
481
477
use futures:: { channel:: mpsc, stream, StreamExt } ;
482
478
use headers:: { Authorization , HeaderMapExt } ;
483
479
use http:: request:: Parts ;
484
480
use hyper:: { Method , Response , StatusCode } ;
485
- use serde:: Deserialize ;
481
+ use serde:: { de , Deserialize } ;
486
482
use vector_core:: event:: { BatchNotifier , BatchStatus , LogEvent } ;
487
483
488
484
use super :: * ;
@@ -812,15 +808,44 @@ mod tests {
812
808
}
813
809
814
810
#[ tokio:: test]
815
- async fn json_compression ( ) {
811
+ async fn json_gzip_compression ( ) {
812
+ json_compression ( "gzip" ) . await ;
813
+ }
814
+
815
+ #[ tokio:: test]
816
+ async fn json_zstd_compression ( ) {
817
+ json_compression ( "zstd" ) . await ;
818
+ }
819
+
820
+ #[ tokio:: test]
821
+ async fn json_zlib_compression ( ) {
822
+ json_compression ( "zlib" ) . await ;
823
+ }
824
+
825
+ #[ tokio:: test]
826
+ async fn json_gzip_compression_with_payload_wrapper ( ) {
827
+ json_compression_with_payload_wrapper ( "gzip" ) . await ;
828
+ }
829
+
830
+ #[ tokio:: test]
831
+ async fn json_zlib_compression_with_payload_wrapper ( ) {
832
+ json_compression_with_payload_wrapper ( "zlib" ) . await ;
833
+ }
834
+
835
+ #[ tokio:: test]
836
+ async fn json_zstd_compression_with_payload_wrapper ( ) {
837
+ json_compression_with_payload_wrapper ( "zstd" ) . await ;
838
+ }
839
+
840
+ async fn json_compression ( compression : & str ) {
816
841
components:: assert_sink_compliance ( & HTTP_SINK_TAGS , async {
817
842
let num_lines = 1000 ;
818
843
819
844
let in_addr = next_addr ( ) ;
820
845
821
846
let config = r#"
822
847
uri = "http://$IN_ADDR/frames"
823
- compression = "gzip "
848
+ compression = "$COMPRESSION "
824
849
encoding.codec = "json"
825
850
method = "post"
826
851
@@ -829,7 +854,9 @@ mod tests {
829
854
user = "waldo"
830
855
password = "hunter2"
831
856
"#
832
- . replace ( "$IN_ADDR" , & in_addr. to_string ( ) ) ;
857
+ . replace ( "$IN_ADDR" , & in_addr. to_string ( ) )
858
+ . replace ( "$COMPRESSION" , compression) ;
859
+
833
860
let config: HttpSinkConfig = toml:: from_str ( & config) . unwrap ( ) ;
834
861
835
862
let cx = SinkContext :: new_test ( ) ;
@@ -856,8 +883,7 @@ mod tests {
856
883
Some ( Authorization :: basic( "waldo" , "hunter2" ) ) ,
857
884
parts. headers. typed_get( )
858
885
) ;
859
- let lines: Vec < serde_json:: Value > =
860
- serde_json:: from_reader ( MultiGzDecoder :: new ( body. reader ( ) ) ) . unwrap ( ) ;
886
+ let lines: Vec < serde_json:: Value > = parse_compressed_json ( compression, body) ;
861
887
stream:: iter ( lines)
862
888
} )
863
889
. map ( |line| line. get ( "message" ) . unwrap ( ) . as_str ( ) . unwrap ( ) . to_owned ( ) )
@@ -870,16 +896,15 @@ mod tests {
870
896
. await ;
871
897
}
872
898
873
- #[ tokio:: test]
874
- async fn json_compression_with_payload_wrapper ( ) {
899
+ async fn json_compression_with_payload_wrapper ( compression : & str ) {
875
900
components:: assert_sink_compliance ( & HTTP_SINK_TAGS , async {
876
901
let num_lines = 1000 ;
877
902
878
903
let in_addr = next_addr ( ) ;
879
904
880
905
let config = r#"
881
906
uri = "http://$IN_ADDR/frames"
882
- compression = "gzip "
907
+ compression = "$COMPRESSION "
883
908
encoding.codec = "json"
884
909
payload_prefix = '{"data":'
885
910
payload_suffix = "}"
@@ -890,7 +915,9 @@ mod tests {
890
915
user = "waldo"
891
916
password = "hunter2"
892
917
"#
893
- . replace ( "$IN_ADDR" , & in_addr. to_string ( ) ) ;
918
+ . replace ( "$IN_ADDR" , & in_addr. to_string ( ) )
919
+ . replace ( "$COMPRESSION" , compression) ;
920
+
894
921
let config: HttpSinkConfig = toml:: from_str ( & config) . unwrap ( ) ;
895
922
896
923
let cx = SinkContext :: new_test ( ) ;
@@ -918,8 +945,8 @@ mod tests {
918
945
parts. headers. typed_get( )
919
946
) ;
920
947
921
- let message: serde_json:: Value =
922
- serde_json :: from_reader ( MultiGzDecoder :: new ( body . reader ( ) ) ) . unwrap ( ) ;
948
+ let message: serde_json:: Value = parse_compressed_json ( compression , body ) ;
949
+
923
950
let lines: Vec < serde_json:: Value > =
924
951
message[ "data" ] . as_array ( ) . unwrap ( ) . to_vec ( ) ;
925
952
stream:: iter ( lines)
@@ -934,6 +961,18 @@ mod tests {
934
961
. await ;
935
962
}
936
963
964
+ fn parse_compressed_json < T > ( compression : & str , buf : Bytes ) -> T
965
+ where
966
+ T : de:: DeserializeOwned ,
967
+ {
968
+ match compression {
969
+ "gzip" => serde_json:: from_reader ( MultiGzDecoder :: new ( buf. reader ( ) ) ) . unwrap ( ) ,
970
+ "zstd" => serde_json:: from_reader ( zstd:: Decoder :: new ( buf. reader ( ) ) . unwrap ( ) ) . unwrap ( ) ,
971
+ "zlib" => serde_json:: from_reader ( ZlibDecoder :: new ( buf. reader ( ) ) ) . unwrap ( ) ,
972
+ _ => panic ! ( "undefined compression: {}" , compression) ,
973
+ }
974
+ }
975
+
937
976
async fn get_received (
938
977
rx : mpsc:: Receiver < ( Parts , Bytes ) > ,
939
978
assert_parts : impl Fn ( Parts ) ,
0 commit comments