Skip to content

Commit a196c9c

Browse files
authored
feat(clients): response decompression (#6095)
1 parent e825c07 commit a196c9c

File tree

6 files changed

+114
-2
lines changed

6 files changed

+114
-2
lines changed

clients/algoliasearch-client-javascript/packages/requester-node-http/src/createHttpRequester.ts

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import http from 'http';
22
import https from 'https';
33
import { URL } from 'url';
4+
import zlib from 'zlib';
45

56
import type { EndRequest, Requester, Response } from '@algolia/client-common';
67

@@ -41,6 +42,7 @@ export function createHttpRequester({
4142
method: request.method,
4243
...requesterOptions,
4344
headers: {
45+
'accept-encoding': 'gzip',
4446
...request.headers,
4547
...requesterOptions.headers,
4648
},
@@ -61,9 +63,14 @@ export function createHttpRequester({
6163
clearTimeout(connectTimeout as NodeJS.Timeout);
6264
clearTimeout(responseTimeout as NodeJS.Timeout);
6365

66+
let buffer = Buffer.concat(contentBuffers);
67+
if (response.headers['content-encoding'] === 'gzip') {
68+
buffer = zlib.gunzipSync(buffer);
69+
}
70+
6471
resolve({
6572
status: response.statusCode || 0,
66-
content: Buffer.concat(contentBuffers).toString(),
73+
content: buffer.toString(),
6774
isTimedOut: false,
6875
});
6976
});

clients/algoliasearch-client-ruby/lib/algolia/transport/transport.rb

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -136,7 +136,6 @@ def build_body(body, request_options)
136136
def generate_header_params(body, request_options)
137137
header_params = request_options.header_params.transform_keys(&:downcase)
138138
header_params = @config.header_params.merge(header_params)
139-
header_params["accept-encoding"] = "gzip" if request_options.compression_type == "gzip"
140139
if request_options.compression_type == "gzip" && body.is_a?(String) && !body.to_s.strip.empty?
141140
header_params["content-encoding"] = "gzip"
142141
end
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
import type { Server } from 'http';
2+
3+
import zlib from 'node:zlib';
4+
5+
import type { Express } from 'express';
6+
7+
import { setupServer } from './index.ts';
8+
9+
const RESPONSE_BODY = {
10+
message: 'ok decompression test server response',
11+
data: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit.',
12+
};
13+
14+
function addRoutes(app: Express): void {
15+
app.get('/1/test/gzip-response', (req, res) => {
16+
const acceptEncoding = req.headers['accept-encoding'] || '';
17+
if (!acceptEncoding.includes('gzip')) {
18+
res.status(400).json({ message: 'client did not send accept-encoding: gzip' });
19+
return;
20+
}
21+
22+
const body = JSON.stringify(RESPONSE_BODY);
23+
zlib.gzip(Buffer.from(body, 'utf-8'), (err, compressed) => {
24+
if (err) {
25+
res.status(500).json({ message: `error compressing response: ${err}` });
26+
return;
27+
}
28+
29+
res.writeHead(200, {
30+
'Content-Type': 'application/json',
31+
'Content-Encoding': 'gzip',
32+
});
33+
res.end(compressed);
34+
});
35+
});
36+
}
37+
38+
export function gzipResponseServer(): Promise<Server> {
39+
return setupServer('gzipResponse', 6691, addRoutes);
40+
}

scripts/cts/testServer/index.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import { benchmarkServer } from './benchmark.ts';
1414
import { chunkWrapperServer } from './chunkWrapper.ts';
1515
import { errorServer, errorServerRetriedOnce, errorServerRetriedTwice, neverCalledServer } from './error.ts';
1616
import { gzipServer } from './gzip.ts';
17+
import { gzipResponseServer } from './gzipResponse.ts';
1718
import { pushMockServer, pushMockServerRetriedOnce } from './pushMock.ts';
1819
import { replaceAllObjectsServer } from './replaceAllObjects.ts';
1920
import { replaceAllObjectsServerFailed } from './replaceAllObjectsFailed.ts';
@@ -35,6 +36,7 @@ export async function startTestServer(suites: Record<CTSType, boolean>): Promise
3536
neverCalledServer(),
3637
successServer(),
3738
gzipServer(),
39+
gzipResponseServer(),
3840
timeoutServerBis(),
3941
accountCopyIndexServer(),
4042
replaceAllObjectsServer(),

tests/CTS/client/composition/api.json

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,5 +85,37 @@
8585
}
8686
}
8787
]
88+
},
89+
{
90+
"testName": "test the response decompression strategy",
91+
"autoCreateClient": false,
92+
"steps": [
93+
{
94+
"type": "createClient",
95+
"parameters": {
96+
"appId": "test-app-id",
97+
"apiKey": "test-api-key",
98+
"customHosts": [
99+
{
100+
"port": 6691
101+
}
102+
]
103+
}
104+
},
105+
{
106+
"type": "method",
107+
"method": "customGet",
108+
"parameters": {
109+
"path": "1/test/gzip-response"
110+
},
111+
"expected": {
112+
"type": "response",
113+
"match": {
114+
"message": "ok decompression test server response",
115+
"data": "Lorem ipsum dolor sit amet, consectetur adipiscing elit."
116+
}
117+
}
118+
}
119+
]
88120
}
89121
]

tests/CTS/client/search/api.json

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -224,6 +224,38 @@
224224
}
225225
]
226226
},
227+
{
228+
"testName": "test the response decompression strategy",
229+
"autoCreateClient": false,
230+
"steps": [
231+
{
232+
"type": "createClient",
233+
"parameters": {
234+
"appId": "test-app-id",
235+
"apiKey": "test-api-key",
236+
"customHosts": [
237+
{
238+
"port": 6691
239+
}
240+
]
241+
}
242+
},
243+
{
244+
"type": "method",
245+
"method": "customGet",
246+
"parameters": {
247+
"path": "1/test/gzip-response"
248+
},
249+
"expected": {
250+
"type": "response",
251+
"match": {
252+
"message": "ok decompression test server response",
253+
"data": "Lorem ipsum dolor sit amet, consectetur adipiscing elit."
254+
}
255+
}
256+
}
257+
]
258+
},
227259
{
228260
"testName": "calls api with default read timeouts",
229261
"steps": [

0 commit comments

Comments
 (0)