@algolia/requester-node-http 5.0.0-alpha.1 → 5.0.0-alpha.12

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -18,9 +18,11 @@ function echoRequester(status = 200) {
18
18
 
19
19
  // Global agents allow us to reuse the TCP protocol with multiple clients
20
20
  const agentOptions = { keepAlive: true };
21
- const httpAgent = new http__default["default"].Agent(agentOptions);
22
- const httpsAgent = new https__default["default"].Agent(agentOptions);
23
- function createHttpRequester() {
21
+ const defaultHttpAgent = new http__default["default"].Agent(agentOptions);
22
+ const defaultHttpsAgent = new https__default["default"].Agent(agentOptions);
23
+ function createHttpRequester({ agent: userGlobalAgent, httpAgent: userHttpAgent, httpsAgent: userHttpsAgent, requesterOptions = {}, } = {}) {
24
+ const httpAgent = userHttpAgent || userGlobalAgent || defaultHttpAgent;
25
+ const httpsAgent = userHttpsAgent || userGlobalAgent || defaultHttpsAgent;
24
26
  function send(request) {
25
27
  return new Promise((resolve) => {
26
28
  let responseTimeout;
@@ -33,9 +35,15 @@ function createHttpRequester() {
33
35
  hostname: url$1.hostname,
34
36
  path,
35
37
  method: request.method,
36
- headers: request.headers,
37
- ...(url$1.port !== undefined ? { port: url$1.port || '' } : {}),
38
+ ...requesterOptions,
39
+ headers: {
40
+ ...request.headers,
41
+ ...requesterOptions.headers,
42
+ },
38
43
  };
44
+ if (url$1.port && !requesterOptions.port) {
45
+ options.port = url$1.port;
46
+ }
39
47
  const req = (url$1.protocol === 'https:' ? https__default["default"] : http__default["default"]).request(options, (response) => {
40
48
  let contentBuffers = [];
41
49
  response.on('data', (chunk) => {
@@ -9,9 +9,11 @@ function echoRequester(status = 200) {
9
9
 
10
10
  // Global agents allow us to reuse the TCP protocol with multiple clients
11
11
  const agentOptions = { keepAlive: true };
12
- const httpAgent = new http.Agent(agentOptions);
13
- const httpsAgent = new https.Agent(agentOptions);
14
- function createHttpRequester() {
12
+ const defaultHttpAgent = new http.Agent(agentOptions);
13
+ const defaultHttpsAgent = new https.Agent(agentOptions);
14
+ function createHttpRequester({ agent: userGlobalAgent, httpAgent: userHttpAgent, httpsAgent: userHttpsAgent, requesterOptions = {}, } = {}) {
15
+ const httpAgent = userHttpAgent || userGlobalAgent || defaultHttpAgent;
16
+ const httpsAgent = userHttpsAgent || userGlobalAgent || defaultHttpsAgent;
15
17
  function send(request) {
16
18
  return new Promise((resolve) => {
17
19
  let responseTimeout;
@@ -24,9 +26,15 @@ function createHttpRequester() {
24
26
  hostname: url.hostname,
25
27
  path,
26
28
  method: request.method,
27
- headers: request.headers,
28
- ...(url.port !== undefined ? { port: url.port || '' } : {}),
29
+ ...requesterOptions,
30
+ headers: {
31
+ ...request.headers,
32
+ ...requesterOptions.headers,
33
+ },
29
34
  };
35
+ if (url.port && !requesterOptions.port) {
36
+ options.port = url.port;
37
+ }
30
38
  const req = (url.protocol === 'https:' ? https : http).request(options, (response) => {
31
39
  let contentBuffers = [];
32
40
  response.on('data', (chunk) => {
@@ -1,3 +1,16 @@
1
+ /// <reference types="node" />
2
+ /// <reference types="node" />
3
+ import http from 'http';
4
+ import https from 'https';
1
5
  import type { Requester } from '@algolia/client-common';
2
- export declare function createHttpRequester(): Requester;
6
+ export declare type CreateHttpRequesterOptions = Partial<{
7
+ agent: http.Agent | https.Agent;
8
+ httpAgent: http.Agent;
9
+ httpsAgent: https.Agent;
10
+ /**
11
+ * RequestOptions to be merged with the end request, it will override default options if provided.
12
+ */
13
+ requesterOptions: https.RequestOptions;
14
+ }>;
15
+ export declare function createHttpRequester({ agent: userGlobalAgent, httpAgent: userHttpAgent, httpsAgent: userHttpsAgent, requesterOptions, }?: CreateHttpRequesterOptions): Requester;
3
16
  //# sourceMappingURL=createHttpRequester.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"createHttpRequester.d.ts","sourceRoot":"","sources":["../../../../packages/requester-node-http/src/createHttpRequester.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAc,SAAS,EAAY,MAAM,wBAAwB,CAAC;AAO9E,wBAAgB,mBAAmB,IAAI,SAAS,CAmF/C"}
1
+ {"version":3,"file":"createHttpRequester.d.ts","sourceRoot":"","sources":["../../src/createHttpRequester.ts"],"names":[],"mappings":";;AAAA,OAAO,IAAI,MAAM,MAAM,CAAC;AACxB,OAAO,KAAK,MAAM,OAAO,CAAC;AAG1B,OAAO,KAAK,EAAc,SAAS,EAAY,MAAM,wBAAwB,CAAC;AAE9E,oBAAY,0BAA0B,GAAG,OAAO,CAAC;IAC/C,KAAK,EAAE,IAAI,CAAC,KAAK,GAAG,KAAK,CAAC,KAAK,CAAC;IAChC,SAAS,EAAE,IAAI,CAAC,KAAK,CAAC;IACtB,UAAU,EAAE,KAAK,CAAC,KAAK,CAAC;IACxB;;OAEG;IACH,gBAAgB,EAAE,KAAK,CAAC,cAAc,CAAC;CACxC,CAAC,CAAC;AAOH,wBAAgB,mBAAmB,CAAC,EAClC,KAAK,EAAE,eAAe,EACtB,SAAS,EAAE,aAAa,EACxB,UAAU,EAAE,cAAc,EAC1B,gBAAqB,GACtB,GAAE,0BAA+B,GAAG,SAAS,CA6F7C"}
@@ -1 +1 @@
1
- {"version":3,"file":"echoRequester.d.ts","sourceRoot":"","sources":["../../../../packages/requester-node-http/src/echoRequester.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,wBAAwB,CAAC;AAExD,wBAAgB,aAAa,CAAC,MAAM,GAAE,MAAY,GAAG,SAAS,CAE7D"}
1
+ {"version":3,"file":"echoRequester.d.ts","sourceRoot":"","sources":["../../src/echoRequester.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,wBAAwB,CAAC;AAExD,wBAAgB,aAAa,CAAC,MAAM,GAAE,MAAY,GAAG,SAAS,CAE7D"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@algolia/requester-node-http",
3
- "version": "5.0.0-alpha.1",
3
+ "version": "5.0.0-alpha.12",
4
4
  "description": "Promise-based request library for node using the native http module.",
5
5
  "repository": "algolia/algoliasearch-client-javascript",
6
6
  "license": "MIT",
@@ -14,18 +14,19 @@
14
14
  "index.ts"
15
15
  ],
16
16
  "scripts": {
17
- "clean": "rm -rf dist/",
17
+ "build": "yarn clean && rollup --config",
18
+ "clean": "rm -rf ./dist || true",
18
19
  "test": "jest"
19
20
  },
20
21
  "dependencies": {
21
- "@algolia/client-common": "5.0.0-alpha.1"
22
+ "@algolia/client-common": "5.0.0-alpha.12"
22
23
  },
23
24
  "devDependencies": {
24
- "@types/jest": "28.1.6",
25
- "@types/node": "16.11.45",
25
+ "@types/jest": "28.1.7",
26
+ "@types/node": "16.11.47",
26
27
  "jest": "28.1.3",
27
28
  "nock": "13.2.9",
28
- "ts-jest": "28.0.5",
29
+ "ts-jest": "28.0.8",
29
30
  "typescript": "4.7.4"
30
31
  },
31
32
  "engines": {
@@ -1,4 +1,5 @@
1
- import type http from 'http';
1
+ import http from 'http';
2
+ import https from 'https';
2
3
  import { Readable } from 'stream';
3
4
 
4
5
  import type { EndRequest } from '@algolia/client-common';
@@ -17,6 +18,72 @@ import {
17
18
 
18
19
  const requester = createHttpRequester();
19
20
 
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
+
20
87
  describe('status code handling', () => {
21
88
  it('sends requests', async () => {
22
89
  const body = getStringifiedBody();
@@ -125,8 +192,8 @@ describe('timeout handling', () => {
125
192
  const now = Date.now();
126
193
 
127
194
  expect(response.content).toBe('Connection timeout');
128
- expect(now - before).toBeGreaterThan(999);
129
- expect(now - before).toBeLessThan(1200);
195
+ expect(now - before).toBeGreaterThanOrEqual(999);
196
+ expect(now - before).toBeLessThanOrEqual(1200);
130
197
  });
131
198
 
132
199
  it('connection timeouts with the given 2 seconds connection timeout', async () => {
@@ -140,8 +207,8 @@ describe('timeout handling', () => {
140
207
  const now = Date.now();
141
208
 
142
209
  expect(response.content).toBe('Connection timeout');
143
- expect(now - before).toBeGreaterThan(1999);
144
- expect(now - before).toBeLessThan(2200);
210
+ expect(now - before).toBeGreaterThanOrEqual(1999);
211
+ expect(now - before).toBeLessThanOrEqual(2200);
145
212
  });
146
213
 
147
214
  it("socket timeouts if response don't appears before the timeout with 2 seconds timeout", async () => {
@@ -156,8 +223,8 @@ describe('timeout handling', () => {
156
223
  const now = Date.now();
157
224
 
158
225
  expect(response.content).toBe('Socket timeout');
159
- expect(now - before).toBeGreaterThan(1999);
160
- expect(now - before).toBeLessThan(2200);
226
+ expect(now - before).toBeGreaterThanOrEqual(1999);
227
+ expect(now - before).toBeLessThanOrEqual(2200);
161
228
  });
162
229
 
163
230
  it("socket timeouts if response don't appears before the timeout with 3 seconds timeout", async () => {
@@ -171,8 +238,8 @@ describe('timeout handling', () => {
171
238
  const now = Date.now();
172
239
 
173
240
  expect(response.content).toBe('Socket timeout');
174
- expect(now - before).toBeGreaterThan(2999);
175
- expect(now - before).toBeLessThan(3200);
241
+ expect(now - before).toBeGreaterThanOrEqual(2999);
242
+ expect(now - before).toBeLessThanOrEqual(3200);
176
243
  });
177
244
 
178
245
  it('do not timeouts if response appears before the timeout', async () => {
@@ -188,8 +255,8 @@ describe('timeout handling', () => {
188
255
  expect(response.isTimedOut).toBe(false);
189
256
  expect(response.status).toBe(200);
190
257
  expect(response.content).toBe('{"foo": "bar"}');
191
- expect(now - before).toBeGreaterThan(4999);
192
- expect(now - before).toBeLessThan(5200);
258
+ expect(now - before).toBeGreaterThanOrEqual(4999);
259
+ expect(now - before).toBeLessThanOrEqual(5200);
193
260
  }, 10000); // This is a long-running test, default server timeout is set to 5000ms
194
261
  });
195
262
 
@@ -4,12 +4,30 @@ import { URL } from 'url';
4
4
 
5
5
  import type { EndRequest, Requester, Response } from '@algolia/client-common';
6
6
 
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
+
7
17
  // Global agents allow us to reuse the TCP protocol with multiple clients
8
18
  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;
11
30
 
12
- export function createHttpRequester(): Requester {
13
31
  function send(request: EndRequest): Promise<Response> {
14
32
  return new Promise((resolve) => {
15
33
  let responseTimeout: NodeJS.Timeout | undefined;
@@ -23,10 +41,17 @@ export function createHttpRequester(): Requester {
23
41
  hostname: url.hostname,
24
42
  path,
25
43
  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
+ },
28
49
  };
29
50
 
51
+ if (url.port && !requesterOptions.port) {
52
+ options.port = url.port;
53
+ }
54
+
30
55
  const req = (url.protocol === 'https:' ? https : http).request(
31
56
  options,
32
57
  (response) => {