Skip to content

Commit

Permalink
Feature/add override ipaddres configuration option (#1070)
Browse files Browse the repository at this point in the history
* feature: add option to override ip address in request headers (when recording in docker containers)

* chore: update dependencies

* ci: update node version to 21
  • Loading branch information
mdasberg authored Apr 5, 2024
1 parent 3fc6460 commit 1506a3d
Show file tree
Hide file tree
Showing 13 changed files with 3,517 additions and 3,238 deletions.
1 change: 1 addition & 0 deletions .eslintrc
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@
140
],
"no-console": "off",
"no-empty-function": "off",
"no-multi-assign": "off",
"no-param-reassign": "off",
"no-prototype-builtins": "off",
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ jobs:
fail-fast: true
matrix:
node_version:
- 18
- 21
os:
- ubuntu-latest
- macOS-latest
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/qa.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ jobs:
fetch-depth: 0
- uses: actions/setup-node@v3
with:
node-version: 18
node-version: 21
registry-url: https://registry.npmjs.org
- name: install
run: yarn install --frozen-lockfile
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ jobs:
- uses: actions/checkout@v3
- uses: actions/setup-node@v3
with:
node-version: 18
node-version: 21
registry-url: https://registry.npmjs.org
- name: install
run: yarn install --frozen-lockfile
Expand Down
4 changes: 0 additions & 4 deletions .husky/pre-commit

This file was deleted.

69 changes: 34 additions & 35 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -33,51 +33,50 @@
"api"
],
"devDependencies": {
"@commitlint/cli": "17.4.4",
"@commitlint/config-conventional": "17.4.4",
"@semantic-release/changelog": "6.0.2",
"@semantic-release/commit-analyzer": "9.0.2",
"@commitlint/cli": "19.2.1",
"@commitlint/config-conventional": "19.1.0",
"@semantic-release/changelog": "6.0.3",
"@semantic-release/commit-analyzer": "12.0.0",
"@semantic-release/git": "10.0.1",
"@semantic-release/github": "8.0.7",
"@semantic-release/npm": "9.0.2",
"@semantic-release/release-notes-generator": "10.0.3",
"@types/body-parser": "1.19.2",
"@types/chokidar": "2.1.3",
"@types/debug": "4.1.7",
"@types/fs-extra": "11.0.1",
"@semantic-release/github": "10.0.2",
"@semantic-release/npm": "12.0.0",
"@semantic-release/release-notes-generator": "13.0.0",
"@types/body-parser": "1.19.5",
"@types/debug": "4.1.12",
"@types/fs-extra": "11.0.4",
"@types/glob": "8.1.0",
"@types/jest": "29.5.0",
"@types/node": "18.15.5",
"@types/node-fetch": "2.6.2",
"@types/url-join": "4.0.1",
"@types/uuid": "9.0.1",
"@typescript-eslint/eslint-plugin": "5.56.0",
"@typescript-eslint/parser": "5.56.0",
"@types/jest": "29.5.12",
"@types/node": "20.12.4",
"@types/node-fetch": "2.6.11",
"@types/url-join": "4.0.3",
"@types/uuid": "9.0.8",
"@typescript-eslint/eslint-plugin": "7.5.0",
"@typescript-eslint/parser": "7.5.0",
"commitizen": "4.3.0",
"eslint": "8.36.0",
"eslint": "8.57.0",
"eslint-config-airbnb-base": "15.0.0",
"eslint-plugin-import": "2.27.5",
"eslint-plugin-jest": "27.2.1",
"husky": "8.0.3",
"jest": "29.5.0",
"eslint-plugin-import": "2.29.1",
"eslint-plugin-jest": "27.9.0",
"husky": "9.0.11",
"jest": "29.7.0",
"jest-createspyobj": "2.0.0",
"jest-fetch-mock": "3.0.3",
"lint-staged": "13.2.0",
"rimraf": "4.4.0",
"semantic-release": "20.1.3",
"ts-jest": "29.0.5",
"typescript": "4.9.5"
"lint-staged": "15.2.2",
"rimraf": "5.0.5",
"semantic-release": "23.0.7",
"ts-jest": "29.1.2",
"typescript": "5.4.4"
},
"dependencies": {
"body-parser": "1.20.2",
"chokidar": "3.5.3",
"chokidar": "3.6.0",
"debug": "4.3.4",
"fs-extra": "11.1.1",
"glob": "8.1.0",
"inversify": "6.0.1",
"node-fetch": "2.6.9",
"reflect-metadata": "0.1.13",
"uuid": "9.0.0"
"fs-extra": "11.2.0",
"glob": "10.3.12",
"inversify": "6.0.2",
"node-fetch": "2.7.0",
"reflect-metadata": "0.2.2",
"uuid": "9.0.1"
},
"lint-staged": {
"**/**.{ts}": [
Expand Down
4 changes: 3 additions & 1 deletion src/core/configuration.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ export interface MiddlewareConfiguration {
basePath: string;
identifier: string;
useHeader: boolean;
ipAddress: string;
}

export interface Configuration {
Expand All @@ -12,6 +13,7 @@ export const DefaultConfiguration: Configuration = {
middleware: {
basePath: '/ngapimock',
identifier: 'apimockid',
useHeader: false
useHeader: false,
ipAddress: undefined
}
};
2 changes: 1 addition & 1 deletion src/core/convert.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ describe('Converter', () => {
debugFn = jest.spyOn(process.stderr, 'write');
fsReadJsonSyncFn = fs.readJsonSync as jest.Mock;
fsOutputJsonSyncFn = fs.outputJsonSync as jest.Mock;
globSyncFn = glob.sync as jest.Mock;
globSyncFn = glob.sync as unknown as jest.Mock;

globSyncFn.mockReturnValue(['mock/old.mock.json', 'mock/new.mock.json']);
fsReadJsonSyncFn.mockReturnValueOnce({
Expand Down
86 changes: 86 additions & 0 deletions src/core/middleware/handlers/mock/record.response.handler.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,92 @@ describe('RecordResponseHandler', () => {
});
});

describe('with ipAddress configured', () => {
beforeEach(() => {
container.rebind('Configuration').toConstantValue({ middleware: { basePath: '/base-path', ipAddress: 'some-ip' } });

recordResponseHandler = container.get<RecordResponseHandler>('RecordResponseHandler');
recordFn = jest.spyOn(recordResponseHandler, 'record');
fetchResponseFn = jest.spyOn(recordResponseHandler, 'fetchResponse');

fetchResponseFn.mockResolvedValue({
buffer: responseBufferFn, headers: { raw: responseHeadersRawFn }, status: 200
});
});

describe('method GET', () => {
beforeEach(() => {
request.method = HttpMethods.GET;

recordResponseHandler.handle(request, response as any, nextFn, {
id: 'apimockId',
mock: { name: 'some' } as Mock,
body: JSON.stringify({ x: 'x' })
});
});

it('sets the record header to true', () => expect(request.headers.record).toBe('true'));

it('calls the api without body', async () => {
expect(fetchResponseFn).toHaveBeenCalled();
const actualRequest = fetchResponseFn.mock.calls[0][0];
expect(actualRequest.url).toBe('http://some-ip:8888/some/api');
expect(actualRequest.method).toBe(HttpMethods.GET);
expect(actualRequest.body).toEqual(null);
expect(actualRequest.headers.get('host')).toBe('localhost:8888');
expect(actualRequest.headers.get('record')).toBe('true');
});
});

describe('method HEAD', () => {
beforeEach(() => {
request.method = HttpMethods.HEAD;

recordResponseHandler.handle(request, response as any, nextFn, {
id: 'apimockId',
mock: { name: 'some' } as Mock,
body: JSON.stringify({ x: 'x' })
});
});

it('sets the record header to true', () => expect(request.headers.record).toBe('true'));

it('calls the api without body', async () => {
expect(fetchResponseFn).toHaveBeenCalled();
const actualRequest = fetchResponseFn.mock.calls[0][0];
expect(actualRequest.url).toBe('http://some-ip:8888/some/api');
expect(actualRequest.method).toBe(HttpMethods.HEAD);
expect(actualRequest.body).toEqual(null);
expect(actualRequest.headers.get('host')).toBe('localhost:8888');
expect(actualRequest.headers.get('record')).toBe('true');
});
});

describe('method OTHER', () => {
beforeEach(() => {
request.method = HttpMethods.POST;

recordResponseHandler.handle(request, response as any, nextFn, {
id: 'apimockId',
mock: { name: 'some' } as Mock,
body: { x: 'x' }
});
});

it('sets the record header to true', () => expect(request.headers.record).toBe('true'));

it('calls the api without body', async () => {
expect(fetchResponseFn).toHaveBeenCalled();
const actualRequest = fetchResponseFn.mock.calls[0][0];
expect(actualRequest.url).toBe('http://some-ip:8888/some/api');
expect(actualRequest.method).toBe(HttpMethods.POST);
expect(actualRequest.body).not.toEqual(null);
expect(actualRequest.headers.get('host')).toBe('localhost:8888');
expect(actualRequest.headers.get('record')).toBe('true');
});
});
});

describe('on successful api call', () => {
beforeEach(async () => {
responseHeadersGetFn.mockReturnValue('application/pdf');
Expand Down
3 changes: 2 additions & 1 deletion src/core/middleware/handlers/mock/record.response.handler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ export class RecordResponseHandler implements Handler {
async handle(request: http.IncomingMessage, response: http.ServerResponse, next: Function, params: { id: string, mock: Mock, body: any }): Promise<any> {
const { method } = request;
const { headers } = request;
const ipAddress = this.configuration.middleware.ipAddress !== undefined ? headers.host.replace('localhost', this.configuration.middleware.ipAddress) : headers.host;

headers.record = 'true';

Expand All @@ -46,7 +47,7 @@ export class RecordResponseHandler implements Handler {
}

try {
const res = await this.fetchResponse(new Request(`http://${headers.host}${request.url}`, requestInit));
const res = await this.fetchResponse(new Request(`http://${ipAddress}${request.url}`, requestInit));
const responseData = await res.buffer();
const responseHeaders = await res.headers.raw();
const responseStatusCode = res.status;
Expand Down
2 changes: 1 addition & 1 deletion src/core/processor/mocks.processor.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ describe('MocksProcessor', () => {
debug.enable('ng-apimock:processor-mock');
debugFn = jest.spyOn(process.stderr, 'write');
loadFileFn = fileLoader.loadFile as jest.Mock;
globSyncFn = glob.sync as jest.Mock;
globSyncFn = glob.sync as unknown as jest.Mock;

(state as any).mocks = [];
(state as any).defaults = {};
Expand Down
2 changes: 1 addition & 1 deletion src/core/processor/presets.processor.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ describe('PresetsProcessor', () => {
debug.enable('ng-apimock:processor-preset');
debugFn = jest.spyOn(process.stderr, 'write');
loadFileFn = fileLoader.loadFile as jest.Mock;
globSyncFn = glob.sync as jest.Mock;
globSyncFn = glob.sync as unknown as jest.Mock;

(state as any).presets = [];
globSyncFn.mockReturnValue([
Expand Down
Loading

0 comments on commit 1506a3d

Please sign in to comment.