1- import { gunzipSync } from 'fflate ' ;
2- import { beforeEach , describe , expect , test } from 'vitest' ;
1+ import { gunzipSync , gzipSync } from 'node:zlib ' ;
2+ import { beforeEach , describe , expect , test , vi } from 'vitest' ;
33import { createMemoryCache , createNullCache } from '../../cache' ;
44import { createNullLogger } from '../../logger' ;
55import { createTransporter } from '../../transporter' ;
66import { COMPRESSION_THRESHOLD } from '../../transporter/compress' ;
7- import type { AlgoliaAgent , EndRequest } from '../../types' ;
7+ import type { AlgoliaAgent , EndRequest , Logger } from '../../types' ;
88
9- // A payload large enough to exceed COMPRESSION_THRESHOLD
109const largePayload = { data : 'x' . repeat ( COMPRESSION_THRESHOLD + 1 ) } ;
1110
1211const algoliaAgent : AlgoliaAgent = {
1312 value : 'test' ,
1413 add : ( ) => algoliaAgent ,
1514} ;
1615
17- function makeTransporter ( compression ?: 'gzip' , onRequest ?: ( req : EndRequest ) => void ) {
16+ async function gzipCompress ( data : string ) : Promise < Uint8Array > {
17+ return gzipSync ( Buffer . from ( data ) ) ;
18+ }
19+
20+ function makeTransporter ( opts : {
21+ compress ?: ( data : string ) => Promise < Uint8Array > ;
22+ compression ?: 'gzip' ;
23+ logger ?: Logger ;
24+ onRequest ?: ( req : EndRequest ) => void ;
25+ } ) {
1826 return createTransporter ( {
1927 hosts : [ { url : 'localhost' , accept : 'readWrite' , protocol : 'https' } ] ,
2028 hostsCache : createNullCache ( ) ,
2129 baseHeaders : { } ,
2230 baseQueryParameters : { } ,
2331 algoliaAgent,
24- logger : createNullLogger ( ) ,
32+ logger : opts . logger ?? createNullLogger ( ) ,
2533 timeouts : { connect : 1000 , read : 2000 , write : 3000 } ,
26- ...( compression ? { compression } : { } ) ,
34+ ...( opts . compress ? { compress : opts . compress } : { } ) ,
35+ ...( opts . compression ? { compression : opts . compression } : { } ) ,
2736 requester : {
2837 send : async ( req ) => {
29- onRequest ?.( req ) ;
38+ opts . onRequest ?.( req ) ;
3039 return { status : 200 , content : '{}' , isTimedOut : false } ;
3140 } ,
3241 } ,
@@ -42,28 +51,28 @@ describe('compression', () => {
4251 captured = undefined ;
4352 } ) ;
4453
45- test ( 'does not compress when compression is not configured' , async ( ) => {
46- const transporter = makeTransporter ( undefined , ( req ) => {
47- captured = req ;
54+ test ( 'does not compress when compression is not enabled' , async ( ) => {
55+ const transporter = makeTransporter ( {
56+ compress : gzipCompress ,
57+ onRequest : ( req ) => {
58+ captured = req ;
59+ } ,
4860 } ) ;
4961
50- await transporter . request ( {
51- method : 'POST' ,
52- path : '/test' ,
53- queryParameters : { } ,
54- headers : { } ,
55- data : { foo : 'bar' } ,
56- } ) ;
62+ await transporter . request ( { method : 'POST' , path : '/test' , queryParameters : { } , headers : { } , data : largePayload } ) ;
5763
5864 expect ( captured ) . toBeDefined ( ) ;
5965 expect ( captured ! . headers [ 'content-encoding' ] ) . toBeUndefined ( ) ;
6066 expect ( typeof captured ! . data ) . toBe ( 'string' ) ;
61- expect ( captured ! . data ) . toBe ( '{"foo":"bar"}' ) ;
6267 } ) ;
6368
64- test ( 'compresses POST body when compression is gzip' , async ( ) => {
65- const transporter = makeTransporter ( 'gzip' , ( req ) => {
66- captured = req ;
69+ test ( 'compresses POST body when compression is gzip and compress is provided' , async ( ) => {
70+ const transporter = makeTransporter ( {
71+ compress : gzipCompress ,
72+ compression : 'gzip' ,
73+ onRequest : ( req ) => {
74+ captured = req ;
75+ } ,
6776 } ) ;
6877
6978 await transporter . request ( { method : 'POST' , path : '/test' , queryParameters : { } , headers : { } , data : largePayload } ) ;
@@ -72,13 +81,17 @@ describe('compression', () => {
7281 expect ( captured ! . headers [ 'content-encoding' ] ) . toBe ( 'gzip' ) ;
7382 expect ( captured ! . data ) . toBeInstanceOf ( Uint8Array ) ;
7483
75- const decompressed = new TextDecoder ( ) . decode ( gunzipSync ( captured ! . data as Uint8Array ) ) ;
84+ const decompressed = gunzipSync ( Buffer . from ( captured ! . data as Uint8Array ) ) . toString ( ) ;
7685 expect ( decompressed ) . toBe ( JSON . stringify ( largePayload ) ) ;
7786 } ) ;
7887
79- test ( 'compresses PUT body when compression is gzip' , async ( ) => {
80- const transporter = makeTransporter ( 'gzip' , ( req ) => {
81- captured = req ;
88+ test ( 'compresses PUT body when compression is gzip and compress is provided' , async ( ) => {
89+ const transporter = makeTransporter ( {
90+ compress : gzipCompress ,
91+ compression : 'gzip' ,
92+ onRequest : ( req ) => {
93+ captured = req ;
94+ } ,
8295 } ) ;
8396
8497 await transporter . request ( { method : 'PUT' , path : '/test' , queryParameters : { } , headers : { } , data : largePayload } ) ;
@@ -87,13 +100,17 @@ describe('compression', () => {
87100 expect ( captured ! . headers [ 'content-encoding' ] ) . toBe ( 'gzip' ) ;
88101 expect ( captured ! . data ) . toBeInstanceOf ( Uint8Array ) ;
89102
90- const decompressed = new TextDecoder ( ) . decode ( gunzipSync ( captured ! . data as Uint8Array ) ) ;
103+ const decompressed = gunzipSync ( Buffer . from ( captured ! . data as Uint8Array ) ) . toString ( ) ;
91104 expect ( decompressed ) . toBe ( JSON . stringify ( largePayload ) ) ;
92105 } ) ;
93106
94107 test ( 'does not compress POST when body is below threshold' , async ( ) => {
95- const transporter = makeTransporter ( 'gzip' , ( req ) => {
96- captured = req ;
108+ const transporter = makeTransporter ( {
109+ compress : gzipCompress ,
110+ compression : 'gzip' ,
111+ onRequest : ( req ) => {
112+ captured = req ;
113+ } ,
97114 } ) ;
98115
99116 await transporter . request ( {
@@ -110,8 +127,12 @@ describe('compression', () => {
110127 } ) ;
111128
112129 test ( 'does not compress GET requests' , async ( ) => {
113- const transporter = makeTransporter ( 'gzip' , ( req ) => {
114- captured = req ;
130+ const transporter = makeTransporter ( {
131+ compress : gzipCompress ,
132+ compression : 'gzip' ,
133+ onRequest : ( req ) => {
134+ captured = req ;
135+ } ,
115136 } ) ;
116137
117138 await transporter . request ( { method : 'GET' , path : '/test' , queryParameters : { } , headers : { } } ) ;
@@ -121,15 +142,36 @@ describe('compression', () => {
121142 expect ( captured ! . data ) . toBeUndefined ( ) ;
122143 } ) ;
123144
124- test ( 'does not compress POST when body is empty' , async ( ) => {
125- const transporter = makeTransporter ( 'gzip' , ( req ) => {
126- captured = req ;
145+ test ( 'logs warning when compression is gzip but compress method is missing' , async ( ) => {
146+ const logger : Logger = { debug : vi . fn ( ) , info : vi . fn ( ) , error : vi . fn ( ) } ;
147+ const transporter = makeTransporter ( {
148+ compression : 'gzip' ,
149+ logger,
150+ onRequest : ( req ) => {
151+ captured = req ;
152+ } ,
127153 } ) ;
128154
129- await transporter . request ( { method : 'POST' , path : '/test' , queryParameters : { } , headers : { } } ) ;
155+ await transporter . request ( { method : 'POST' , path : '/test' , queryParameters : { } , headers : { } , data : largePayload } ) ;
130156
131157 expect ( captured ) . toBeDefined ( ) ;
132158 expect ( captured ! . headers [ 'content-encoding' ] ) . toBeUndefined ( ) ;
133- expect ( captured ! . data ) . toBeUndefined ( ) ;
159+ expect ( typeof captured ! . data ) . toBe ( 'string' ) ;
160+ expect ( logger . info ) . toHaveBeenCalledWith ( 'Compression is disabled because no compress method is available.' ) ;
161+ } ) ;
162+
163+ test ( 'silently sends uncompressed when compression is gzip, compress is missing, and null logger' , async ( ) => {
164+ const transporter = makeTransporter ( {
165+ compression : 'gzip' ,
166+ onRequest : ( req ) => {
167+ captured = req ;
168+ } ,
169+ } ) ;
170+
171+ await transporter . request ( { method : 'POST' , path : '/test' , queryParameters : { } , headers : { } , data : largePayload } ) ;
172+
173+ expect ( captured ) . toBeDefined ( ) ;
174+ expect ( captured ! . headers [ 'content-encoding' ] ) . toBeUndefined ( ) ;
175+ expect ( typeof captured ! . data ) . toBe ( 'string' ) ;
134176 } ) ;
135177} ) ;
0 commit comments