From 891376772b56e5859f1b2870bb9feb916b7b90c4 Mon Sep 17 00:00:00 2001 From: Florian Rappl Date: Fri, 24 Jul 2020 08:44:27 +0200 Subject: [PATCH] Updated documentation and CHANGELOG --- CHANGELOG.md | 4 ++++ docs/proxy-injector.md | 26 +++++++++++++++++++++ package.json | 2 +- src/server/helpers/proxy-request.ts | 19 +++++++++++++++- src/server/injectors/proxy-injector.ts | 31 +++++++++++++++----------- 5 files changed, 67 insertions(+), 15 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2fbeb5e..8ea072f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,9 @@ # Changelog +## 0.11.1 + +- Added options for proxy headers + ## 0.11.0 - Updated dependencies diff --git a/docs/proxy-injector.md b/docs/proxy-injector.md index 0f5e4e1..4f38ab1 100644 --- a/docs/proxy-injector.md +++ b/docs/proxy-injector.md @@ -20,7 +20,33 @@ interface ProxyInjectorConfiguration { active?: boolean; agentOptions?: any; proxy?: any; + defaultHeaders?: Array; + discardHeaders?: Array; + permitHeaders?: Array; + followRedirect?: boolean; } ``` The mapping is already a general configuration, as the targets need to be known as well as their usual counterparts (e.g., to identify the correct URLs in an HAR file). The `agentOptions` can be used to specify more sophisticated options for the proxyed request (e.g., which ciphers to use). The `proxy` option allows us to set a (corporate?) proxy to be used on the local machine (oh the irony - a proxy server that allows setting another proxy ...). + +While the `defaultHeaders` provide a way to override the used default set of headers, `permitHeaders` are for explicitly allowing non-default headers and `discardHeaders` may be used to define which headers should never be considered. + +If not explicitly specified the default headers are defined to be: + +```js +const defaultProxyHeaders = [ + 'authorization', + 'accept', + 'content-type', + 'cookie', + 'accept-language', + 'user-agent', + 'if-match', + 'if-range', + 'if-unmodified-since', + 'if-none-match', + 'if-modified-since', + 'pragma', + 'range', +]; +``` diff --git a/package.json b/package.json index 11a118d..4b811b9 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "kras", - "version": "0.11.0", + "version": "0.11.1", "description": "Efficient server proxying and mocking in Node.js.", "main": "dist/server/index.js", "types": "dist/server/index.d.ts", diff --git a/src/server/helpers/proxy-request.ts b/src/server/helpers/proxy-request.ts index 101884a..3bf1ad9 100644 --- a/src/server/helpers/proxy-request.ts +++ b/src/server/helpers/proxy-request.ts @@ -2,6 +2,22 @@ import * as request from 'request'; import { fromNode } from './build-response'; import { KrasInjectorInfo } from '../types'; +export const defaultProxyHeaders = [ + 'authorization', + 'accept', + 'content-type', + 'cookie', + 'accept-language', + 'user-agent', + 'if-match', + 'if-range', + 'if-unmodified-since', + 'if-none-match', + 'if-modified-since', + 'pragma', + 'range', +]; + export interface ProxyCallback { (err?: Error, foo?: any): void; } @@ -14,6 +30,7 @@ export interface ProxyRequestOptions { agentOptions?: any; proxy?: any; injector?: KrasInjectorInfo; + redirect?: boolean; } export function proxyRequest(req: ProxyRequestOptions, callback: ProxyCallback) { @@ -28,7 +45,7 @@ export function proxyRequest(req: ProxyRequestOptions, callback: ProxyCallback) agentOptions: req.agentOptions, headers: req.headers, body: req.body, - followRedirect: req.followRedirect || true, + followRedirect: req.redirect ?? true, }, (err, ans, body) => { if (err) { diff --git a/src/server/injectors/proxy-injector.ts b/src/server/injectors/proxy-injector.ts index e91755a..c5e144e 100644 --- a/src/server/injectors/proxy-injector.ts +++ b/src/server/injectors/proxy-injector.ts @@ -1,6 +1,6 @@ import * as WebSocket from 'ws'; import { EventEmitter } from 'events'; -import { proxyRequest } from '../helpers'; +import { proxyRequest, defaultProxyHeaders } from '../helpers'; import { KrasInjector, KrasAnswer, @@ -13,12 +13,20 @@ import { export interface ProxyInjectorConfig { agentOptions?: any; proxy?: any; + defaultHeaders?: Array; + discardHeaders?: Array; + permitHeaders?: Array; + followRedirect?: boolean; } export interface DynamicProxyInjectorConfig { [target: string]: string; } +function normalizeHeader(header: string) { + return header.toLowerCase(); +} + interface WebSocketSessions { [id: string]: WebSocket; } @@ -145,24 +153,21 @@ export default class ProxyInjector implements KrasInjector { } handle(req: KrasRequest): Promise | KrasAnswer { - const defaultHeaders = this.config.defaultHeaders || ["authorization", "accept", "content-type", "cookie", "accept-language", "user-agent", "if-match", "if-range", "if-unmodified-since", "if-none-match", "if-modified-since", "pragma", "range"]; - const discardHeaders = this.config.discardHeaders || []; - const permitHeaders = this.config.permitHeaders || []; - const allowHeaders = [...defaultHeaders.filter(header => !discardHeaders.includes(header.toLowerCase())), ...permitHeaders]; - const headers = allowHeaders.reduce((headers, header) => { - header = header.toLowerCase(); - if(req.headers[header]){ - headers[header] = req.headers[header]; - } + const defaultHeaders = (this.config.defaultHeaders || defaultProxyHeaders).map(normalizeHeader); + const discardHeaders = (this.config.discardHeaders || []).map(normalizeHeader); + const permitHeaders = (this.config.permitHeaders || []).map(normalizeHeader); + const headerNames = [...defaultHeaders.filter(header => !discardHeaders.includes(header)), ...permitHeaders]; + const headers = headerNames.reduce((headers, header) => { + headers[header] = req.headers[header]; return headers; - }, {}); + }, {} as Record>); const [target] = this.connectors.filter(m => m.target === req.target); if (target) { return new Promise(resolve => proxyRequest( { - headers: headers, + headers, url: target.address + req.url, method: req.method, body: req.content, @@ -172,7 +177,7 @@ export default class ProxyInjector implements KrasInjector { name: this.name, host: target, }, - followRedirect: req.config.followRedirect || true, + redirect: this.config.followRedirect, }, (err, ans) => { if (err) {