http-proxy
Advanced tools
Comparing version 1.16.2 to 1.17.0
@@ -7,4 +7,3 @@ var common = exports, | ||
var upgradeHeader = /(^|,)\s*upgrade\s*($|,)/i, | ||
isSSL = /^https|wss/, | ||
cookieDomainRegex = /(;\s*domain=)([^;]+)/i; | ||
isSSL = /^https|wss/; | ||
@@ -44,3 +43,3 @@ /** | ||
outgoing.method = req.method; | ||
outgoing.method = options.method || req.method; | ||
outgoing.headers = extend({}, req.headers); | ||
@@ -216,23 +215,23 @@ | ||
*/ | ||
common.rewriteCookieDomain = function rewriteCookieDomain(header, config) { | ||
common.rewriteCookieProperty = function rewriteCookieProperty(header, config, property) { | ||
if (Array.isArray(header)) { | ||
return header.map(function (headerElement) { | ||
return rewriteCookieDomain(headerElement, config); | ||
return rewriteCookieProperty(headerElement, config, property); | ||
}); | ||
} | ||
return header.replace(cookieDomainRegex, function(match, prefix, previousDomain) { | ||
var newDomain; | ||
if (previousDomain in config) { | ||
newDomain = config[previousDomain]; | ||
return header.replace(new RegExp("(;\\s*" + property + "=)([^;]+)", 'i'), function(match, prefix, previousValue) { | ||
var newValue; | ||
if (previousValue in config) { | ||
newValue = config[previousValue]; | ||
} else if ('*' in config) { | ||
newDomain = config['*']; | ||
newValue = config['*']; | ||
} else { | ||
//no match, return previous domain | ||
//no match, return previous value | ||
return match; | ||
} | ||
if (newDomain) { | ||
//replace domain | ||
return prefix + newDomain; | ||
if (newValue) { | ||
//replace value | ||
return prefix + newValue; | ||
} else { | ||
//remove domain | ||
//remove value | ||
return ''; | ||
@@ -239,0 +238,0 @@ } |
@@ -44,2 +44,3 @@ var httpProxy = module.exports, | ||
var requestOptions = options; | ||
if( | ||
@@ -50,5 +51,5 @@ !(args[cntr] instanceof Buffer) && | ||
//Copy global options | ||
options = extend({}, options); | ||
requestOptions = extend({}, options); | ||
//Overwrite with request options | ||
extend(options, args[cntr]); | ||
extend(requestOptions, args[cntr]); | ||
@@ -65,7 +66,7 @@ cntr--; | ||
['target', 'forward'].forEach(function(e) { | ||
if (typeof options[e] === 'string') | ||
options[e] = parse_url(options[e]); | ||
if (typeof requestOptions[e] === 'string') | ||
requestOptions[e] = parse_url(requestOptions[e]); | ||
}); | ||
if (!options.target && !options.forward) { | ||
if (!requestOptions.target && !requestOptions.forward) { | ||
return this.emit('error', new Error('Must provide a proper URL as target')); | ||
@@ -83,3 +84,3 @@ } | ||
*/ | ||
if(passes[i](req, res, options, head, this, cbl)) { // passes can return a truthy value to halt the loop | ||
if(passes[i](req, res, requestOptions, head, this, cbl)) { // passes can return a truthy value to halt the loop | ||
break; | ||
@@ -86,0 +87,0 @@ } |
@@ -1,5 +0,6 @@ | ||
var http = require('http'), | ||
https = require('https'), | ||
var httpNative = require('http'), | ||
httpsNative = require('https'), | ||
web_o = require('./web-outgoing'), | ||
common = require('../common'); | ||
common = require('../common'), | ||
followRedirects = require('follow-redirects'); | ||
@@ -10,2 +11,4 @@ web_o = Object.keys(web_o).map(function(pass) { | ||
var nativeAgents = { http: httpNative, https: httpsNative }; | ||
/*! | ||
@@ -103,2 +106,6 @@ * Array of passes. | ||
var agents = options.followRedirects ? followRedirects : nativeAgents; | ||
var http = agents.http; | ||
var https = agents.https; | ||
if(options.forward) { | ||
@@ -167,17 +174,22 @@ // If forward enable, so just pipe the request | ||
if(server) { server.emit('proxyRes', proxyRes, req, res); } | ||
for(var i=0; i < web_o.length; i++) { | ||
if(web_o[i](req, res, proxyRes, options)) { break; } | ||
if(!res.headersSent && !options.selfHandleResponse) { | ||
for(var i=0; i < web_o.length; i++) { | ||
if(web_o[i](req, res, proxyRes, options)) { break; } | ||
} | ||
} | ||
// Allow us to listen when the proxy has completed | ||
proxyRes.on('end', function () { | ||
server.emit('end', req, res, proxyRes); | ||
}); | ||
proxyRes.pipe(res); | ||
if (!res.finished) { | ||
// Allow us to listen when the proxy has completed | ||
proxyRes.on('end', function () { | ||
if (server) server.emit('end', req, res, proxyRes); | ||
}); | ||
// We pipe to the response unless its expected to be handled by the user | ||
if (!options.selfHandleResponse) proxyRes.pipe(res); | ||
} else { | ||
if (server) server.emit('end', req, res, proxyRes); | ||
} | ||
}); | ||
//proxyReq.end(); | ||
} | ||
}; |
@@ -87,2 +87,3 @@ var url = require('url'), | ||
var rewriteCookieDomainConfig = options.cookieDomainRewrite, | ||
rewriteCookiePathConfig = options.cookiePathRewrite, | ||
preserveHeaderKeyCase = options.preserveHeaderKeyCase, | ||
@@ -93,4 +94,7 @@ rawHeaderKeyMap, | ||
if (rewriteCookieDomainConfig && key.toLowerCase() === 'set-cookie') { | ||
header = common.rewriteCookieDomain(header, rewriteCookieDomainConfig); | ||
header = common.rewriteCookieProperty(header, rewriteCookieDomainConfig, 'domain'); | ||
} | ||
if (rewriteCookiePathConfig && key.toLowerCase() === 'set-cookie') { | ||
header = common.rewriteCookieProperty(header, rewriteCookiePathConfig, 'path'); | ||
} | ||
res.setHeader(String(key).trim(), header); | ||
@@ -103,2 +107,6 @@ }; | ||
if (typeof rewriteCookiePathConfig === 'string') { //also test for '' | ||
rewriteCookiePathConfig = { '*': rewriteCookiePathConfig }; | ||
} | ||
// message.rawHeaders is added in: v0.11.6 | ||
@@ -135,5 +143,6 @@ // https://nodejs.org/api/http.html#http_message_rawheaders | ||
if(proxyRes.statusMessage) { | ||
res.writeHead(proxyRes.statusCode, proxyRes.statusMessage); | ||
res.statusCode = proxyRes.statusCode; | ||
res.statusMessage = proxyRes.statusMessage; | ||
} else { | ||
res.writeHead(proxyRes.statusCode); | ||
res.statusCode = proxyRes.statusCode; | ||
} | ||
@@ -140,0 +149,0 @@ } |
@@ -80,2 +80,20 @@ var http = require('http'), | ||
stream : function stream(req, socket, options, head, server, clb) { | ||
var createHttpHeader = function(line, headers) { | ||
return Object.keys(headers).reduce(function (head, key) { | ||
var value = headers[key]; | ||
if (!Array.isArray(value)) { | ||
head.push(key + ': ' + value); | ||
return head; | ||
} | ||
for (var i = 0; i < value.length; i++) { | ||
head.push(key + ': ' + value[i]); | ||
} | ||
return head; | ||
}, [line]) | ||
.join('\r\n') + '\r\n\r\n'; | ||
} | ||
common.setupSocket(socket); | ||
@@ -97,3 +115,6 @@ | ||
// if upgrade event isn't going to happen, close the socket | ||
if (!res.upgrade) socket.end(); | ||
if (!res.upgrade) { | ||
socket.write(createHttpHeader('HTTP/' + res.httpVersion + ' ' + res.statusCode + ' ' + res.statusMessage, res.headers)); | ||
res.pipe(socket); | ||
} | ||
}); | ||
@@ -124,19 +145,4 @@ | ||
// | ||
socket.write( | ||
Object.keys(proxyRes.headers).reduce(function (head, key) { | ||
var value = proxyRes.headers[key]; | ||
socket.write(createHttpHeader('HTTP/1.1 101 Switching Protocols', proxyRes.headers)); | ||
if (!Array.isArray(value)) { | ||
head.push(key + ': ' + value); | ||
return head; | ||
} | ||
for (var i = 0; i < value.length; i++) { | ||
head.push(key + ': ' + value[i]); | ||
} | ||
return head; | ||
}, ['HTTP/1.1 101 Switching Protocols']) | ||
.join('\r\n') + '\r\n\r\n' | ||
); | ||
proxySocket.pipe(socket).pipe(proxySocket); | ||
@@ -143,0 +149,0 @@ |
{ | ||
"name": "http-proxy", | ||
"version": "1.16.2", | ||
"version": "1.17.0", | ||
"repository": { | ||
@@ -15,16 +15,15 @@ "type": "git", | ||
"dependencies": { | ||
"eventemitter3": "1.x.x", | ||
"requires-port": "1.x.x" | ||
"eventemitter3": "^3.0.0", | ||
"requires-port": "^1.0.0", | ||
"follow-redirects": "^1.0.0" | ||
}, | ||
"devDependencies": { | ||
"async": "*", | ||
"blanket": "*", | ||
"coveralls": "*", | ||
"dox": "*", | ||
"expect.js": "*", | ||
"mocha": "*", | ||
"mocha-lcov-reporter": "*", | ||
"async": "^2.0.0", | ||
"concat-stream": "^1.6.2", | ||
"expect.js": "~0.3.1", | ||
"mocha": "^3.5.3", | ||
"nyc": "^11.7.1", | ||
"semver": "^5.0.3", | ||
"socket.io": "*", | ||
"socket.io-client": "*", | ||
"socket.io": "^2.1.0", | ||
"socket.io-client": "^2.1.0", | ||
"sse": "0.0.6", | ||
@@ -34,13 +33,9 @@ "ws": "^0.8.0" | ||
"scripts": { | ||
"coveralls": "mocha --require blanket --reporter mocha-lcov-reporter | ./node_modules/coveralls/bin/coveralls.js", | ||
"blanket": { | ||
"pattern": "lib/http-proxy" | ||
}, | ||
"test": "mocha test/*-test.js", | ||
"test-cov": "mocha --require blanket -R html-cov > cov/coverage.html" | ||
"mocha": "mocha test/*-test.js", | ||
"test": "nyc --reporter=text --reporter=lcov npm run mocha" | ||
}, | ||
"engines": { | ||
"node": ">=0.10.0" | ||
"node": ">=4.0.0" | ||
}, | ||
"license": "MIT" | ||
} |
103
README.md
@@ -5,12 +5,4 @@ <p align="center"> | ||
node-http-proxy | ||
======= | ||
# node-http-proxy [![Build Status](https://travis-ci.org/nodejitsu/node-http-proxy.svg?branch=master)](https://travis-ci.org/nodejitsu/node-http-proxy) [![codecov](https://codecov.io/gh/nodejitsu/node-http-proxy/branch/master/graph/badge.svg)](https://codecov.io/gh/nodejitsu/node-http-proxy) | ||
<p align="left"> | ||
<a href="https://travis-ci.org/nodejitsu/node-http-proxy" target="_blank"> | ||
<img src="https://travis-ci.org/nodejitsu/node-http-proxy.png"/></a> | ||
<a href="https://coveralls.io/r/nodejitsu/node-http-proxy" target="_blank"> | ||
<img src="https://coveralls.io/repos/nodejitsu/node-http-proxy/badge.png"/></a> | ||
</p> | ||
`node-http-proxy` is an HTTP programmable proxying library that supports | ||
@@ -57,3 +49,3 @@ websockets. It is suitable for implementing components such as reverse | ||
A new proxy is created by calling `createProxyServer` and passing | ||
an `options` object as argument ([valid properties are available here](lib/http-proxy.js#L33-L50)) | ||
an `options` object as argument ([valid properties are available here](lib/http-proxy.js#L22-L50)) | ||
@@ -130,3 +122,3 @@ ```javascript | ||
#### Setup a stand-alone proxy server with custom server logic | ||
This example show how you can proxy a request using your own HTTP server | ||
This example shows how you can proxy a request using your own HTTP server | ||
and also you can put your own logic to handle the request. | ||
@@ -243,3 +235,3 @@ | ||
#### Using HTTPS | ||
You can activate the validation of a secure SSL certificate to the target connection (avoid self signed certs), just set `secure: true` in the options. | ||
You can activate the validation of a secure SSL certificate to the target connection (avoid self-signed certs), just set `secure: true` in the options. | ||
@@ -280,2 +272,20 @@ ##### HTTPS -> HTTP | ||
##### HTTP -> HTTPS (using a PKCS12 client certificate) | ||
```js | ||
// | ||
// Create an HTTP proxy server with an HTTPS target | ||
// | ||
httpProxy.createProxyServer({ | ||
target: { | ||
protocol: 'https:', | ||
host: 'my-domain-name', | ||
port: 443, | ||
pfx: fs.readFileSync('path/to/certificate.p12'), | ||
passphrase: 'password', | ||
}, | ||
changeOrigin: true, | ||
}).listen(8000); | ||
``` | ||
**[Back to top](#table-of-contents)** | ||
@@ -349,3 +359,3 @@ | ||
* 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. | ||
* 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: | ||
@@ -359,5 +369,38 @@ ``` | ||
``` | ||
* **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/", | ||
"*": "" | ||
} | ||
``` | ||
* **headers**: object with extra headers to be added to target requests. | ||
* **proxyTimeout**: timeout (in millis) when proxy receives no response from target | ||
* **proxyTimeout**: timeout (in millis) for outgoing proxy requests | ||
* **timeout**: timeout (in millis) for incoming requests | ||
* **followRedirects**: true/false, Default: false - specify whether you want to follow redirects | ||
* **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 | ||
* **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: | ||
``` | ||
'use strict'; | ||
const streamify = require('stream-array'); | ||
const HttpProxy = require('http-proxy'); | ||
const proxy = new HttpProxy(); | ||
module.exports = (req, res, next) => { | ||
proxy.web(req, res, { | ||
target: 'http://localhost:4003/', | ||
buffer: streamify(req.rawBody) | ||
}, next); | ||
}; | ||
``` | ||
**NOTE:** | ||
@@ -372,2 +415,3 @@ `options.ws` and `options.ssl` are optional. | ||
**[Back to top](#table-of-contents)** | ||
@@ -453,2 +497,32 @@ | ||
If you want to handle your own response after receiving the `proxyRes`, you can do | ||
so with `selfHandleResponse`. As you can see below, if you use this option, you | ||
are able to intercept and read the `proxyRes` but you must also make sure to | ||
reply to the `res` itself otherwise the original client will never receive any | ||
data. | ||
### Modify response | ||
```js | ||
var option = { | ||
target: target, | ||
selfHandleResponse : true | ||
}; | ||
proxy.on('proxyRes', function (proxyRes, req, res) { | ||
var body = new Buffer(''); | ||
proxyRes.on('data', function (data) { | ||
body = Buffer.concat([body, data]); | ||
}); | ||
proxyRes.on('end', function () { | ||
body = body.toString(); | ||
console.log("res from proxied server:", body); | ||
res.end("my response to cli"); | ||
}); | ||
}); | ||
proxy.web(req, res, option); | ||
``` | ||
#### ProxyTable API | ||
@@ -472,2 +546,3 @@ | ||
* Read carefully our [Code Of Conduct](https://github.com/nodejitsu/node-http-proxy/blob/master/CODE_OF_CONDUCT.md) | ||
* Search on Google/Github | ||
@@ -474,0 +549,0 @@ * If you can't find anything, open an issue |
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
444265
10
37
1328
569
3
+ Addedfollow-redirects@^1.0.0
+ Addedeventemitter3@3.1.2(transitive)
+ Addedfollow-redirects@1.15.9(transitive)
- Removedeventemitter3@1.2.0(transitive)
Updatedeventemitter3@^3.0.0
Updatedrequires-port@^1.0.0