Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 13 additions & 2 deletions src/lib/contentstack-core.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,26 @@ import axios, { AxiosRequestHeaders, getAdapter } from 'axios';
import { AxiosInstance, HttpClientParams } from './types';
import { ERROR_MESSAGES } from './error-messages';

const isNodeEnvironment = typeof window === 'undefined';

// Guarded require: keeps 'http'/'https' out of browser bundles, which have no browser field of their own to redirect this.
function createKeepAliveAgent(moduleName: 'http' | 'https') {
if (!isNodeEnvironment) {
return false as const;
}

return new (require(moduleName).Agent)({ keepAlive: true });
}

export function httpClient(options: HttpClientParams): AxiosInstance {
const defaultConfig = {
insecure: false,
retryOnError: true,
headers: {} as AxiosRequestHeaders,
basePath: '',
proxy: false as const,
httpAgent: false,
httpsAgent: false,
httpAgent: createKeepAliveAgent('http'),
httpsAgent: createKeepAliveAgent('https'),
timeout: 30000,
logHandler: (level: string, data?: any) => {
if (level === 'error') {
Expand Down
22 changes: 22 additions & 0 deletions test/contentstack-core.node-agent.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
/**
* @jest-environment node
*/
import http from 'http';
import https from 'https';
import { httpClient } from '../src/lib/contentstack-core';

describe('httpClient default connection agents (Node environment)', () => {
it('should default httpAgent to a keepAlive http.Agent when not explicitly provided', () => {
const instance = httpClient({});

expect(instance.defaults.httpAgent).toBeInstanceOf(http.Agent);
expect((instance.defaults.httpAgent as any).keepAlive).toBe(true);
});

it('should default httpsAgent to a keepAlive https.Agent when not explicitly provided', () => {
const instance = httpClient({});

expect(instance.defaults.httpsAgent).toBeInstanceOf(https.Agent);
expect((instance.defaults.httpsAgent as any).keepAlive).toBe(true);
});
});
23 changes: 23 additions & 0 deletions test/contentstack-core.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,29 @@ describe('contentstackCore', () => {
});
});

describe('connection agents', () => {
it.each(['httpAgent', 'httpsAgent'])(
'should preserve an explicitly provided %s instead of defaulting it',
(agentOption) => {
const customAgent = { custom: true };
const options = { [agentOption]: customAgent };

const instance = httpClient(options as any);

expect((instance.defaults as any)[agentOption]).toEqual(customAgent);
}
);

it.each(['httpAgent', 'httpsAgent'])('should default %s to false in a browser-like environment', (agentOption) => {
// This spec file runs under jsdom (see jest.preset.js), so `window` is
// already defined here - matching a real browser, unlike the Node-only
// agent behavior covered in contentstack-core.node-agent.spec.ts.
const instance = httpClient({});

expect((instance.defaults as any)[agentOption]).toBe(false);
});
});

describe('config.headers', () => {
it('should include apiKey in headers when provided', () => {
const options = {
Expand Down
Loading