http-proxy-middleware
Advanced tools
Comparing version 0.19.0 to 0.19.1
# Changelog | ||
## [v0.19.1](https://github.com/chimurai/http-proxy-middleware/releases/tag/v0.19.1) | ||
- fix(log): handle case when error code is missing ([#303](https://github.com/chimurai/http-proxy-middleware/pull/303)) | ||
## [v0.19.0](https://github.com/chimurai/http-proxy-middleware/releases/tag/v0.19.0) | ||
- feat(http-proxy): bump to v1.17.0 ([#261](https://github.com/chimurai/http-proxy-middleware/pull/261)) | ||
## [v0.18.0](https://github.com/chimurai/http-proxy-middleware/releases/tag/v0.18.0) | ||
- fix(vulnerability): update micromatch to v3.x ([npm:braces:20180219](https://snyk.io/test/npm/http-proxy-middleware?tab=issues&severity=high&severity=medium&severity=low#npm:braces:20180219 | ||
)) | ||
- fix(vulnerability): update micromatch to v3.x ([npm:braces:20180219](https://snyk.io/test/npm/http-proxy-middleware?tab=issues&severity=high&severity=medium&severity=low#npm:braces:20180219)) | ||
- test(node): drop node 0.x support ([#212](https://github.com/chimurai/http-proxy-middleware/pull/212)) | ||
## [v0.17.4](https://github.com/chimurai/http-proxy-middleware/releases/tag/v0.17.4) | ||
## [v0.17.4](https://github.com/chimurai/http-proxy-middleware/releases/tag/v0.17.4) | ||
- fix(ntlm authentication): fixed bug preventing proxying with ntlm authentication. ([#132](https://github.com/chimurai/http-proxy-middleware/pull/149)) (Thanks: [EladBezalel](https://github.com/EladBezalel), [oshri551](https://github.com/oshri551)) | ||
## [v0.17.3](https://github.com/chimurai/http-proxy-middleware/releases/tag/v0.17.3) | ||
## [v0.17.3](https://github.com/chimurai/http-proxy-middleware/releases/tag/v0.17.3) | ||
- fix(onError): improve default proxy error handling. http status codes (504, 502 and 500). ([#132](https://github.com/chimurai/http-proxy-middleware/pull/132)) ([graingert](https://github.com/graingert)) | ||
## [v0.17.2](https://github.com/chimurai/http-proxy-middleware/releases/tag/v0.17.2) | ||
- feat(logging): improve error message & add link to Node errors page. ([#106](https://github.com/chimurai/http-proxy-middleware/pull/106)) ([cloudmu](https://github.com/cloudmu)) | ||
@@ -26,8 +32,11 @@ - feat(pathRewrite): path can be empty string. ([#110](https://github.com/chimurai/http-proxy-middleware/pull/110)) ([sunnylqm](https://github.com/sunnylqm)) | ||
## [v0.17.1](https://github.com/chimurai/http-proxy-middleware/releases/tag/v0.17.1) | ||
- fix(Express sub Router): 404 on non-proxy routes ([#94](https://github.com/chimurai/http-proxy-middleware/issues/94)) | ||
- fix(Express sub Router): 404 on non-proxy routes ([#94](https://github.com/chimurai/http-proxy-middleware/issues/94)) | ||
## [v0.17.0](https://github.com/chimurai/http-proxy-middleware/releases/tag/v0.17.0) | ||
- fix(context matching): Use [RFC 3986 path](https://tools.ietf.org/html/rfc3986#section-3.3) in context matching. (excludes query parameters) | ||
## [v0.16.0](https://github.com/chimurai/http-proxy-middleware/releases/tag/v0.16.0) | ||
- deprecated(proxyTable): renamed `proxyTable` to `router`. | ||
@@ -37,5 +46,7 @@ - feat(router): support for custom `router` function. | ||
## [v0.15.2](https://github.com/chimurai/http-proxy-middleware/releases/tag/v0.15.2) | ||
- fix(websocket): fixes websocket upgrade. | ||
## [v0.15.1](https://github.com/chimurai/http-proxy-middleware/releases/tag/v0.15.1) | ||
- feat(pathRewrite): expose `req` object to pathRewrite function. | ||
@@ -45,5 +56,7 @@ - fix(websocket): fixes websocket upgrade when both config.ws and external .upgrade() are used. | ||
## [v0.15.0](https://github.com/chimurai/http-proxy-middleware/releases/tag/v0.15.0) | ||
- feat(pathRewrite): support for custom pathRewrite function. | ||
## [v0.14.0](https://github.com/chimurai/http-proxy-middleware/releases/tag/v0.14.0) | ||
- feat(proxy): support proxy creation without context. | ||
@@ -53,5 +66,7 @@ - fix(connect mounting): use connect's `path` configuration to mount proxy. | ||
## [v0.13.0](https://github.com/chimurai/http-proxy-middleware/releases/tag/v0.13.0) | ||
- feat(context): custom context matcher; when simple `path` matching is not sufficient. | ||
## [v0.12.0](https://github.com/chimurai/http-proxy-middleware/releases/tag/v0.12.0) | ||
- add option `onProxyReqWs` (subscribe to http-proxy `proxyReqWs` event) | ||
@@ -62,5 +77,7 @@ - add option `onOpen` (subscribe to http-proxy `open` event) | ||
## [v0.11.0](https://github.com/chimurai/http-proxy-middleware/releases/tag/v0.11.0) | ||
- improved logging | ||
## [v0.10.0](https://github.com/chimurai/http-proxy-middleware/releases/tag/v0.10.0) | ||
- feat(proxyTable) - added proxyTable support for WebSockets. | ||
@@ -70,5 +87,7 @@ - fixed(proxyTable) - ensure original path (not rewritten path) is being used when `proxyTable` is used in conjunction with `pathRewrite`. | ||
## [v0.9.1](https://github.com/chimurai/http-proxy-middleware/releases/tag/v0.9.1) | ||
- fix server crash when socket error not handled correctly. | ||
## [v0.9.0](https://github.com/chimurai/http-proxy-middleware/releases/tag/v0.9.0) | ||
- support subscribing to http-proxy `proxyReq` event ([trbngr](https://github.com/trbngr)) | ||
@@ -78,8 +97,11 @@ - add `logLevel` and `logProvider` support | ||
## [v0.8.2](https://github.com/chimurai/http-proxy-middleware/releases/tag/v0.8.2) | ||
- fix proxyError handler ([mTazelaar](https://github.com/mTazelaar)) | ||
## [v0.8.1](https://github.com/chimurai/http-proxy-middleware/releases/tag/v0.8.1) | ||
- fix pathRewrite when `agent` is configured | ||
## [v0.8.0](https://github.com/chimurai/http-proxy-middleware/releases/tag/v0.8.0) | ||
- support external websocket upgrade | ||
@@ -89,2 +111,3 @@ - fix websocket shorthand | ||
## [v0.7.0](https://github.com/chimurai/http-proxy-middleware/releases/tag/v0.7.0) | ||
- support shorthand syntax | ||
@@ -94,5 +117,7 @@ - fix express/connect mounting | ||
## [v0.6.0](https://github.com/chimurai/http-proxy-middleware/releases/tag/v0.6.0) | ||
- support proxyTable | ||
## [v0.5.0](https://github.com/chimurai/http-proxy-middleware/releases/tag/v0.5.0) | ||
- support subscribing to http-proxy `error` event | ||
@@ -102,11 +127,15 @@ - support subscribing to http-proxy `proxyRes` event | ||
## [v0.4.0](https://github.com/chimurai/http-proxy-middleware/releases/tag/v0.4.0) | ||
- support websocket | ||
## [v0.3.0](https://github.com/chimurai/http-proxy-middleware/releases/tag/v0.3.0) | ||
- support wildcard / glob | ||
## [v0.2.0](https://github.com/chimurai/http-proxy-middleware/releases/tag/v0.2.0) | ||
- support multiple paths | ||
## [v0.1.0](https://github.com/chimurai/http-proxy-middleware/releases/tag/v0.1.0) | ||
- support path rewrite | ||
@@ -116,2 +145,3 @@ - deprecate proxyHost option | ||
## [v0.0.5](https://github.com/chimurai/http-proxy-middleware/releases/tag/v0.0.5) | ||
- initial release |
var HPM = require('./lib') | ||
module.exports = function (context, opts) { | ||
module.exports = function(context, opts) { | ||
return new HPM(context, opts) | ||
} |
@@ -10,3 +10,3 @@ var _ = require('lodash') | ||
function createConfig (context, opts) { | ||
function createConfig(context, opts) { | ||
// structure of config object to be returned | ||
@@ -23,4 +23,4 @@ var config = { | ||
// app.use('/api', proxy('http://localhost:9000')); | ||
// app.use(proxy('http://localhost:9000/api')); | ||
// app.use('/api', proxy('http://localhost:9000')); | ||
// app.use(proxy('http://localhost:9000/api')); | ||
} else if (isStringShortHand(context)) { | ||
@@ -36,3 +36,3 @@ var oUrl = url.parse(context) | ||
} | ||
// app.use('/api', proxy({target:'http://localhost:9000'})); | ||
// app.use('/api', proxy({target:'http://localhost:9000'})); | ||
} else { | ||
@@ -69,5 +69,5 @@ config.context = context | ||
*/ | ||
function isStringShortHand (context) { | ||
function isStringShortHand(context) { | ||
if (_.isString(context)) { | ||
return !!(url.parse(context).host) | ||
return !!url.parse(context).host | ||
} | ||
@@ -87,7 +87,7 @@ } | ||
*/ | ||
function isContextless (context, opts) { | ||
return (_.isPlainObject(context) && _.isEmpty(opts)) | ||
function isContextless(context, opts) { | ||
return _.isPlainObject(context) && _.isEmpty(opts) | ||
} | ||
function mapLegacyProxyHostOption (options) { | ||
function mapLegacyProxyHostOption(options) { | ||
// set options.headers.host when option.proxyHost is provided | ||
@@ -97,3 +97,5 @@ if (options.proxyHost) { | ||
logger.warn('[HPM] Deprecated "option.proxyHost"') | ||
logger.warn(' Use "option.changeOrigin" or "option.headers.host" instead') | ||
logger.warn( | ||
' Use "option.changeOrigin" or "option.headers.host" instead' | ||
) | ||
logger.warn(' "option.proxyHost" will be removed in future release.') | ||
@@ -110,3 +112,3 @@ logger.warn('*************************************') | ||
// Warn deprecated proxyTable api usage | ||
function mapLegacyProxyTableOption (options) { | ||
function mapLegacyProxyTableOption(options) { | ||
if (options.proxyTable) { | ||
@@ -126,3 +128,3 @@ logger.warn('*************************************') | ||
function configureLogger (options) { | ||
function configureLogger(options) { | ||
if (options.logLevel) { | ||
@@ -129,0 +131,0 @@ logger.setLevel(options.logLevel) |
@@ -11,3 +11,3 @@ var _ = require('lodash') | ||
function matchContext (context, uri, req) { | ||
function matchContext(context, uri, req) { | ||
// single path | ||
@@ -49,3 +49,3 @@ if (isStringPath(context)) { | ||
*/ | ||
function matchSingleStringPath (context, uri) { | ||
function matchSingleStringPath(context, uri) { | ||
var pathname = getUrlPathName(uri) | ||
@@ -55,9 +55,9 @@ return pathname.indexOf(context) === 0 | ||
function matchSingleGlobPath (pattern, uri) { | ||
function matchSingleGlobPath(pattern, uri) { | ||
var pathname = getUrlPathName(uri) | ||
var matches = micromatch(pathname, pattern) | ||
return matches && (matches.length > 0) | ||
return matches && matches.length > 0 | ||
} | ||
function matchMultiGlobPath (patternList, uri) { | ||
function matchMultiGlobPath(patternList, uri) { | ||
return matchSingleGlobPath(patternList, uri) | ||
@@ -71,3 +71,3 @@ } | ||
*/ | ||
function matchMultiPath (contextList, uri) { | ||
function matchMultiPath(contextList, uri) { | ||
for (var i = 0; i < contextList.length; i++) { | ||
@@ -88,12 +88,12 @@ var context = contextList[i] | ||
*/ | ||
function getUrlPathName (uri) { | ||
function getUrlPathName(uri) { | ||
return uri && url.parse(uri).pathname | ||
} | ||
function isStringPath (context) { | ||
function isStringPath(context) { | ||
return _.isString(context) && !isGlob(context) | ||
} | ||
function isGlobPath (context) { | ||
function isGlobPath(context) { | ||
return isGlob(context) | ||
} |
/* eslint-disable max-len */ | ||
module.exports = { | ||
ERR_CONFIG_FACTORY_TARGET_MISSING: '[HPM] Missing "target" option. Example: {target: "http://www.example.org"}', | ||
ERR_CONTEXT_MATCHER_GENERIC: '[HPM] Invalid context. Expecting something like: "/api" or ["/api", "/ajax"]', | ||
ERR_CONTEXT_MATCHER_INVALID_ARRAY: '[HPM] Invalid context. Expecting something like: ["/api", "/ajax"] or ["/api/**", "!**.html"]', | ||
ERR_PATH_REWRITER_CONFIG: '[HPM] Invalid pathRewrite config. Expecting object with pathRewrite config or a rewrite function' | ||
ERR_CONFIG_FACTORY_TARGET_MISSING: | ||
'[HPM] Missing "target" option. Example: {target: "http://www.example.org"}', | ||
ERR_CONTEXT_MATCHER_GENERIC: | ||
'[HPM] Invalid context. Expecting something like: "/api" or ["/api", "/ajax"]', | ||
ERR_CONTEXT_MATCHER_INVALID_ARRAY: | ||
'[HPM] Invalid context. Expecting something like: ["/api", "/ajax"] or ["/api/**", "!**.html"]', | ||
ERR_PATH_REWRITER_CONFIG: | ||
'[HPM] Invalid pathRewrite config. Expecting object with pathRewrite config or a rewrite function' | ||
} |
@@ -9,6 +9,6 @@ var _ = require('lodash') | ||
function init (proxy, opts) { | ||
function init(proxy, opts) { | ||
var handlers = getProxyEventHandlers(opts) | ||
_.forIn(handlers, function (handler, eventName) { | ||
_.forIn(handlers, function(handler, eventName) { | ||
proxy.on(eventName, handlers[eventName]) | ||
@@ -20,8 +20,15 @@ }) | ||
function getProxyEventHandlers (opts) { | ||
function getProxyEventHandlers(opts) { | ||
// https://github.com/nodejitsu/node-http-proxy#listening-for-proxy-events | ||
var proxyEvents = ['error', 'proxyReq', 'proxyReqWs', 'proxyRes', 'open', 'close'] | ||
var proxyEvents = [ | ||
'error', | ||
'proxyReq', | ||
'proxyReqWs', | ||
'proxyRes', | ||
'open', | ||
'close' | ||
] | ||
var handlers = {} | ||
_.forEach(proxyEvents, function (event) { | ||
_.forEach(proxyEvents, function(event) { | ||
// all handlers for the http-proxy events are prefixed with 'on'. | ||
@@ -51,4 +58,4 @@ // loop through options and try to find these handlers | ||
function defaultErrorHandler (err, req, res) { | ||
var host = (req.headers && req.headers.host) | ||
function defaultErrorHandler(err, req, res) { | ||
var host = req.headers && req.headers.host | ||
var code = err.code | ||
@@ -66,3 +73,4 @@ | ||
break | ||
default: res.writeHead(500) | ||
default: | ||
res.writeHead(500) | ||
} | ||
@@ -75,5 +83,5 @@ } | ||
function logClose (req, socket, head) { | ||
function logClose(req, socket, head) { | ||
// view disconnected websocket connections | ||
logger.info('[HPM] Client disconnected') | ||
} |
@@ -13,3 +13,3 @@ var _ = require('lodash') | ||
function HttpProxyMiddleware (context, opts) { | ||
function HttpProxyMiddleware(context, opts) { | ||
// https://github.com/chimurai/http-proxy-middleware/issues/57 | ||
@@ -23,3 +23,8 @@ var wsUpgradeDebounced = _.debounce(handleUpgrade) | ||
var proxy = httpProxy.createProxyServer({}) | ||
logger.info('[HPM] Proxy created:', config.context, ' -> ', proxyOptions.target) | ||
logger.info( | ||
'[HPM] Proxy created:', | ||
config.context, | ||
' -> ', | ||
proxyOptions.target | ||
) | ||
@@ -40,3 +45,3 @@ var pathRewriter = PathRewriter.create(proxyOptions.pathRewrite) // returns undefined when "pathRewrite" is not provided | ||
function middleware (req, res, next) { | ||
function middleware(req, res, next) { | ||
if (shouldProxy(config.context, req)) { | ||
@@ -55,3 +60,3 @@ var activeProxyOptions = prepareProxyRequest(req) | ||
function catchUpgradeRequest (server) { | ||
function catchUpgradeRequest(server) { | ||
// subscribe once; don't subscribe on every request... | ||
@@ -65,3 +70,3 @@ // https://github.com/chimurai/http-proxy-middleware/issues/113 | ||
function handleUpgrade (req, socket, head) { | ||
function handleUpgrade(req, socket, head) { | ||
// set to initialized when used externally | ||
@@ -85,4 +90,4 @@ wsInitialized = true | ||
*/ | ||
function shouldProxy (context, req) { | ||
var path = (req.originalUrl || req.url) | ||
function shouldProxy(context, req) { | ||
var path = req.originalUrl || req.url | ||
return contextMatcher.match(context, path, req) | ||
@@ -99,6 +104,6 @@ } | ||
*/ | ||
function prepareProxyRequest (req) { | ||
function prepareProxyRequest(req) { | ||
// https://github.com/chimurai/http-proxy-middleware/issues/17 | ||
// https://github.com/chimurai/http-proxy-middleware/issues/94 | ||
req.url = (req.originalUrl || req.url) | ||
req.url = req.originalUrl || req.url | ||
@@ -117,4 +122,15 @@ // store uri before it gets rewritten for logging | ||
if (proxyOptions.logLevel === 'debug') { | ||
var arrow = getArrow(originalPath, req.url, proxyOptions.target, newProxyOptions.target) | ||
logger.debug('[HPM] %s %s %s %s', req.method, originalPath, arrow, newProxyOptions.target) | ||
var arrow = getArrow( | ||
originalPath, | ||
req.url, | ||
proxyOptions.target, | ||
newProxyOptions.target | ||
) | ||
logger.debug( | ||
'[HPM] %s %s %s %s', | ||
req.method, | ||
originalPath, | ||
arrow, | ||
newProxyOptions.target | ||
) | ||
} | ||
@@ -126,3 +142,3 @@ | ||
// Modify option.target when router present. | ||
function __applyRouter (req, options) { | ||
function __applyRouter(req, options) { | ||
var newTarget | ||
@@ -134,3 +150,7 @@ | ||
if (newTarget) { | ||
logger.debug('[HPM] Router new target: %s -> "%s"', options.target, newTarget) | ||
logger.debug( | ||
'[HPM] Router new target: %s -> "%s"', | ||
options.target, | ||
newTarget | ||
) | ||
options.target = newTarget | ||
@@ -142,3 +162,3 @@ } | ||
// rewrite path | ||
function __applyPathRewrite (req, pathRewriter) { | ||
function __applyPathRewrite(req, pathRewriter) { | ||
if (pathRewriter) { | ||
@@ -155,10 +175,20 @@ var path = pathRewriter(req.url, req) | ||
function logError (err, req, res) { | ||
var hostname = (req.headers && req.headers.host) || (req.hostname || req.host) // (websocket) || (node0.10 || node 4/5) | ||
function logError(err, req, res) { | ||
var hostname = | ||
(req.headers && req.headers.host) || (req.hostname || req.host) // (websocket) || (node0.10 || node 4/5) | ||
var target = proxyOptions.target.host || proxyOptions.target | ||
var errorMessage = '[HPM] Error occurred while trying to proxy request %s from %s to %s (%s) (%s)' | ||
var errReference = 'https://nodejs.org/api/errors.html#errors_common_system_errors' // link to Node Common Systems Errors page | ||
var errorMessage = | ||
'[HPM] Error occurred while trying to proxy request %s from %s to %s (%s) (%s)' | ||
var errReference = | ||
'https://nodejs.org/api/errors.html#errors_common_system_errors' // link to Node Common Systems Errors page | ||
logger.error(errorMessage, req.url, hostname, target, err.code, errReference) | ||
logger.error( | ||
errorMessage, | ||
req.url, | ||
hostname, | ||
target, | ||
err.code || err, | ||
errReference | ||
) | ||
} | ||
} |
@@ -25,3 +25,3 @@ var util = require('util') | ||
// singleton | ||
getInstance: function () { | ||
getInstance: function() { | ||
if (!loggerInstance) { | ||
@@ -36,3 +36,3 @@ loggerInstance = new Logger() | ||
function Logger () { | ||
function Logger() { | ||
var logLevel | ||
@@ -47,3 +47,3 @@ var provider | ||
error: error, | ||
setLevel: function (v) { | ||
setLevel: function(v) { | ||
if (isValidLevel(v)) { | ||
@@ -53,3 +53,3 @@ logLevel = v | ||
}, | ||
setProvider: function (fn) { | ||
setProvider: function(fn) { | ||
if (fn && isValidProvider(fn)) { | ||
@@ -65,5 +65,5 @@ provider = fn(defaultProvider) | ||
function init () { | ||
function init() { | ||
api.setLevel('info') | ||
api.setProvider(function () { | ||
api.setProvider(function() { | ||
return defaultProvider | ||
@@ -74,7 +74,7 @@ }) | ||
// log will log messages, regardless of logLevels | ||
function log () { | ||
function log() { | ||
provider.log(_interpolate.apply(null, arguments)) | ||
} | ||
function debug () { | ||
function debug() { | ||
if (_showLevel('debug')) { | ||
@@ -85,3 +85,3 @@ provider.debug(_interpolate.apply(null, arguments)) | ||
function info () { | ||
function info() { | ||
if (_showLevel('info')) { | ||
@@ -92,3 +92,3 @@ provider.info(_interpolate.apply(null, arguments)) | ||
function warn () { | ||
function warn() { | ||
if (_showLevel('warn')) { | ||
@@ -99,3 +99,3 @@ provider.warn(_interpolate.apply(null, arguments)) | ||
function error () { | ||
function error() { | ||
if (_showLevel('error')) { | ||
@@ -111,7 +111,7 @@ provider.error(_interpolate.apply(null, arguments)) | ||
*/ | ||
function _showLevel (showLevel) { | ||
function _showLevel(showLevel) { | ||
var result = false | ||
var currentLogLevel = LEVELS[logLevel] | ||
if (currentLogLevel && (currentLogLevel <= LEVELS[showLevel])) { | ||
if (currentLogLevel && currentLogLevel <= LEVELS[showLevel]) { | ||
result = true | ||
@@ -125,3 +125,3 @@ } | ||
// make it possible for additional log data, such date/time or custom prefix. | ||
function _interpolate () { | ||
function _interpolate() { | ||
var fn = _.spread(util.format) | ||
@@ -133,3 +133,3 @@ var result = fn(_.slice(arguments)) | ||
function isValidProvider (fnProvider) { | ||
function isValidProvider(fnProvider) { | ||
var result = true | ||
@@ -144,3 +144,3 @@ | ||
function isValidLevel (levelName) { | ||
function isValidLevel(levelName) { | ||
var validLevels = _.keys(LEVELS) | ||
@@ -169,6 +169,6 @@ var isValid = _.includes(validLevels, levelName) | ||
*/ | ||
function getArrow (originalPath, newPath, originalTarget, newTarget) { | ||
function getArrow(originalPath, newPath, originalTarget, newTarget) { | ||
var arrow = ['>'] | ||
var isNewTarget = (originalTarget !== newTarget) // router | ||
var isNewPath = (originalPath !== newPath) // pathRewrite | ||
var isNewTarget = originalTarget !== newTarget // router | ||
var isNewPath = originalPath !== newPath // pathRewrite | ||
@@ -175,0 +175,0 @@ if (isNewPath && !isNewTarget) { |
@@ -15,3 +15,3 @@ var _ = require('lodash') | ||
*/ | ||
function createPathRewriter (rewriteConfig) { | ||
function createPathRewriter(rewriteConfig) { | ||
var rulesCache | ||
@@ -31,6 +31,6 @@ | ||
function rewritePath (path) { | ||
function rewritePath(path) { | ||
var result = path | ||
_.forEach(rulesCache, function (rule) { | ||
_.forEach(rulesCache, function(rule) { | ||
if (rule.regex.test(path)) { | ||
@@ -47,3 +47,3 @@ result = result.replace(rule.regex, rule.value) | ||
function isValidRewriteConfig (rewriteConfig) { | ||
function isValidRewriteConfig(rewriteConfig) { | ||
if (_.isFunction(rewriteConfig)) { | ||
@@ -53,5 +53,7 @@ return true | ||
return true | ||
} else if (_.isUndefined(rewriteConfig) || | ||
_.isNull(rewriteConfig) || | ||
_.isEqual(rewriteConfig, {})) { | ||
} else if ( | ||
_.isUndefined(rewriteConfig) || | ||
_.isNull(rewriteConfig) || | ||
_.isEqual(rewriteConfig, {}) | ||
) { | ||
return false | ||
@@ -63,7 +65,7 @@ } else { | ||
function parsePathRewriteRules (rewriteConfig) { | ||
function parsePathRewriteRules(rewriteConfig) { | ||
var rules = [] | ||
if (_.isPlainObject(rewriteConfig)) { | ||
_.forIn(rewriteConfig, function (value, key) { | ||
_.forIn(rewriteConfig, function(value, key) { | ||
rules.push({ | ||
@@ -73,3 +75,7 @@ regex: new RegExp(key), | ||
}) | ||
logger.info('[HPM] Proxy rewrite rule created: "%s" ~> "%s"', key, rewriteConfig[key]) | ||
logger.info( | ||
'[HPM] Proxy rewrite rule created: "%s" ~> "%s"', | ||
key, | ||
rewriteConfig[key] | ||
) | ||
}) | ||
@@ -76,0 +82,0 @@ } |
@@ -8,3 +8,3 @@ var _ = require('lodash') | ||
function getTarget (req, config) { | ||
function getTarget(req, config) { | ||
var newTarget | ||
@@ -22,3 +22,3 @@ var router = config.router | ||
function getTargetFromProxyTable (req, table) { | ||
function getTargetFromProxyTable(req, table) { | ||
var result | ||
@@ -30,5 +30,6 @@ var host = req.headers.host | ||
_.forIn(table, function (value, key) { | ||
_.forIn(table, function(value, key) { | ||
if (containsPath(key)) { | ||
if (hostAndPath.indexOf(key) > -1) { // match 'localhost:3000/api' | ||
if (hostAndPath.indexOf(key) > -1) { | ||
// match 'localhost:3000/api' | ||
result = table[key] | ||
@@ -39,3 +40,4 @@ logger.debug('[HPM] Router table match: "%s"', key) | ||
} else { | ||
if (key === host) { // match 'localhost:3000' | ||
if (key === host) { | ||
// match 'localhost:3000' | ||
result = table[key] | ||
@@ -51,4 +53,4 @@ logger.debug('[HPM] Router table match: "%s"', host) | ||
function containsPath (v) { | ||
function containsPath(v) { | ||
return v.indexOf('/') > -1 | ||
} |
{ | ||
"name": "http-proxy-middleware", | ||
"version": "0.19.0", | ||
"version": "0.19.1", | ||
"description": "The one-liner node.js proxy middleware for connect, express and browser-sync", | ||
@@ -12,8 +12,7 @@ "main": "index.js", | ||
"clean": "rm -rf coverage", | ||
"lint": "standard --verbose | snazzy --colors", | ||
"lint:fix": "standard --fix", | ||
"lint": "prettier \"**/*.{js,md}\" --list-different", | ||
"lint:fix": "prettier \"**/*.{js,md}\" --write", | ||
"test": "npm run lint && mocha --recursive --colors --reporter spec", | ||
"cover": "npm run clean && istanbul cover ./node_modules/mocha/bin/_mocha -- --recursive", | ||
"coveralls": "istanbul cover ./node_modules/mocha/bin/_mocha --report lcovonly -- --recursive --reporter spec && istanbul-coveralls && npm run clean", | ||
"commitmsg": "commitlint -e $GIT_PARAMS" | ||
"coveralls": "istanbul cover ./node_modules/mocha/bin/_mocha --report lcovonly -- --recursive --reporter spec && istanbul-coveralls && npm run clean" | ||
}, | ||
@@ -46,10 +45,10 @@ "repository": { | ||
"devDependencies": { | ||
"@commitlint/cli": "^7.1.1", | ||
"@commitlint/config-conventional": "^7.1.1", | ||
"browser-sync": "^2.24.7", | ||
"chai": "^4.1.2", | ||
"@commitlint/cli": "^7.2.1", | ||
"@commitlint/config-conventional": "^7.1.2", | ||
"browser-sync": "^2.26.3", | ||
"chai": "^4.2.0", | ||
"connect": "^3.6.6", | ||
"coveralls": "^3.0.2", | ||
"express": "^4.16.3", | ||
"husky": "^0.14.3", | ||
"express": "^4.16.4", | ||
"husky": "^1.2.0", | ||
"istanbul": "^0.4.5", | ||
@@ -59,6 +58,6 @@ "istanbul-coveralls": "^1.0.3", | ||
"mocha-lcov-reporter": "1.3.0", | ||
"opn": "^5.3.0", | ||
"snazzy": "^8.0.0", | ||
"standard": "^12.0.0", | ||
"ws": "^6.0.0" | ||
"opn": "^5.4.0", | ||
"precise-commits": "^1.0.2", | ||
"prettier": "^1.15.2", | ||
"ws": "^6.1.2" | ||
}, | ||
@@ -68,3 +67,3 @@ "dependencies": { | ||
"is-glob": "^4.0.0", | ||
"lodash": "^4.17.10", | ||
"lodash": "^4.17.11", | ||
"micromatch": "^3.1.10" | ||
@@ -75,6 +74,7 @@ }, | ||
}, | ||
"standard": { | ||
"env": [ | ||
"mocha" | ||
] | ||
"husky": { | ||
"hooks": { | ||
"commit-msg": "commitlint -E HUSKY_GIT_PARAMS", | ||
"pre-commit": "precise-commits" | ||
} | ||
}, | ||
@@ -81,0 +81,0 @@ "commitlint": { |
522
README.md
@@ -7,3 +7,3 @@ # http-proxy-middleware | ||
[![dependency Status](https://snyk.io/test/npm/http-proxy-middleware/badge.svg)](https://snyk.io/test/npm/http-proxy-middleware) | ||
[![JavaScript Style Guide](https://img.shields.io/badge/codestyle-standard-brightgreen.svg)](https://standardjs.com) | ||
[![code style: prettier](https://img.shields.io/badge/code_style-prettier-ff69b4.svg?style=flat-square)](https://github.com/prettier/prettier) | ||
@@ -19,9 +19,9 @@ Node.js proxying made simple. Configure proxy middleware with ease for [connect](https://github.com/senchalabs/connect), [express](https://github.com/strongloop/express), [browser-sync](https://github.com/BrowserSync/browser-sync) and [many more](#compatible-servers). | ||
```javascript | ||
var express = require('express'); | ||
var proxy = require('http-proxy-middleware'); | ||
var express = require('express') | ||
var proxy = require('http-proxy-middleware') | ||
var app = express(); | ||
var app = express() | ||
app.use('/api', proxy({target: 'http://www.example.org', changeOrigin: true})); | ||
app.listen(3000); | ||
app.use('/api', proxy({ target: 'http://www.example.org', changeOrigin: true })) | ||
app.listen(3000) | ||
@@ -44,9 +44,9 @@ // http://localhost:3000/api/foo/bar -> http://www.example.org/api/foo/bar | ||
- [Options](#options) | ||
- [http-proxy-middleware options](#http-proxy-middleware-options) | ||
- [http-proxy events](#http-proxy-events) | ||
- [http-proxy options](#http-proxy-options) | ||
- [http-proxy-middleware options](#http-proxy-middleware-options) | ||
- [http-proxy events](#http-proxy-events) | ||
- [http-proxy options](#http-proxy-options) | ||
- [Shorthand](#shorthand) | ||
- [app.use\(path, proxy\)](#appusepath-proxy) | ||
- [app.use\(path, proxy\)](#appusepath-proxy) | ||
- [WebSocket](#websocket) | ||
- [External WebSocket upgrade](#external-websocket-upgrade) | ||
- [External WebSocket upgrade](#external-websocket-upgrade) | ||
- [Working examples](#working-examples) | ||
@@ -61,3 +61,2 @@ - [Recipes](#recipes) | ||
## Install | ||
@@ -76,5 +75,5 @@ | ||
```javascript | ||
var proxy = require('http-proxy-middleware'); | ||
var proxy = require('http-proxy-middleware') | ||
var apiProxy = proxy('/api', {target: 'http://www.example.org'}); | ||
var apiProxy = proxy('/api', { target: 'http://www.example.org' }) | ||
// \____/ \_____________________________/ | ||
@@ -86,6 +85,7 @@ // | | | ||
``` | ||
* **context**: Determine which requests should be proxied to the target host. | ||
(more on [context matching](#context-matching)) | ||
* **options.target**: target host to proxy to. _(protocol + host)_ | ||
- **context**: Determine which requests should be proxied to the target host. | ||
(more on [context matching](#context-matching)) | ||
- **options.target**: target host to proxy to. _(protocol + host)_ | ||
(full list of [`http-proxy-middleware` configuration options](#options)) | ||
@@ -95,7 +95,7 @@ | ||
``` javascript | ||
```javascript | ||
// shorthand syntax for the example above: | ||
var apiProxy = proxy('http://www.example.org/api'); | ||
var apiProxy = proxy('http://www.example.org/api') | ||
``` | ||
``` | ||
More about the [shorthand configuration](#shorthand). | ||
@@ -109,28 +109,28 @@ | ||
// include dependencies | ||
var express = require('express'); | ||
var proxy = require('http-proxy-middleware'); | ||
var express = require('express') | ||
var proxy = require('http-proxy-middleware') | ||
// proxy middleware options | ||
var options = { | ||
target: 'http://www.example.org', // target host | ||
changeOrigin: true, // needed for virtual hosted sites | ||
ws: true, // proxy websockets | ||
pathRewrite: { | ||
'^/api/old-path' : '/api/new-path', // rewrite path | ||
'^/api/remove/path' : '/path' // remove base path | ||
}, | ||
router: { | ||
// when request.headers.host == 'dev.localhost:3000', | ||
// override target 'http://www.example.org' to 'http://localhost:8000' | ||
'dev.localhost:3000' : 'http://localhost:8000' | ||
} | ||
}; | ||
target: 'http://www.example.org', // target host | ||
changeOrigin: true, // needed for virtual hosted sites | ||
ws: true, // proxy websockets | ||
pathRewrite: { | ||
'^/api/old-path': '/api/new-path', // rewrite path | ||
'^/api/remove/path': '/path' // remove base path | ||
}, | ||
router: { | ||
// when request.headers.host == 'dev.localhost:3000', | ||
// override target 'http://www.example.org' to 'http://localhost:8000' | ||
'dev.localhost:3000': 'http://localhost:8000' | ||
} | ||
} | ||
// create the proxy (without context) | ||
var exampleProxy = proxy(options); | ||
var exampleProxy = proxy(options) | ||
// mount `exampleProxy` in web server | ||
var app = express(); | ||
app.use('/api', exampleProxy); | ||
app.listen(3000); | ||
var app = express() | ||
app.use('/api', exampleProxy) | ||
app.listen(3000) | ||
``` | ||
@@ -151,34 +151,40 @@ | ||
* **path matching** | ||
- `proxy({...})` - matches any path, all requests will be proxied. | ||
- `proxy('/', {...})` - matches any path, all requests will be proxied. | ||
- `proxy('/api', {...})` - matches paths starting with `/api` | ||
- **path matching** | ||
* **multiple path matching** | ||
- `proxy(['/api', '/ajax', '/someotherpath'], {...})` | ||
- `proxy({...})` - matches any path, all requests will be proxied. | ||
- `proxy('/', {...})` - matches any path, all requests will be proxied. | ||
- `proxy('/api', {...})` - matches paths starting with `/api` | ||
* **wildcard path matching** | ||
For fine-grained control you can use wildcard matching. Glob pattern matching is done by _micromatch_. Visit [micromatch](https://www.npmjs.com/package/micromatch) or [glob](https://www.npmjs.com/package/glob) for more globbing examples. | ||
- `proxy('**', {...})` matches any path, all requests will be proxied. | ||
- `proxy('**/*.html', {...})` matches any path which ends with `.html` | ||
- `proxy('/*.html', {...})` matches paths directly under path-absolute | ||
- `proxy('/api/**/*.html', {...})` matches requests ending with `.html` in the path of `/api` | ||
- `proxy(['/api/**', '/ajax/**'], {...})` combine multiple patterns | ||
- `proxy(['/api/**', '!**/bad.json'], {...})` exclusion | ||
- **multiple path matching** | ||
* **custom matching** | ||
For full control you can provide a custom function to determine which requests should be proxied or not. | ||
```javascript | ||
/** | ||
* @return {Boolean} | ||
*/ | ||
var filter = function (pathname, req) { | ||
return (pathname.match('^/api') && req.method === 'GET'); | ||
}; | ||
- `proxy(['/api', '/ajax', '/someotherpath'], {...})` | ||
var apiProxy = proxy(filter, {target: 'http://www.example.org'}) | ||
``` | ||
- **wildcard path matching** | ||
For fine-grained control you can use wildcard matching. Glob pattern matching is done by _micromatch_. Visit [micromatch](https://www.npmjs.com/package/micromatch) or [glob](https://www.npmjs.com/package/glob) for more globbing examples. | ||
- `proxy('**', {...})` matches any path, all requests will be proxied. | ||
- `proxy('**/*.html', {...})` matches any path which ends with `.html` | ||
- `proxy('/*.html', {...})` matches paths directly under path-absolute | ||
- `proxy('/api/**/*.html', {...})` matches requests ending with `.html` in the path of `/api` | ||
- `proxy(['/api/**', '/ajax/**'], {...})` combine multiple patterns | ||
- `proxy(['/api/**', '!**/bad.json'], {...})` exclusion | ||
**Note**: In multiple path matching, you cannot use string paths and wildcard paths together. | ||
- **custom matching** | ||
For full control you can provide a custom function to determine which requests should be proxied or not. | ||
```javascript | ||
/** | ||
* @return {Boolean} | ||
*/ | ||
var filter = function(pathname, req) { | ||
return pathname.match('^/api') && req.method === 'GET' | ||
} | ||
var apiProxy = proxy(filter, { target: 'http://www.example.org' }) | ||
``` | ||
## Options | ||
@@ -188,63 +194,66 @@ | ||
* **option.pathRewrite**: object/function, rewrite target's url path. Object-keys will be used as _RegExp_ to match paths. | ||
```javascript | ||
// rewrite path | ||
pathRewrite: {'^/old/api' : '/new/api'} | ||
// remove path | ||
pathRewrite: {'^/remove/api' : ''} | ||
// add base path | ||
pathRewrite: {'^/' : '/basepath/'} | ||
- **option.pathRewrite**: object/function, rewrite target's url path. Object-keys will be used as _RegExp_ to match paths. | ||
// custom rewriting | ||
pathRewrite: function (path, req) { return path.replace('/api', '/base/api') } | ||
``` | ||
```javascript | ||
// rewrite path | ||
pathRewrite: {'^/old/api' : '/new/api'} | ||
* **option.router**: object/function, re-target `option.target` for specific requests. | ||
```javascript | ||
// Use `host` and/or `path` to match requests. First match will be used. | ||
// The order of the configuration matters. | ||
router: { | ||
'integration.localhost:3000' : 'http://localhost:8001', // host only | ||
'staging.localhost:3000' : 'http://localhost:8002', // host only | ||
'localhost:3000/api' : 'http://localhost:8003', // host + path | ||
'/rest' : 'http://localhost:8004' // path only | ||
} | ||
// remove path | ||
pathRewrite: {'^/remove/api' : ''} | ||
// Custom router function | ||
router: function(req) { | ||
return 'http://localhost:8004'; | ||
} | ||
``` | ||
// add base path | ||
pathRewrite: {'^/' : '/basepath/'} | ||
* **option.logLevel**: string, ['debug', 'info', 'warn', 'error', 'silent']. Default: `'info'` | ||
// custom rewriting | ||
pathRewrite: function (path, req) { return path.replace('/api', '/base/api') } | ||
``` | ||
* **option.logProvider**: function, modify or replace log provider. Default: `console`. | ||
```javascript | ||
// simple replace | ||
function logProvider(provider) { | ||
// replace the default console log provider. | ||
return require('winston'); | ||
} | ||
``` | ||
- **option.router**: object/function, re-target `option.target` for specific requests. | ||
```javascript | ||
// verbose replacement | ||
function logProvider(provider) { | ||
var logger = new (require('winston').Logger)(); | ||
```javascript | ||
// Use `host` and/or `path` to match requests. First match will be used. | ||
// The order of the configuration matters. | ||
router: { | ||
'integration.localhost:3000' : 'http://localhost:8001', // host only | ||
'staging.localhost:3000' : 'http://localhost:8002', // host only | ||
'localhost:3000/api' : 'http://localhost:8003', // host + path | ||
'/rest' : 'http://localhost:8004' // path only | ||
} | ||
var myCustomProvider = { | ||
log: logger.log, | ||
debug: logger.debug, | ||
info: logger.info, | ||
warn: logger.warn, | ||
error: logger.error | ||
} | ||
return myCustomProvider; | ||
// Custom router function | ||
router: function(req) { | ||
return 'http://localhost:8004'; | ||
} | ||
``` | ||
- **option.logLevel**: string, ['debug', 'info', 'warn', 'error', 'silent']. Default: `'info'` | ||
- **option.logProvider**: function, modify or replace log provider. Default: `console`. | ||
```javascript | ||
// simple replace | ||
function logProvider(provider) { | ||
// replace the default console log provider. | ||
return require('winston') | ||
} | ||
``` | ||
```javascript | ||
// verbose replacement | ||
function logProvider(provider) { | ||
var logger = new (require('winston')).Logger() | ||
var myCustomProvider = { | ||
log: logger.log, | ||
debug: logger.debug, | ||
info: logger.info, | ||
warn: logger.warn, | ||
error: logger.error | ||
} | ||
``` | ||
* (DEPRECATED) **option.proxyHost**: Use `option.changeOrigin = true` instead. | ||
* (DEPRECATED) **option.proxyTable**: Use `option.router` instead. | ||
return myCustomProvider | ||
} | ||
``` | ||
- (DEPRECATED) **option.proxyHost**: Use `option.changeOrigin = true` instead. | ||
- (DEPRECATED) **option.proxyTable**: Use `option.router` instead. | ||
@@ -255,53 +264,60 @@ ### http-proxy events | ||
* **option.onError**: function, subscribe to http-proxy's `error` event for custom error handling. | ||
```javascript | ||
function onError(err, req, res) { | ||
res.writeHead(500, { | ||
'Content-Type': 'text/plain' | ||
}); | ||
res.end('Something went wrong. And we are reporting a custom error message.'); | ||
} | ||
``` | ||
- **option.onError**: function, subscribe to http-proxy's `error` event for custom error handling. | ||
* **option.onProxyRes**: function, subscribe to http-proxy's `proxyRes` event. | ||
```javascript | ||
function onProxyRes(proxyRes, req, res) { | ||
proxyRes.headers['x-added'] = 'foobar'; // add new header to response | ||
delete proxyRes.headers['x-removed']; // remove header from response | ||
} | ||
``` | ||
```javascript | ||
function onError(err, req, res) { | ||
res.writeHead(500, { | ||
'Content-Type': 'text/plain' | ||
}) | ||
res.end( | ||
'Something went wrong. And we are reporting a custom error message.' | ||
) | ||
} | ||
``` | ||
* **option.onProxyReq**: function, subscribe to http-proxy's `proxyReq` event. | ||
```javascript | ||
function onProxyReq(proxyReq, req, res) { | ||
// add custom header to request | ||
proxyReq.setHeader('x-added', 'foobar'); | ||
// or log the req | ||
} | ||
``` | ||
- **option.onProxyRes**: function, subscribe to http-proxy's `proxyRes` event. | ||
* **option.onProxyReqWs**: function, subscribe to http-proxy's `proxyReqWs` event. | ||
```javascript | ||
function onProxyReqWs(proxyReq, req, socket, options, head) { | ||
// add custom header | ||
proxyReq.setHeader('X-Special-Proxy-Header', 'foobar'); | ||
} | ||
``` | ||
```javascript | ||
function onProxyRes(proxyRes, req, res) { | ||
proxyRes.headers['x-added'] = 'foobar' // add new header to response | ||
delete proxyRes.headers['x-removed'] // remove header from response | ||
} | ||
``` | ||
* **option.onOpen**: function, subscribe to http-proxy's `open` event. | ||
```javascript | ||
function onOpen(proxySocket) { | ||
// listen for messages coming FROM the target here | ||
proxySocket.on('data', hybiParseAndLogMessage); | ||
} | ||
``` | ||
- **option.onProxyReq**: function, subscribe to http-proxy's `proxyReq` event. | ||
* **option.onClose**: function, subscribe to http-proxy's `close` event. | ||
```javascript | ||
function onClose(res, socket, head) { | ||
// view disconnected websocket connections | ||
console.log('Client disconnected'); | ||
} | ||
``` | ||
```javascript | ||
function onProxyReq(proxyReq, req, res) { | ||
// add custom header to request | ||
proxyReq.setHeader('x-added', 'foobar') | ||
// or log the req | ||
} | ||
``` | ||
- **option.onProxyReqWs**: function, subscribe to http-proxy's `proxyReqWs` event. | ||
```javascript | ||
function onProxyReqWs(proxyReq, req, socket, options, head) { | ||
// add custom header | ||
proxyReq.setHeader('X-Special-Proxy-Header', 'foobar') | ||
} | ||
``` | ||
- **option.onOpen**: function, subscribe to http-proxy's `open` event. | ||
```javascript | ||
function onOpen(proxySocket) { | ||
// listen for messages coming FROM the target here | ||
proxySocket.on('data', hybiParseAndLogMessage) | ||
} | ||
``` | ||
- **option.onClose**: function, subscribe to http-proxy's `close` event. | ||
```javascript | ||
function onClose(res, socket, head) { | ||
// view disconnected websocket connections | ||
console.log('Client disconnected') | ||
} | ||
``` | ||
### http-proxy options | ||
@@ -311,69 +327,67 @@ | ||
* **option.target**: url string to be parsed with the url module | ||
* **option.forward**: url string to be parsed with the url module | ||
* **option.agent**: object to be passed to http(s).request (see Node's [https agent](http://nodejs.org/api/https.html#https_class_https_agent) and [http agent](http://nodejs.org/api/http.html#http_class_http_agent) objects) | ||
* **option.ssl**: object to be passed to https.createServer() | ||
* **option.ws**: true/false: if you want to proxy websockets | ||
* **option.xfwd**: true/false, adds x-forward headers | ||
* **option.secure**: true/false, if you want to verify the SSL Certs | ||
* **option.toProxy**: true/false, passes the absolute URL as the `path` (useful for proxying to proxies) | ||
* **option.prependPath**: true/false, Default: true - specify whether you want to prepend the target's path to the proxy path | ||
* **option.ignorePath**: true/false, Default: false - specify whether you want to ignore the proxy path of the incoming request (note: you will have to append / manually if required). | ||
* **option.localAddress** : Local interface string to bind for outgoing connections | ||
* **option.changeOrigin**: true/false, Default: false - changes the origin of the host header to the target URL | ||
* **option.preserveHeaderKeyCase**: true/false, Default: false - specify whether you want to keep letter case of response header key | ||
* **option.auth** : Basic authentication i.e. 'user:password' to compute an Authorization header. | ||
* **option.hostRewrite**: rewrites the location hostname on (301/302/307/308) redirects. | ||
* **option.autoRewrite**: rewrites the location host/port on (301/302/307/308) redirects based on requested host/port. Default: false. | ||
* **option.protocolRewrite**: rewrites the location protocol on (301/302/307/308) redirects to 'http' or 'https'. Default: null. | ||
* **option.cookieDomainRewrite**: rewrites domain of `set-cookie` headers. Possible values: | ||
* `false` (default): disable cookie rewriting | ||
* String: new domain, for example `cookieDomainRewrite: "new.domain"`. To remove the domain, use `cookieDomainRewrite: ""`. | ||
* Object: mapping of domains to new domains, use `"*"` to match all domains. | ||
For example keep one domain unchanged, rewrite one domain and remove other domains: | ||
``` | ||
cookieDomainRewrite: { | ||
"unchanged.domain": "unchanged.domain", | ||
"old.domain": "new.domain", | ||
"*": "" | ||
} | ||
``` | ||
* **option.cookiePathRewrite**: rewrites path of `set-cookie` headers. Possible values: | ||
* `false` (default): disable cookie rewriting | ||
* String: new path, for example `cookiePathRewrite: "/newPath/"`. To remove the path, use `cookiePathRewrite: ""`. To set path to root use `cookiePathRewrite: "/"`. | ||
* Object: mapping of paths to new paths, use `"*"` to match all paths. | ||
For example, to keep one path unchanged, rewrite one path and remove other paths: | ||
``` | ||
cookiePathRewrite: { | ||
"/unchanged.path/": "/unchanged.path/", | ||
"/old.path/": "/new.path/", | ||
"*": "" | ||
} | ||
``` | ||
* **option.headers**: object, adds [request headers](https://en.wikipedia.org/wiki/List_of_HTTP_header_fields#Request_fields). (Example: `{host:'www.example.org'}`) | ||
* **option.proxyTimeout**: timeout (in millis) when proxy receives no response from target | ||
* **option.timeout**: timeout (in millis) for incoming requests | ||
* **option.followRedirects**: true/false, Default: false - specify whether you want to follow redirects | ||
* **option.selfHandleResponse** true/false, if set to true, none of the webOutgoing passes are called and it's your responsibility to appropriately return the response by listening and acting on the `proxyRes` event | ||
* **option.buffer**: stream of data to send as the request body. Maybe you have some middleware that consumes the request stream before proxying it on e.g. If you read the body of a request into a field called 'req.rawbody' you could restream this field in the buffer option: | ||
- **option.target**: url string to be parsed with the url module | ||
- **option.forward**: url string to be parsed with the url module | ||
- **option.agent**: object to be passed to http(s).request (see Node's [https agent](http://nodejs.org/api/https.html#https_class_https_agent) and [http agent](http://nodejs.org/api/http.html#http_class_http_agent) objects) | ||
- **option.ssl**: object to be passed to https.createServer() | ||
- **option.ws**: true/false: if you want to proxy websockets | ||
- **option.xfwd**: true/false, adds x-forward headers | ||
- **option.secure**: true/false, if you want to verify the SSL Certs | ||
- **option.toProxy**: true/false, passes the absolute URL as the `path` (useful for proxying to proxies) | ||
- **option.prependPath**: true/false, Default: true - specify whether you want to prepend the target's path to the proxy path | ||
- **option.ignorePath**: true/false, Default: false - specify whether you want to ignore the proxy path of the incoming request (note: you will have to append / manually if required). | ||
- **option.localAddress** : Local interface string to bind for outgoing connections | ||
- **option.changeOrigin**: true/false, Default: false - changes the origin of the host header to the target URL | ||
- **option.preserveHeaderKeyCase**: true/false, Default: false - specify whether you want to keep letter case of response header key | ||
- **option.auth** : Basic authentication i.e. 'user:password' to compute an Authorization header. | ||
- **option.hostRewrite**: rewrites the location hostname on (301/302/307/308) redirects. | ||
- **option.autoRewrite**: rewrites the location host/port on (301/302/307/308) redirects based on requested host/port. Default: false. | ||
- **option.protocolRewrite**: rewrites the location protocol on (301/302/307/308) redirects to 'http' or 'https'. Default: null. | ||
- **option.cookieDomainRewrite**: rewrites domain of `set-cookie` headers. Possible values: | ||
- `false` (default): disable cookie rewriting | ||
- String: new domain, for example `cookieDomainRewrite: "new.domain"`. To remove the domain, use `cookieDomainRewrite: ""`. | ||
- Object: mapping of domains to new domains, use `"*"` to match all domains. | ||
For example keep one domain unchanged, rewrite one domain and remove other domains: | ||
``` | ||
'use strict'; | ||
cookieDomainRewrite: { | ||
"unchanged.domain": "unchanged.domain", | ||
"old.domain": "new.domain", | ||
"*": "" | ||
} | ||
``` | ||
- **option.cookiePathRewrite**: rewrites path of `set-cookie` headers. Possible values: | ||
- `false` (default): disable cookie rewriting | ||
- String: new path, for example `cookiePathRewrite: "/newPath/"`. To remove the path, use `cookiePathRewrite: ""`. To set path to root use `cookiePathRewrite: "/"`. | ||
- Object: mapping of paths to new paths, use `"*"` to match all paths. | ||
For example, to keep one path unchanged, rewrite one path and remove other paths: | ||
``` | ||
cookiePathRewrite: { | ||
"/unchanged.path/": "/unchanged.path/", | ||
"/old.path/": "/new.path/", | ||
"*": "" | ||
} | ||
``` | ||
- **option.headers**: object, adds [request headers](https://en.wikipedia.org/wiki/List_of_HTTP_header_fields#Request_fields). (Example: `{host:'www.example.org'}`) | ||
- **option.proxyTimeout**: timeout (in millis) when proxy receives no response from target | ||
- **option.timeout**: timeout (in millis) for incoming requests | ||
- **option.followRedirects**: true/false, Default: false - specify whether you want to follow redirects | ||
- **option.selfHandleResponse** true/false, if set to true, none of the webOutgoing passes are called and it's your responsibility to appropriately return the response by listening and acting on the `proxyRes` event | ||
- **option.buffer**: stream of data to send as the request body. Maybe you have some middleware that consumes the request stream before proxying it on e.g. If you read the body of a request into a field called 'req.rawbody' you could restream this field in the buffer option: | ||
const streamify = require('stream-array'); | ||
const HttpProxy = require('http-proxy'); | ||
const proxy = new HttpProxy(); | ||
``` | ||
'use strict'; | ||
module.exports = (req, res, next) => { | ||
const streamify = require('stream-array'); | ||
const HttpProxy = require('http-proxy'); | ||
const proxy = new HttpProxy(); | ||
proxy.web(req, res, { | ||
target: 'http://localhost:4003/', | ||
buffer: streamify(req.rawBody) | ||
}, next); | ||
module.exports = (req, res, next) => { | ||
}; | ||
``` | ||
proxy.web(req, res, { | ||
target: 'http://localhost:4003/', | ||
buffer: streamify(req.rawBody) | ||
}, next); | ||
}; | ||
``` | ||
## Shorthand | ||
@@ -384,11 +398,9 @@ | ||
```javascript | ||
proxy('http://www.example.org:8000/api'); | ||
proxy('http://www.example.org:8000/api') | ||
// proxy('/api', {target: 'http://www.example.org:8000'}); | ||
proxy('http://www.example.org:8000/api/books/*/**.json'); | ||
proxy('http://www.example.org:8000/api/books/*/**.json') | ||
// proxy('/api/books/*/**.json', {target: 'http://www.example.org:8000'}); | ||
proxy('http://www.example.org:8000/api', {changeOrigin:true}); | ||
proxy('http://www.example.org:8000/api', { changeOrigin: true }) | ||
// proxy('/api', {target: 'http://www.example.org:8000', changeOrigin: true}); | ||
@@ -399,12 +411,14 @@ ``` | ||
If you want to use the server's `app.use` `path` parameter to match requests; | ||
If you want to use the server's `app.use` `path` parameter to match requests; | ||
Create and mount the proxy without the http-proxy-middleware `context` parameter: | ||
```javascript | ||
app.use('/api', proxy({target:'http://www.example.org', changeOrigin:true})); | ||
app.use('/api', proxy({ target: 'http://www.example.org', changeOrigin: true })) | ||
``` | ||
`app.use` documentation: | ||
* express: http://expressjs.com/en/4x/api.html#app.use | ||
* connect: https://github.com/senchalabs/connect#mount-middleware | ||
- express: http://expressjs.com/en/4x/api.html#app.use | ||
- connect: https://github.com/senchalabs/connect#mount-middleware | ||
## WebSocket | ||
@@ -414,9 +428,9 @@ | ||
// verbose api | ||
proxy('/', {target:'http://echo.websocket.org', ws:true}); | ||
proxy('/', { target: 'http://echo.websocket.org', ws: true }) | ||
// shorthand | ||
proxy('http://echo.websocket.org', {ws:true}); | ||
proxy('http://echo.websocket.org', { ws: true }) | ||
// shorter shorthand | ||
proxy('ws://echo.websocket.org'); | ||
proxy('ws://echo.websocket.org') | ||
``` | ||
@@ -427,13 +441,13 @@ | ||
In the previous WebSocket examples, http-proxy-middleware relies on a initial http request in order to listen to the http `upgrade` event. If you need to proxy WebSockets without the initial http request, you can subscribe to the server's http `upgrade` event manually. | ||
```javascript | ||
var wsProxy = proxy('ws://echo.websocket.org', {changeOrigin:true}); | ||
var wsProxy = proxy('ws://echo.websocket.org', { changeOrigin: true }) | ||
var app = express(); | ||
app.use(wsProxy); | ||
var app = express() | ||
app.use(wsProxy) | ||
var server = app.listen(3000); | ||
server.on('upgrade', wsProxy.upgrade); // <-- subscribe to http 'upgrade' | ||
var server = app.listen(3000) | ||
server.on('upgrade', wsProxy.upgrade) // <-- subscribe to http 'upgrade' | ||
``` | ||
## Working examples | ||
@@ -443,6 +457,6 @@ | ||
* Browser-Sync ([example source](https://github.com/chimurai/http-proxy-middleware/tree/master/examples/browser-sync/index.js)) | ||
* express ([example source](https://github.com/chimurai/http-proxy-middleware/tree/master/examples/express/index.js)) | ||
* connect ([example source](https://github.com/chimurai/http-proxy-middleware/tree/master/examples/connect/index.js)) | ||
* WebSocket ([example source](https://github.com/chimurai/http-proxy-middleware/tree/master/examples/websocket/index.js)) | ||
- Browser-Sync ([example source](https://github.com/chimurai/http-proxy-middleware/tree/master/examples/browser-sync/index.js)) | ||
- express ([example source](https://github.com/chimurai/http-proxy-middleware/tree/master/examples/express/index.js)) | ||
- connect ([example source](https://github.com/chimurai/http-proxy-middleware/tree/master/examples/connect/index.js)) | ||
- WebSocket ([example source](https://github.com/chimurai/http-proxy-middleware/tree/master/examples/websocket/index.js)) | ||
@@ -456,11 +470,12 @@ ## Recipes | ||
`http-proxy-middleware` is compatible with the following servers: | ||
* [connect](https://www.npmjs.com/package/connect) | ||
* [express](https://www.npmjs.com/package/express) | ||
* [browser-sync](https://www.npmjs.com/package/browser-sync) | ||
* [lite-server](https://www.npmjs.com/package/lite-server) | ||
* [grunt-contrib-connect](https://www.npmjs.com/package/grunt-contrib-connect) | ||
* [grunt-browser-sync](https://www.npmjs.com/package/grunt-browser-sync) | ||
* [gulp-connect](https://www.npmjs.com/package/gulp-connect) | ||
* [gulp-webserver](https://www.npmjs.com/package/gulp-webserver) | ||
- [connect](https://www.npmjs.com/package/connect) | ||
- [express](https://www.npmjs.com/package/express) | ||
- [browser-sync](https://www.npmjs.com/package/browser-sync) | ||
- [lite-server](https://www.npmjs.com/package/lite-server) | ||
- [grunt-contrib-connect](https://www.npmjs.com/package/grunt-contrib-connect) | ||
- [grunt-browser-sync](https://www.npmjs.com/package/grunt-browser-sync) | ||
- [gulp-connect](https://www.npmjs.com/package/gulp-connect) | ||
- [gulp-webserver](https://www.npmjs.com/package/gulp-webserver) | ||
Sample implementations can be found in the [server recipes](https://github.com/chimurai/http-proxy-middleware/tree/master/recipes/servers.md). | ||
@@ -490,3 +505,2 @@ | ||
## License | ||
@@ -493,0 +507,0 @@ |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
47749
680
492
Updatedlodash@^4.17.11