Skip to content

Commit 0d988f9

Browse files
authored
feat(javascript): allow providing options for node requester (#872)
1 parent 7b96d39 commit 0d988f9

File tree

2 files changed

+98
-6
lines changed

2 files changed

+98
-6
lines changed

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

Lines changed: 68 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
import type http from 'http';
1+
import http from 'http';
2+
import https from 'https';
23
import { Readable } from 'stream';
34

45
import type { EndRequest } from '@algolia/client-common';
@@ -17,6 +18,72 @@ import {
1718

1819
const requester = createHttpRequester();
1920

21+
const httpsBaseRequest = https.request;
22+
const httpBaseRequest = http.request;
23+
24+
describe('api', () => {
25+
const mockedRequestResponse = {
26+
destroy: jest.fn(),
27+
on: jest.fn(),
28+
once: jest.fn(),
29+
write: jest.fn(),
30+
end: jest.fn(),
31+
};
32+
33+
beforeAll(() => {
34+
// @ts-expect-error we don't care about the response for those tests
35+
https.request = jest.fn(() => mockedRequestResponse);
36+
});
37+
38+
afterAll(() => {
39+
https.request = httpsBaseRequest;
40+
http.request = httpBaseRequest;
41+
jest.resetAllMocks();
42+
jest.clearAllMocks();
43+
});
44+
45+
it('allow init without parameters', () => {
46+
expect(() => createHttpRequester()).not.toThrow();
47+
});
48+
49+
it('allow providing custom agent', async () => {
50+
const agent = new http.Agent();
51+
// @ts-expect-error we don't care about the response for those tests
52+
http.request = jest.fn(() => mockedRequestResponse);
53+
const tmpRequester = createHttpRequester({
54+
agent,
55+
});
56+
57+
await tmpRequester.send({
58+
...requestStub,
59+
url: 'http://algolia-dns.net/foo?x-algolia-header=bar',
60+
});
61+
62+
expect(http.request).toHaveBeenCalled();
63+
});
64+
65+
it('allow overriding default options', async () => {
66+
const tmpRequester = createHttpRequester({
67+
requesterOptions: {
68+
headers: {
69+
'my-extra-header': 'algolia',
70+
},
71+
},
72+
});
73+
74+
await tmpRequester.send(requestStub);
75+
76+
expect(https.request).toHaveBeenCalledWith(
77+
expect.objectContaining({
78+
headers: expect.objectContaining({
79+
'my-extra-header': 'algolia',
80+
}),
81+
}),
82+
expect.any(Function)
83+
);
84+
});
85+
});
86+
2087
describe('status code handling', () => {
2188
it('sends requests', async () => {
2289
const body = getStringifiedBody();

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

Lines changed: 30 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,30 @@ import { URL } from 'url';
44

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

7+
export type CreateHttpRequesterOptions = Partial<{
8+
agent: http.Agent | https.Agent;
9+
httpAgent: http.Agent;
10+
httpsAgent: https.Agent;
11+
/**
12+
* RequestOptions to be merged with the end request, it will override default options if provided.
13+
*/
14+
requesterOptions: https.RequestOptions;
15+
}>;
16+
717
// Global agents allow us to reuse the TCP protocol with multiple clients
818
const agentOptions = { keepAlive: true };
9-
const httpAgent = new http.Agent(agentOptions);
10-
const httpsAgent = new https.Agent(agentOptions);
19+
const defaultHttpAgent = new http.Agent(agentOptions);
20+
const defaultHttpsAgent = new https.Agent(agentOptions);
21+
22+
export function createHttpRequester({
23+
agent: userGlobalAgent,
24+
httpAgent: userHttpAgent,
25+
httpsAgent: userHttpsAgent,
26+
requesterOptions = {},
27+
}: CreateHttpRequesterOptions = {}): Requester {
28+
const httpAgent = userHttpAgent || userGlobalAgent || defaultHttpAgent;
29+
const httpsAgent = userHttpsAgent || userGlobalAgent || defaultHttpsAgent;
1130

12-
export function createHttpRequester(): Requester {
1331
function send(request: EndRequest): Promise<Response> {
1432
return new Promise((resolve) => {
1533
let responseTimeout: NodeJS.Timeout | undefined;
@@ -23,10 +41,17 @@ export function createHttpRequester(): Requester {
2341
hostname: url.hostname,
2442
path,
2543
method: request.method,
26-
headers: request.headers,
27-
...(url.port !== undefined ? { port: url.port || '' } : {}),
44+
...requesterOptions,
45+
headers: {
46+
...request.headers,
47+
...requesterOptions.headers,
48+
},
2849
};
2950

51+
if (url.port && !requesterOptions.port) {
52+
options.port = url.port;
53+
}
54+
3055
const req = (url.protocol === 'https:' ? https : http).request(
3156
options,
3257
(response) => {

0 commit comments

Comments
 (0)