mirror of
https://github.com/http-party/node-http-proxy.git
synced 2025-12-08 20:59:18 +00:00
Compare commits
95 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
9b96cd7251 | ||
|
|
335aeeba2f | ||
|
|
dba39668ba | ||
|
|
9bbe486c5e | ||
|
|
6e4bef4d1c | ||
|
|
d05624167c | ||
|
|
244303b994 | ||
|
|
b4028ba78b | ||
|
|
77a98159d2 | ||
|
|
c662f9ebcd | ||
|
|
806e4927c9 | ||
|
|
c8fa599983 | ||
|
|
0d9ed366b1 | ||
|
|
9d75b981a1 | ||
|
|
192b2b980b | ||
|
|
4a657a7126 | ||
|
|
7a154f81d1 | ||
|
|
749eec65c3 | ||
|
|
e588213644 | ||
|
|
59c4403e9d | ||
|
|
dd1d08b631 | ||
|
|
16d4f8a951 | ||
|
|
fc93520d74 | ||
|
|
7e4a0e511b | ||
|
|
a9b09cce43 | ||
|
|
b00911c937 | ||
|
|
36bfe566a7 | ||
|
|
91fee3e943 | ||
|
|
235f0aa047 | ||
|
|
acdbec09c6 | ||
|
|
569e2ac4fb | ||
|
|
cb3171abfa | ||
|
|
a3fe02d651 | ||
|
|
42e8e1e099 | ||
|
|
e94d52973a | ||
|
|
4a37175a52 | ||
|
|
e5c02b8a8a | ||
|
|
2c44039a7c | ||
|
|
8097ae237e | ||
|
|
abf882e03c | ||
|
|
bab02e909e | ||
|
|
c9a556cfa5 | ||
|
|
6f88caf6e4 | ||
|
|
d2f9db8241 | ||
|
|
8231984fb0 | ||
|
|
81d58c531b | ||
|
|
d533a1be43 | ||
|
|
89f9ef87e0 | ||
|
|
c5d8466483 | ||
|
|
107c18720c | ||
|
|
de1b80851a | ||
|
|
bc6a23709c | ||
|
|
f5c2381395 | ||
|
|
50f58b4cd9 | ||
|
|
2c98416ac2 | ||
|
|
543636d0f6 | ||
|
|
a4bccc332d | ||
|
|
f4ff1006b9 | ||
|
|
09dcb98456 | ||
|
|
812757541d | ||
|
|
c979ba9f2c | ||
|
|
e6f24ba617 | ||
|
|
d73f1ee873 | ||
|
|
a539f3cbc1 | ||
|
|
d4d85ac5c4 | ||
|
|
c1fb596b85 | ||
|
|
961f457622 | ||
|
|
ac1a01b1f3 | ||
|
|
8cb451f20c | ||
|
|
c252b32f6c | ||
|
|
927357bedc | ||
|
|
4edbb62cc5 | ||
|
|
69cf892519 | ||
|
|
2f7f03778c | ||
|
|
d8223884f6 | ||
|
|
d0f1dfeb82 | ||
|
|
220f5fb795 | ||
|
|
d48f67eb90 | ||
|
|
61c2889109 | ||
|
|
fbc266809c | ||
|
|
8eddf45f2a | ||
|
|
f5217d6c20 | ||
|
|
2d01edc5a5 | ||
|
|
d0a1588639 | ||
|
|
912cd3acae | ||
|
|
84087208dd | ||
|
|
b98c75b1ff | ||
|
|
b781af641a | ||
|
|
cbd5777060 | ||
|
|
d8fb344715 | ||
|
|
1e52f660f0 | ||
|
|
9d06ca99d3 | ||
|
|
d0e000e1f9 | ||
|
|
183b5bb4fc | ||
|
|
3a347af543 |
6
.auto-changelog
Normal file
6
.auto-changelog
Normal file
@ -0,0 +1,6 @@
|
||||
{
|
||||
"output": "CHANGELOG.md",
|
||||
"template": "keepachangelog",
|
||||
"unreleased": true,
|
||||
"commitLimit": false
|
||||
}
|
||||
1
.gitattributes
vendored
Normal file
1
.gitattributes
vendored
Normal file
@ -0,0 +1 @@
|
||||
package-lock.json binary
|
||||
2
.gitignore
vendored
2
.gitignore
vendored
@ -6,3 +6,5 @@ notes
|
||||
primus-proxy.js
|
||||
tes.js
|
||||
npm-debug.log
|
||||
.nyc_output
|
||||
coverage
|
||||
|
||||
@ -2,6 +2,8 @@ test
|
||||
examples
|
||||
doc
|
||||
benchmark
|
||||
coverage
|
||||
.nyc_output
|
||||
.travis.yml
|
||||
CHANGELOG.md
|
||||
UPGRADING.md
|
||||
UPGRADING.md
|
||||
|
||||
20
.travis.yml
20
.travis.yml
@ -1,18 +1,12 @@
|
||||
sudo: false
|
||||
language: node_js
|
||||
node_js:
|
||||
- "0.10"
|
||||
- "0.12"
|
||||
- "4.2"
|
||||
|
||||
before_install:
|
||||
- travis_retry npm install -g npm@2.14.5
|
||||
- travis_retry npm install
|
||||
|
||||
- "8"
|
||||
- "10"
|
||||
- "12"
|
||||
script:
|
||||
- npm test
|
||||
|
||||
notifications:
|
||||
email:
|
||||
- travis@nodejitsu.com
|
||||
irc: "irc.freenode.org#nodejitsu"
|
||||
after_success:
|
||||
- bash <(curl -s https://codecov.io/bash)
|
||||
matrix:
|
||||
fast_finish: true
|
||||
|
||||
1872
CHANGELOG.md
Normal file
1872
CHANGELOG.md
Normal file
File diff suppressed because it is too large
Load Diff
74
CODE_OF_CONDUCT.md
Normal file
74
CODE_OF_CONDUCT.md
Normal file
@ -0,0 +1,74 @@
|
||||
# Contributor Covenant Code of Conduct
|
||||
|
||||
## Our Pledge
|
||||
|
||||
In the interest of fostering an open and welcoming environment, we as
|
||||
contributors and maintainers pledge to making participation in our project and
|
||||
our community a harassment-free experience for everyone, regardless of age, body
|
||||
size, disability, ethnicity, gender identity and expression, level of experience,
|
||||
nationality, personal appearance, race, religion, or sexual identity and
|
||||
orientation.
|
||||
|
||||
## Our Standards
|
||||
|
||||
Examples of behavior that contributes to creating a positive environment
|
||||
include:
|
||||
|
||||
* Using welcoming and inclusive language
|
||||
* Being respectful of differing viewpoints and experiences
|
||||
* Gracefully accepting constructive criticism
|
||||
* Focusing on what is best for the community
|
||||
* Showing empathy towards other community members
|
||||
|
||||
Examples of unacceptable behavior by participants include:
|
||||
|
||||
* The use of sexualized language or imagery and unwelcome sexual attention or
|
||||
advances
|
||||
* Trolling, insulting/derogatory comments, and personal or political attacks
|
||||
* Public or private harassment
|
||||
* Publishing others' private information, such as a physical or electronic
|
||||
address, without explicit permission
|
||||
* Other conduct which could reasonably be considered inappropriate in a
|
||||
professional setting
|
||||
|
||||
## Our Responsibilities
|
||||
|
||||
Project maintainers are responsible for clarifying the standards of acceptable
|
||||
behavior and are expected to take appropriate and fair corrective action in
|
||||
response to any instances of unacceptable behavior.
|
||||
|
||||
Project maintainers have the right and responsibility to remove, edit, or
|
||||
reject comments, commits, code, wiki edits, issues, and other contributions
|
||||
that are not aligned to this Code of Conduct, or to ban temporarily or
|
||||
permanently any contributor for other behaviors that they deem inappropriate,
|
||||
threatening, offensive, or harmful.
|
||||
|
||||
## Scope
|
||||
|
||||
This Code of Conduct applies both within project spaces and in public spaces
|
||||
when an individual is representing the project or its community. Examples of
|
||||
representing a project or community include using an official project e-mail
|
||||
address, posting via an official social media account, or acting as an appointed
|
||||
representative at an online or offline event. Representation of a project may be
|
||||
further defined and clarified by project maintainers.
|
||||
|
||||
## Enforcement
|
||||
|
||||
Instances of abusive, harassing, or otherwise unacceptable behavior may be
|
||||
reported by contacting the project team at <https://github.com/http-party/node-http-proxy>. All
|
||||
complaints will be reviewed and investigated and will result in a response that
|
||||
is deemed necessary and appropriate to the circumstances. The project team is
|
||||
obligated to maintain confidentiality with regard to the reporter of an incident.
|
||||
Further details of specific enforcement policies may be posted separately.
|
||||
|
||||
Project maintainers who do not follow or enforce the Code of Conduct in good
|
||||
faith may face temporary or permanent repercussions as determined by other
|
||||
members of the project's leadership.
|
||||
|
||||
## Attribution
|
||||
|
||||
This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4,
|
||||
available at [http://contributor-covenant.org/version/1/4][version]
|
||||
|
||||
[homepage]: http://contributor-covenant.org
|
||||
[version]: http://contributor-covenant.org/version/1/4/
|
||||
127
README.md
127
README.md
@ -1,16 +1,8 @@
|
||||
<p align="center">
|
||||
<img src="https://raw.github.com/nodejitsu/node-http-proxy/master/doc/logo.png"/>
|
||||
<img src="https://raw.github.com/http-party/node-http-proxy/master/doc/logo.png"/>
|
||||
</p>
|
||||
|
||||
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 [](https://travis-ci.org/http-party/node-http-proxy) [](https://codecov.io/gh/http-party/node-http-proxy)
|
||||
|
||||
`node-http-proxy` is an HTTP programmable proxying library that supports
|
||||
websockets. It is suitable for implementing components such as reverse
|
||||
@ -53,7 +45,7 @@ Click [here](UPGRADING.md)
|
||||
### Core Concept
|
||||
|
||||
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#L26-L42))
|
||||
|
||||
```javascript
|
||||
var httpProxy = require('http-proxy');
|
||||
@ -93,7 +85,7 @@ proxy.web(req, res, { target: 'http://mytarget.com:8080' }, function(e) { ... })
|
||||
|
||||
When a request is proxied it follows two different pipelines ([available here](lib/http-proxy/passes))
|
||||
which apply transformations to both the `req` and `res` object.
|
||||
The first pipeline (ingoing) is responsible for the creation and manipulation of the stream that connects your client to the target.
|
||||
The first pipeline (incoming) is responsible for the creation and manipulation of the stream that connects your client to the target.
|
||||
The second pipeline (outgoing) is responsible for the creation and manipulation of the stream that, from your target, returns data
|
||||
to the client.
|
||||
|
||||
@ -125,7 +117,7 @@ http.createServer(function (req, res) {
|
||||
**[Back to top](#table-of-contents)**
|
||||
|
||||
#### 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.
|
||||
|
||||
```js
|
||||
@ -145,7 +137,7 @@ var proxy = httpProxy.createProxyServer({});
|
||||
var server = http.createServer(function(req, res) {
|
||||
// You can define here your custom logic to handle the request
|
||||
// and then proxy the request.
|
||||
proxy.web(req, res, { target: 'http://127.0.0.1:5060' });
|
||||
proxy.web(req, res, { target: 'http://127.0.0.1:5050' });
|
||||
});
|
||||
|
||||
console.log("listening on port 5050")
|
||||
@ -183,7 +175,7 @@ var server = http.createServer(function(req, res) {
|
||||
// You can define here your custom logic to handle the request
|
||||
// and then proxy the request.
|
||||
proxy.web(req, res, {
|
||||
target: 'http://127.0.0.1:5060'
|
||||
target: 'http://127.0.0.1:5050'
|
||||
});
|
||||
});
|
||||
|
||||
@ -237,7 +229,7 @@ http.createServer(function (req, res) {
|
||||
**[Back to top](#table-of-contents)**
|
||||
|
||||
#### 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.
|
||||
|
||||
##### HTTPS -> HTTP
|
||||
|
||||
@ -273,6 +265,24 @@ httpProxy.createServer({
|
||||
}).listen(443);
|
||||
```
|
||||
|
||||
##### 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)**
|
||||
|
||||
#### Proxying WebSockets
|
||||
@ -333,11 +343,58 @@ proxyServer.listen(8015);
|
||||
* **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).
|
||||
* **localAddress**: Local interface string to bind for outgoing connections
|
||||
* **changeOrigin**: true/false, Default: false - changes the origin of the host header to the target URL
|
||||
* **preserveHeaderKeyCase**: true/false, Default: false - specify whether you want to keep letter case of response header key
|
||||
* **auth**: Basic authentication i.e. 'user:password' to compute an Authorization header.
|
||||
* **hostRewrite**: rewrites the location hostname on (301/302/307/308) redirects.
|
||||
* **autoRewrite**: rewrites the location host/port on (301/302/307/308) redirects based on requested host/port. Default: false.
|
||||
* **protocolRewrite**: rewrites the location protocol on (301/302/307/308) redirects to 'http' or 'https'. Default: null.
|
||||
* **hostRewrite**: rewrites the location hostname on (201/301/302/307/308) redirects.
|
||||
* **autoRewrite**: rewrites the location host/port on (201/301/302/307/308) redirects based on requested host/port. Default: false.
|
||||
* **protocolRewrite**: rewrites the location protocol on (201/301/302/307/308) redirects to 'http' or 'https'. Default: null.
|
||||
* **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",
|
||||
"*": ""
|
||||
}
|
||||
```
|
||||
* **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) 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:**
|
||||
`options.ws` and `options.ssl` are optional.
|
||||
@ -348,6 +405,7 @@ If you are using the `proxyServer.listen` method, the following options are also
|
||||
* **ssl**: object to be passed to https.createServer()
|
||||
* **ws**: true/false, if you want to proxy websockets
|
||||
|
||||
|
||||
**[Back to top](#table-of-contents)**
|
||||
|
||||
### Listening for proxy events
|
||||
@ -428,6 +486,36 @@ proxy.close();
|
||||
|
||||
### Miscellaneous
|
||||
|
||||
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 = [];
|
||||
proxyRes.on('data', function (chunk) {
|
||||
body.push(chunk);
|
||||
});
|
||||
proxyRes.on('end', function () {
|
||||
body = Buffer.concat(body).toString();
|
||||
console.log("res from proxied server:", body);
|
||||
res.end("my response to cli");
|
||||
});
|
||||
});
|
||||
proxy.web(req, res, option);
|
||||
|
||||
|
||||
```
|
||||
|
||||
#### ProxyTable API
|
||||
|
||||
A proxy table API is available through this add-on [module](https://github.com/donasaur/http-proxy-rules), which lets you define a set of rules to translate matching routes to target routes that the reverse proxy will talk to.
|
||||
@ -446,6 +534,7 @@ Logo created by [Diego Pasquali](http://dribbble.com/diegopq)
|
||||
|
||||
### Contributing and Issues
|
||||
|
||||
* Read carefully our [Code Of Conduct](https://github.com/http-party/node-http-proxy/blob/master/CODE_OF_CONDUCT.md)
|
||||
* Search on Google/Github
|
||||
* If you can't find anything, open an issue
|
||||
* If you feel comfortable about fixing the issue, fork the repo
|
||||
|
||||
@ -12,11 +12,11 @@ httpProxy.createServer({
|
||||
}).listen(8003);
|
||||
```
|
||||
|
||||
Check the [README.md](https://github.com/nodejitsu/node-http-proxy/blob/caronte/README.md) for a more detailed explanation of the parameters.
|
||||
Check the [README.md](https://github.com/http-party/node-http-proxy/blob/caronte/README.md) for a more detailed explanation of the parameters.
|
||||
|
||||
## Proxying
|
||||
|
||||
Web proxying is done by calling the `.web()` method on a Proxy instance. You can check among some use cases in the [examples folder](https://github.com/nodejitsu/node-http-proxy/tree/caronte/examples/http)
|
||||
Web proxying is done by calling the `.web()` method on a Proxy instance. You can check among some use cases in the [examples folder](https://github.com/http-party/node-http-proxy/tree/caronte/examples/http)
|
||||
|
||||
```javascript
|
||||
//
|
||||
@ -32,7 +32,7 @@ httpProxy.createProxyServer({
|
||||
|
||||
```
|
||||
|
||||
Websockets are proxied by the `.ws()` method. The [examples folder](https://github.com/nodejitsu/node-http-proxy/tree/caronte/examples/websocket) again provides a lot of useful snippets!
|
||||
Websockets are proxied by the `.ws()` method. The [examples folder](https://github.com/http-party/node-http-proxy/tree/caronte/examples/websocket) again provides a lot of useful snippets!
|
||||
|
||||
```javascript
|
||||
var proxy = new httpProxy.createProxyServer({
|
||||
@ -90,7 +90,7 @@ which were in the core and delegate them to eventual "userland" modules.
|
||||
|
||||
### Middleware API
|
||||
|
||||
The new API makes it really easy to implement code that behaves like the old Middleware API. You can check some examples [here](https://github.com/nodejitsu/node-http-proxy/tree/caronte/examples/middleware)
|
||||
The new API makes it really easy to implement code that behaves like the old Middleware API. You can check some examples [here](https://github.com/http-party/node-http-proxy/tree/caronte/examples/middleware)
|
||||
|
||||
### ProxyTable API
|
||||
|
||||
|
||||
10
codecov.yml
Normal file
10
codecov.yml
Normal file
@ -0,0 +1,10 @@
|
||||
coverage:
|
||||
parsers:
|
||||
javascript:
|
||||
enable_partials: yes
|
||||
status:
|
||||
project:
|
||||
default:
|
||||
target: "70%"
|
||||
patch:
|
||||
enabled: false
|
||||
@ -1,4 +1,4 @@
|
||||
var httpProxy = require('http-proxy');
|
||||
var httpProxy = require('../../lib/http-proxy');
|
||||
var Agent = require('agentkeepalive');
|
||||
|
||||
var agent = new Agent({
|
||||
@ -13,8 +13,8 @@ var agent = new Agent({
|
||||
var proxy = httpProxy.createProxy({ target: 'http://whatever.com', agent: agent });
|
||||
|
||||
//
|
||||
// Modify headers of the request before it gets sent
|
||||
// So that we handle the NLTM authentication request
|
||||
// Modify headers of the response before it gets sent
|
||||
// So that we handle the NLTM authentication response
|
||||
//
|
||||
proxy.on('proxyRes', function (proxyRes) {
|
||||
var key = 'www-authenticate';
|
||||
|
||||
@ -39,7 +39,7 @@ var https = require('https'),
|
||||
http.createServer(function (req, res) {
|
||||
res.writeHead(200, { 'Content-Type': 'text/plain' });
|
||||
res.write('hello http over https\n');
|
||||
res.end();
|
||||
res.end();
|
||||
}).listen(9009);
|
||||
|
||||
//
|
||||
|
||||
@ -43,7 +43,7 @@ var https = require('https'),
|
||||
https.createServer(httpsOpts, function (req, res) {
|
||||
res.writeHead(200, { 'Content-Type': 'text/plain' });
|
||||
res.write('hello https\n');
|
||||
res.end();
|
||||
res.end();
|
||||
}).listen(9010);
|
||||
|
||||
//
|
||||
|
||||
@ -23,7 +23,7 @@
|
||||
|
||||
var http = require('http'),
|
||||
net = require('net'),
|
||||
httpProxy = require('http-proxy'),
|
||||
httpProxy = require('../../lib/http-proxy'),
|
||||
url = require('url'),
|
||||
util = require('util');
|
||||
|
||||
@ -31,8 +31,9 @@ var proxy = httpProxy.createServer();
|
||||
|
||||
var server = http.createServer(function (req, res) {
|
||||
util.puts('Receiving reverse proxy request for:' + req.url);
|
||||
|
||||
proxy.web(req, res, {target: req.url, secure: false});
|
||||
var parsedUrl = url.parse(req.url);
|
||||
var target = parsedUrl.protocol + '//' + parsedUrl.hostname;
|
||||
proxy.web(req, res, {target: target, secure: false});
|
||||
}).listen(8213);
|
||||
|
||||
server.on('connect', function (req, socket) {
|
||||
|
||||
@ -29,33 +29,42 @@ var http = require('http'),
|
||||
request = require('request'),
|
||||
colors = require('colors'),
|
||||
util = require('util'),
|
||||
queryString = require('querystring'),
|
||||
bodyParser = require('body-parser'),
|
||||
httpProxy = require('../../lib/http-proxy'),
|
||||
proxy = httpProxy.createProxyServer({});
|
||||
|
||||
|
||||
//restreame
|
||||
var restreamer = function (){
|
||||
return function (req, res, next) { //restreame
|
||||
req.removeAllListeners('data')
|
||||
req.removeAllListeners('end')
|
||||
next()
|
||||
process.nextTick(function () {
|
||||
if(req.body) {
|
||||
req.emit('data', JSON.stringify(req.body))
|
||||
}
|
||||
req.emit('end')
|
||||
})
|
||||
//restream parsed body before proxying
|
||||
proxy.on('proxyReq', function(proxyReq, req, res, options) {
|
||||
if (!req.body || !Object.keys(req.body).length) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
var contentType = proxyReq.getHeader('Content-Type');
|
||||
var bodyData;
|
||||
|
||||
if (contentType === 'application/json') {
|
||||
bodyData = JSON.stringify(req.body);
|
||||
}
|
||||
|
||||
if (contentType === 'application/x-www-form-urlencoded') {
|
||||
bodyData = queryString.stringify(req.body);
|
||||
}
|
||||
|
||||
if (bodyData) {
|
||||
proxyReq.setHeader('Content-Length', Buffer.byteLength(bodyData));
|
||||
proxyReq.write(bodyData);
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
//
|
||||
// Basic Http Proxy Server
|
||||
//
|
||||
var app = connect()
|
||||
.use(bodyParser.json())//json
|
||||
.use(restreamer())//restreame
|
||||
.use(bodyParser.json())//json parser
|
||||
.use(bodyParser.urlencoded())//urlencoded parser
|
||||
.use(function(req, res){
|
||||
// modify body here,
|
||||
// eg: req.body = {a: 1}.
|
||||
@ -84,10 +93,16 @@ http.createServer(app1).listen(9013, function(){
|
||||
//request to 8013 to proxy
|
||||
request.post({//
|
||||
url: 'http://127.0.0.1:8013',
|
||||
json: {content: 123, type: "greeting"}
|
||||
json: {content: 123, type: "greeting from json request"}
|
||||
},function(err, res,data){
|
||||
console.log('return:' ,err, data)
|
||||
console.log('return for json request:' ,err, data)
|
||||
})
|
||||
|
||||
// application/x-www-form-urlencoded request
|
||||
request.post({//
|
||||
url: 'http://127.0.0.1:8013',
|
||||
form: {content: 123, type: "greeting from urlencoded request"}
|
||||
},function(err, res,data){
|
||||
console.log('return for urlencoded request:' ,err, data)
|
||||
})
|
||||
});
|
||||
|
||||
|
||||
|
||||
@ -28,24 +28,26 @@ var util = require('util'),
|
||||
colors = require('colors'),
|
||||
http = require('http'),
|
||||
connect = require('connect'),
|
||||
app = connect(),
|
||||
httpProxy = require('../../lib/http-proxy');
|
||||
|
||||
//
|
||||
// Basic Connect App
|
||||
//
|
||||
connect.createServer(
|
||||
function (req, res, next) {
|
||||
var _write = res.write;
|
||||
app.use(function (req, res, next) {
|
||||
var _write = res.write;
|
||||
|
||||
res.write = function (data) {
|
||||
_write.call(res, data.toString().replace("Ruby", "nodejitsu"));
|
||||
}
|
||||
next();
|
||||
},
|
||||
function (req, res) {
|
||||
proxy.web(req, res);
|
||||
res.write = function (data) {
|
||||
_write.call(res, data.toString().replace("Ruby", "http-party"));
|
||||
}
|
||||
).listen(8013);
|
||||
next();
|
||||
});
|
||||
|
||||
app.use(function (req, res) {
|
||||
proxy.web(req, res)
|
||||
});
|
||||
|
||||
http.createServer(app).listen(8013);
|
||||
|
||||
//
|
||||
// Basic Http Proxy Server
|
||||
@ -59,7 +61,7 @@ var proxy = httpProxy.createProxyServer({
|
||||
//
|
||||
http.createServer(function (req, res) {
|
||||
res.writeHead(200, { 'Content-Type': 'text/plain' });
|
||||
res.end('Hello, I know Ruby\n');
|
||||
res.end('Hello, I love Ruby\n');
|
||||
}).listen(9013);
|
||||
|
||||
util.puts('http proxy server'.blue + ' started '.green.bold + 'on port '.blue + '8013'.yellow);
|
||||
|
||||
@ -3,13 +3,12 @@
|
||||
"description": "packages required to run the examples",
|
||||
"version": "0.0.0",
|
||||
"dependencies": {
|
||||
"agentkeepalive": "^2.0.3",
|
||||
"colors": "~0.6.2",
|
||||
"connect": "~2.11.0",
|
||||
"agentkeepalive": "^4.0.0",
|
||||
"colors": "~1.3.0",
|
||||
"connect-restreamer": "~1.0.0",
|
||||
"request": "~2.27.0",
|
||||
"request": "~2.88.0",
|
||||
"socket.io": "~0.9.16",
|
||||
"socket.io-client": "~0.9.16",
|
||||
"sse": "0.0.6"
|
||||
"sse": "0.0.8"
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,12 +1,6 @@
|
||||
var http = require('http'),
|
||||
https = require('https'),
|
||||
url = require('url'),
|
||||
httpProxy = require('./http-proxy/');
|
||||
// Use explicit /index.js to help browserify negociation in require '/lib/http-proxy' (!)
|
||||
var ProxyServer = require('./http-proxy/index.js').Server;
|
||||
|
||||
/**
|
||||
* Export the proxy "Server" as the main export.
|
||||
*/
|
||||
module.exports = httpProxy.Server;
|
||||
|
||||
/**
|
||||
* Creates the proxy server.
|
||||
@ -23,9 +17,8 @@ module.exports = httpProxy.Server;
|
||||
* @api public
|
||||
*/
|
||||
|
||||
module.exports.createProxyServer =
|
||||
module.exports.createServer =
|
||||
module.exports.createProxy = function createProxyServer(options) {
|
||||
|
||||
function createProxyServer(options) {
|
||||
/*
|
||||
* `options` is needed and it must have the following layout:
|
||||
*
|
||||
@ -42,10 +35,11 @@ module.exports.createProxyServer =
|
||||
* ignorePath: <true/false, Default: false - specify whether you want to ignore the proxy path of the incoming request>
|
||||
* localAddress : <Local interface string to bind for outgoing connections>
|
||||
* changeOrigin: <true/false, Default: false - changes the origin of the host header to the target URL>
|
||||
* auth : Basic authentication i.e. 'user:password' to compute an Authorization header.
|
||||
* hostRewrite: rewrites the location hostname on (301/302/307/308) redirects, Default: null.
|
||||
* autoRewrite: rewrites the location host/port on (301/302/307/308) redirects based on requested host/port. Default: false.
|
||||
* protocolRewrite: rewrites the location protocol on (301/302/307/308) redirects to 'http' or 'https'. Default: null.
|
||||
* preserveHeaderKeyCase: <true/false, Default: false - specify whether you want to keep letter case of response header key >
|
||||
* auth : Basic authentication i.e. 'user:password' to compute an Authorization header.
|
||||
* hostRewrite: rewrites the location hostname on (201/301/302/307/308) redirects, Default: null.
|
||||
* autoRewrite: rewrites the location host/port on (201/301/302/307/308) redirects based on requested host/port. Default: false.
|
||||
* protocolRewrite: rewrites the location protocol on (201/301/302/307/308) redirects to 'http' or 'https'. Default: null.
|
||||
* }
|
||||
*
|
||||
* NOTE: `options.ws` and `options.ssl` are optional.
|
||||
@ -54,6 +48,19 @@ module.exports.createProxyServer =
|
||||
* }
|
||||
*/
|
||||
|
||||
return new httpProxy.Server(options);
|
||||
};
|
||||
return new ProxyServer(options);
|
||||
}
|
||||
|
||||
|
||||
ProxyServer.createProxyServer = createProxyServer;
|
||||
ProxyServer.createServer = createProxyServer;
|
||||
ProxyServer.createProxy = createProxyServer;
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Export the proxy "Server" as the main export.
|
||||
*/
|
||||
module.exports = ProxyServer;
|
||||
|
||||
|
||||
@ -39,7 +39,7 @@ common.setupOutgoing = function(outgoing, options, req, forward) {
|
||||
function(e) { outgoing[e] = options[forward || 'target'][e]; }
|
||||
);
|
||||
|
||||
outgoing.method = req.method;
|
||||
outgoing.method = options.method || req.method;
|
||||
outgoing.headers = extend({}, req.headers);
|
||||
|
||||
if (options.headers){
|
||||
@ -49,6 +49,10 @@ common.setupOutgoing = function(outgoing, options, req, forward) {
|
||||
if (options.auth) {
|
||||
outgoing.auth = options.auth;
|
||||
}
|
||||
|
||||
if (options.ca) {
|
||||
outgoing.ca = options.ca;
|
||||
}
|
||||
|
||||
if (isSSL.test(options[forward || 'target'].protocol)) {
|
||||
outgoing.rejectUnauthorized = (typeof options.secure === "undefined") ? true : options.secure;
|
||||
@ -197,6 +201,41 @@ common.urlJoin = function() {
|
||||
return retSegs.join('?')
|
||||
};
|
||||
|
||||
/**
|
||||
* Rewrites or removes the domain of a cookie header
|
||||
*
|
||||
* @param {String|Array} Header
|
||||
* @param {Object} Config, mapping of domain to rewritten domain.
|
||||
* '*' key to match any domain, null value to remove the domain.
|
||||
*
|
||||
* @api private
|
||||
*/
|
||||
common.rewriteCookieProperty = function rewriteCookieProperty(header, config, property) {
|
||||
if (Array.isArray(header)) {
|
||||
return header.map(function (headerElement) {
|
||||
return rewriteCookieProperty(headerElement, config, property);
|
||||
});
|
||||
}
|
||||
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) {
|
||||
newValue = config['*'];
|
||||
} else {
|
||||
//no match, return previous value
|
||||
return match;
|
||||
}
|
||||
if (newValue) {
|
||||
//replace value
|
||||
return prefix + newValue;
|
||||
} else {
|
||||
//remove value
|
||||
return '';
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Check the host and see if it potentially has a port in it (keep it simple)
|
||||
*
|
||||
|
||||
@ -41,14 +41,15 @@ function createRightProxy(type) {
|
||||
cntr--;
|
||||
}
|
||||
|
||||
var requestOptions = options;
|
||||
if(
|
||||
!(args[cntr] instanceof Buffer) &&
|
||||
args[cntr] !== res
|
||||
) {
|
||||
//Copy global options
|
||||
options = extend({}, options);
|
||||
requestOptions = extend({}, options);
|
||||
//Overwrite with request options
|
||||
extend(options, args[cntr]);
|
||||
extend(requestOptions, args[cntr]);
|
||||
|
||||
cntr--;
|
||||
}
|
||||
@ -60,11 +61,11 @@ function createRightProxy(type) {
|
||||
/* optional args parse end */
|
||||
|
||||
['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'));
|
||||
}
|
||||
|
||||
@ -77,7 +78,7 @@ function createRightProxy(type) {
|
||||
* refer to the connection socket
|
||||
* pass(req, socket, options, head)
|
||||
*/
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,13 +1,15 @@
|
||||
var http = require('http'),
|
||||
https = require('https'),
|
||||
var httpNative = require('http'),
|
||||
httpsNative = require('https'),
|
||||
web_o = require('./web-outgoing'),
|
||||
common = require('../common'),
|
||||
passes = exports;
|
||||
followRedirects = require('follow-redirects');
|
||||
|
||||
web_o = Object.keys(web_o).map(function(pass) {
|
||||
return web_o[pass];
|
||||
});
|
||||
|
||||
var nativeAgents = { http: httpNative, https: httpsNative };
|
||||
|
||||
/*!
|
||||
* Array of passes.
|
||||
*
|
||||
@ -16,7 +18,8 @@ web_o = Object.keys(web_o).map(function(pass) {
|
||||
* flexible.
|
||||
*/
|
||||
|
||||
[ // <--
|
||||
|
||||
module.exports = {
|
||||
|
||||
/**
|
||||
* Sets `content-length` to '0' if request is of DELETE type.
|
||||
@ -28,7 +31,7 @@ web_o = Object.keys(web_o).map(function(pass) {
|
||||
* @api private
|
||||
*/
|
||||
|
||||
function deleteLength(req, res, options) {
|
||||
deleteLength: function deleteLength(req, res, options) {
|
||||
if((req.method === 'DELETE' || req.method === 'OPTIONS')
|
||||
&& !req.headers['content-length']) {
|
||||
req.headers['content-length'] = '0';
|
||||
@ -46,7 +49,7 @@ web_o = Object.keys(web_o).map(function(pass) {
|
||||
* @api private
|
||||
*/
|
||||
|
||||
function timeout(req, res, options) {
|
||||
timeout: function timeout(req, res, options) {
|
||||
if(options.timeout) {
|
||||
req.socket.setTimeout(options.timeout);
|
||||
}
|
||||
@ -62,7 +65,7 @@ web_o = Object.keys(web_o).map(function(pass) {
|
||||
* @api private
|
||||
*/
|
||||
|
||||
function XHeaders(req, res, options) {
|
||||
XHeaders: function XHeaders(req, res, options) {
|
||||
if(!options.xfwd) return;
|
||||
|
||||
var encrypted = req.isSpdy || common.hasEncryptedConnection(req);
|
||||
@ -78,8 +81,8 @@ web_o = Object.keys(web_o).map(function(pass) {
|
||||
(req.headers['x-forwarded-' + header] ? ',' : '') +
|
||||
values[header];
|
||||
});
|
||||
|
||||
req.headers['x-forwarded-host'] = req.headers['host'];
|
||||
|
||||
req.headers['x-forwarded-host'] = req.headers['x-forwarded-host'] || req.headers['host'] || '';
|
||||
},
|
||||
|
||||
/**
|
||||
@ -94,15 +97,27 @@ web_o = Object.keys(web_o).map(function(pass) {
|
||||
* @api private
|
||||
*/
|
||||
|
||||
function stream(req, res, options, _, server, clb) {
|
||||
stream: function stream(req, res, options, _, server, clb) {
|
||||
|
||||
// And we begin!
|
||||
server.emit('start', req, res, options.target)
|
||||
server.emit('start', req, res, options.target || options.forward);
|
||||
|
||||
var agents = options.followRedirects ? followRedirects : nativeAgents;
|
||||
var http = agents.http;
|
||||
var https = agents.https;
|
||||
|
||||
if(options.forward) {
|
||||
// If forward enable, so just pipe the request
|
||||
var forwardReq = (options.forward.protocol === 'https:' ? https : http).request(
|
||||
common.setupOutgoing(options.ssl || {}, options, req, 'forward')
|
||||
);
|
||||
|
||||
// error handler (e.g. ECONNRESET, ECONNREFUSED)
|
||||
// Handle errors on incoming request as well as it makes sense to
|
||||
var forwardError = createErrorHandler(forwardReq, options.forward);
|
||||
req.on('error', forwardError);
|
||||
forwardReq.on('error', forwardError);
|
||||
|
||||
(options.buffer || req).pipe(forwardReq);
|
||||
if(!options.target) { return res.end(); }
|
||||
}
|
||||
@ -114,7 +129,9 @@ web_o = Object.keys(web_o).map(function(pass) {
|
||||
|
||||
// Enable developers to modify the proxyReq before headers are sent
|
||||
proxyReq.on('socket', function(socket) {
|
||||
if(server) { server.emit('proxyReq', proxyReq, req, res, options); }
|
||||
if(server && !proxyReq.getHeader('expect')) {
|
||||
server.emit('proxyReq', proxyReq, req, res, options);
|
||||
}
|
||||
});
|
||||
|
||||
// allow outgoing socket to timeout so that we could
|
||||
@ -130,22 +147,23 @@ web_o = Object.keys(web_o).map(function(pass) {
|
||||
proxyReq.abort();
|
||||
});
|
||||
|
||||
// Handle errors on incoming request as well as it makes sense to
|
||||
// handle errors in proxy and incoming request, just like for forward proxy
|
||||
var proxyError = createErrorHandler(proxyReq, options.target);
|
||||
req.on('error', proxyError);
|
||||
|
||||
// Error Handler
|
||||
proxyReq.on('error', proxyError);
|
||||
|
||||
function proxyError (err){
|
||||
if (req.socket.destroyed && err.code === 'ECONNRESET') {
|
||||
server.emit('econnreset', err, req, res, options.target);
|
||||
return proxyReq.abort();
|
||||
}
|
||||
function createErrorHandler(proxyReq, url) {
|
||||
return function proxyError(err) {
|
||||
if (req.socket.destroyed && err.code === 'ECONNRESET') {
|
||||
server.emit('econnreset', err, req, res, url);
|
||||
return proxyReq.abort();
|
||||
}
|
||||
|
||||
if (clb) {
|
||||
clb(err, req, res, options.target);
|
||||
} else {
|
||||
server.emit('error', err, req, res, options.target);
|
||||
if (clb) {
|
||||
clb(err, req, res, url);
|
||||
} else {
|
||||
server.emit('error', err, req, res, url);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -153,22 +171,24 @@ web_o = Object.keys(web_o).map(function(pass) {
|
||||
|
||||
proxyReq.on('response', function(proxyRes) {
|
||||
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();
|
||||
}
|
||||
|
||||
] // <--
|
||||
.forEach(function(func) {
|
||||
passes[func.name] = func;
|
||||
});
|
||||
};
|
||||
|
||||
@ -1,7 +1,8 @@
|
||||
var url = require('url'),
|
||||
passes = exports;
|
||||
common = require('../common');
|
||||
|
||||
var redirectRegex = /^30(1|2|7|8)$/;
|
||||
|
||||
var redirectRegex = /^201|30(1|2|7|8)$/;
|
||||
|
||||
/*!
|
||||
* Array of passes.
|
||||
@ -11,7 +12,7 @@ var redirectRegex = /^30(1|2|7|8)$/;
|
||||
* flexible.
|
||||
*/
|
||||
|
||||
[ // <--
|
||||
module.exports = { // <--
|
||||
|
||||
/**
|
||||
* If is a HTTP 1.0 request, remove chunk headers
|
||||
@ -22,7 +23,7 @@ var redirectRegex = /^30(1|2|7|8)$/;
|
||||
*
|
||||
* @api private
|
||||
*/
|
||||
function removeChunked(req, res, proxyRes) {
|
||||
removeChunked: function removeChunked(req, res, proxyRes) {
|
||||
if (req.httpVersion === '1.0') {
|
||||
delete proxyRes.headers['transfer-encoding'];
|
||||
}
|
||||
@ -38,15 +39,15 @@ var redirectRegex = /^30(1|2|7|8)$/;
|
||||
*
|
||||
* @api private
|
||||
*/
|
||||
function setConnection(req, res, proxyRes) {
|
||||
setConnection: function setConnection(req, res, proxyRes) {
|
||||
if (req.httpVersion === '1.0') {
|
||||
proxyRes.headers.connection = req.headers.connection || 'close';
|
||||
} else if (!proxyRes.headers.connection) {
|
||||
} else if (req.httpVersion !== '2.0' && !proxyRes.headers.connection) {
|
||||
proxyRes.headers.connection = req.headers.connection || 'keep-alive';
|
||||
}
|
||||
},
|
||||
|
||||
function setRedirectHostRewrite(req, res, proxyRes, options) {
|
||||
setRedirectHostRewrite: function setRedirectHostRewrite(req, res, proxyRes, options) {
|
||||
if ((options.hostRewrite || options.autoRewrite || options.protocolRewrite)
|
||||
&& proxyRes.headers['location']
|
||||
&& redirectRegex.test(proxyRes.statusCode)) {
|
||||
@ -77,14 +78,50 @@ var redirectRegex = /^30(1|2|7|8)$/;
|
||||
* @param {ClientRequest} Req Request object
|
||||
* @param {IncomingMessage} Res Response object
|
||||
* @param {proxyResponse} Res Response object from the proxy request
|
||||
* @param {Object} Options options.cookieDomainRewrite: Config to rewrite cookie domain
|
||||
*
|
||||
* @api private
|
||||
*/
|
||||
function writeHeaders(req, res, proxyRes) {
|
||||
Object.keys(proxyRes.headers).forEach(function(key) {
|
||||
if(proxyRes.headers[key] != undefined){
|
||||
res.setHeader(String(key).trim(), proxyRes.headers[key]);
|
||||
writeHeaders: function writeHeaders(req, res, proxyRes, options) {
|
||||
var rewriteCookieDomainConfig = options.cookieDomainRewrite,
|
||||
rewriteCookiePathConfig = options.cookiePathRewrite,
|
||||
preserveHeaderKeyCase = options.preserveHeaderKeyCase,
|
||||
rawHeaderKeyMap,
|
||||
setHeader = function(key, header) {
|
||||
if (header == undefined) return;
|
||||
if (rewriteCookieDomainConfig && key.toLowerCase() === 'set-cookie') {
|
||||
header = common.rewriteCookieProperty(header, rewriteCookieDomainConfig, 'domain');
|
||||
}
|
||||
if (rewriteCookiePathConfig && key.toLowerCase() === 'set-cookie') {
|
||||
header = common.rewriteCookieProperty(header, rewriteCookiePathConfig, 'path');
|
||||
}
|
||||
res.setHeader(String(key).trim(), header);
|
||||
};
|
||||
|
||||
if (typeof rewriteCookieDomainConfig === 'string') { //also test for ''
|
||||
rewriteCookieDomainConfig = { '*': rewriteCookieDomainConfig };
|
||||
}
|
||||
|
||||
if (typeof rewriteCookiePathConfig === 'string') { //also test for ''
|
||||
rewriteCookiePathConfig = { '*': rewriteCookiePathConfig };
|
||||
}
|
||||
|
||||
// message.rawHeaders is added in: v0.11.6
|
||||
// https://nodejs.org/api/http.html#http_message_rawheaders
|
||||
if (preserveHeaderKeyCase && proxyRes.rawHeaders != undefined) {
|
||||
rawHeaderKeyMap = {};
|
||||
for (var i = 0; i < proxyRes.rawHeaders.length; i += 2) {
|
||||
var key = proxyRes.rawHeaders[i];
|
||||
rawHeaderKeyMap[key.toLowerCase()] = key;
|
||||
}
|
||||
}
|
||||
|
||||
Object.keys(proxyRes.headers).forEach(function(key) {
|
||||
var header = proxyRes.headers[key];
|
||||
if (preserveHeaderKeyCase && rawHeaderKeyMap) {
|
||||
key = rawHeaderKeyMap[key] || key;
|
||||
}
|
||||
setHeader(key, header);
|
||||
});
|
||||
},
|
||||
|
||||
@ -97,11 +134,14 @@ var redirectRegex = /^30(1|2|7|8)$/;
|
||||
*
|
||||
* @api private
|
||||
*/
|
||||
function writeStatusCode(req, res, proxyRes) {
|
||||
res.writeHead(proxyRes.statusCode);
|
||||
writeStatusCode: function writeStatusCode(req, res, proxyRes) {
|
||||
// From Node.js docs: response.writeHead(statusCode[, statusMessage][, headers])
|
||||
if(proxyRes.statusMessage) {
|
||||
res.statusCode = proxyRes.statusCode;
|
||||
res.statusMessage = proxyRes.statusMessage;
|
||||
} else {
|
||||
res.statusCode = proxyRes.statusCode;
|
||||
}
|
||||
}
|
||||
|
||||
] // <--
|
||||
.forEach(function(func) {
|
||||
passes[func.name] = func;
|
||||
});
|
||||
};
|
||||
|
||||
@ -1,7 +1,6 @@
|
||||
var http = require('http'),
|
||||
https = require('https'),
|
||||
common = require('../common'),
|
||||
passes = exports;
|
||||
common = require('../common');
|
||||
|
||||
/*!
|
||||
* Array of passes.
|
||||
@ -16,9 +15,8 @@ var http = require('http'),
|
||||
*
|
||||
*/
|
||||
|
||||
var passes = exports;
|
||||
|
||||
[
|
||||
module.exports = {
|
||||
/**
|
||||
* WebSocket requests must have the `GET` method and
|
||||
* the `upgrade:websocket` header
|
||||
@ -29,7 +27,7 @@ var passes = exports;
|
||||
* @api private
|
||||
*/
|
||||
|
||||
function checkMethodAndHeader (req, socket) {
|
||||
checkMethodAndHeader : function checkMethodAndHeader(req, socket) {
|
||||
if (req.method !== 'GET' || !req.headers.upgrade) {
|
||||
socket.destroy();
|
||||
return true;
|
||||
@ -51,7 +49,7 @@ var passes = exports;
|
||||
* @api private
|
||||
*/
|
||||
|
||||
function XHeaders(req, socket, options) {
|
||||
XHeaders : function XHeaders(req, socket, options) {
|
||||
if(!options.xfwd) return;
|
||||
|
||||
var values = {
|
||||
@ -78,7 +76,25 @@ var passes = exports;
|
||||
*
|
||||
* @api private
|
||||
*/
|
||||
function stream(req, socket, options, head, server, clb) {
|
||||
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);
|
||||
|
||||
if (head && head.length) socket.unshift(head);
|
||||
@ -95,7 +111,10 @@ var passes = exports;
|
||||
proxyReq.on('error', onOutgoingError);
|
||||
proxyReq.on('response', function (res) {
|
||||
// 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);
|
||||
}
|
||||
});
|
||||
|
||||
proxyReq.on('upgrade', function(proxyRes, proxySocket, proxyHead) {
|
||||
@ -121,22 +140,7 @@ var passes = exports;
|
||||
// Remark: Handle writing the headers to the socket when switching protocols
|
||||
// Also handles when a header is an array
|
||||
//
|
||||
socket.write(
|
||||
Object.keys(proxyRes.headers).reduce(function (head, key) {
|
||||
var value = proxyRes.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;
|
||||
}, ['HTTP/1.1 101 Switching Protocols'])
|
||||
.join('\r\n') + '\r\n\r\n'
|
||||
);
|
||||
socket.write(createHttpHeader('HTTP/1.1 101 Switching Protocols', proxyRes.headers));
|
||||
|
||||
proxySocket.pipe(socket).pipe(proxySocket);
|
||||
|
||||
@ -155,8 +159,4 @@ var passes = exports;
|
||||
socket.end();
|
||||
}
|
||||
}
|
||||
|
||||
] // <--
|
||||
.forEach(function(func) {
|
||||
passes[func.name] = func;
|
||||
});
|
||||
};
|
||||
|
||||
2028
package-lock.json
generated
Normal file
2028
package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load Diff
41
package.json
41
package.json
@ -1,9 +1,9 @@
|
||||
{
|
||||
"name": "http-proxy",
|
||||
"version": "1.14.0",
|
||||
"version": "1.18.1",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/nodejitsu/node-http-proxy.git"
|
||||
"url": "https://github.com/http-party/node-http-proxy.git"
|
||||
},
|
||||
"description": "HTTP proxying for the masses",
|
||||
"author": "Charlie Robbins <charlie.robbins@gmail.com>",
|
||||
@ -12,33 +12,30 @@
|
||||
],
|
||||
"main": "index.js",
|
||||
"dependencies": {
|
||||
"eventemitter3": "1.x.x",
|
||||
"requires-port": "1.x.x"
|
||||
"eventemitter3": "^4.0.0",
|
||||
"requires-port": "^1.0.0",
|
||||
"follow-redirects": "^1.0.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"async": "*",
|
||||
"blanket": "*",
|
||||
"coveralls": "*",
|
||||
"dox": "*",
|
||||
"expect.js": "*",
|
||||
"mocha": "*",
|
||||
"mocha-lcov-reporter": "*",
|
||||
"async": "^3.0.0",
|
||||
"auto-changelog": "^1.15.0",
|
||||
"concat-stream": "^2.0.0",
|
||||
"expect.js": "~0.3.1",
|
||||
"mocha": "^3.5.3",
|
||||
"nyc": "^14.0.0",
|
||||
"semver": "^5.0.3",
|
||||
"socket.io": "*",
|
||||
"socket.io-client": "*",
|
||||
"sse": "0.0.6",
|
||||
"ws": "^0.8.0"
|
||||
"socket.io": "^2.1.0",
|
||||
"socket.io-client": "^2.1.0",
|
||||
"sse": "0.0.8",
|
||||
"ws": "^3.0.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",
|
||||
"version": "auto-changelog -p && git add CHANGELOG.md"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=0.10.0"
|
||||
"node": ">=8.0.0"
|
||||
},
|
||||
"license": "MIT"
|
||||
}
|
||||
|
||||
19
renovate.json
Normal file
19
renovate.json
Normal file
@ -0,0 +1,19 @@
|
||||
{
|
||||
"platform": "github",
|
||||
"autodiscover": false,
|
||||
"requireConfig": true,
|
||||
"ignoreNpmrcFile": true,
|
||||
"rangeStrategy": "replace",
|
||||
"packageRules": [
|
||||
{
|
||||
"packagePatterns": [
|
||||
"*"
|
||||
],
|
||||
"minor": {
|
||||
"groupName": "all non-major dependencies",
|
||||
"groupSlug": "all-minor-patch"
|
||||
}
|
||||
}
|
||||
],
|
||||
"commitMessagePrefix": "[dist]"
|
||||
}
|
||||
34
test/fixtures/agent2-cert.pem
vendored
34
test/fixtures/agent2-cert.pem
vendored
@ -1,13 +1,25 @@
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIIB7DCCAZYCCQC7gs0MDNn6MTANBgkqhkiG9w0BAQUFADB9MQswCQYDVQQGEwJV
|
||||
UzELMAkGA1UECBMCQ0ExCzAJBgNVBAcTAlNGMQ8wDQYDVQQKEwZKb3llbnQxEDAO
|
||||
BgNVBAsTB05vZGUuanMxDzANBgNVBAMTBmFnZW50MjEgMB4GCSqGSIb3DQEJARYR
|
||||
cnlAdGlueWNsb3Vkcy5vcmcwHhcNMTEwMzE0MTgyOTEyWhcNMzgwNzI5MTgyOTEy
|
||||
WjB9MQswCQYDVQQGEwJVUzELMAkGA1UECBMCQ0ExCzAJBgNVBAcTAlNGMQ8wDQYD
|
||||
VQQKEwZKb3llbnQxEDAOBgNVBAsTB05vZGUuanMxDzANBgNVBAMTBmFnZW50MjEg
|
||||
MB4GCSqGSIb3DQEJARYRcnlAdGlueWNsb3Vkcy5vcmcwXDANBgkqhkiG9w0BAQEF
|
||||
AANLADBIAkEAyXb8FrRdKbhrKLgLSsn61i1C7w7fVVVd7OQsmV/7p9WB2lWFiDlC
|
||||
WKGU9SiIz/A6wNZDUAuc2E+VwtpCT561AQIDAQABMA0GCSqGSIb3DQEBBQUAA0EA
|
||||
C8HzpuNhFLCI3A5KkBS5zHAQax6TFUOhbpBCR0aTDbJ6F1liDTK1lmU/BjvPoj+9
|
||||
1LHwrmh29rK8kBPEjmymCQ==
|
||||
MIIEIDCCAggCCQChRDh/XiBF+zANBgkqhkiG9w0BAQsFADBUMQswCQYDVQQGEwJ1
|
||||
czETMBEGA1UECAwKV2FzaGluZ3RvbjEQMA4GA1UEBwwHU2VhdHRsZTEeMBwGA1UE
|
||||
AwwVRHVtbXkgSW50ZXJtZWRpYXRlIENBMB4XDTE4MDYyMjIwMzEwNFoXDTMyMDIy
|
||||
OTIwMzEwNFowUDELMAkGA1UEBhMCdXMxEzARBgNVBAgMCldhc2hpbmd0b24xEDAO
|
||||
BgNVBAcMB1NlYXR0bGUxGjAYBgNVBAMMEWR1bW15LmV4YW1wbGUuY29tMIIBIjAN
|
||||
BgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAvSQq3d8AeZMTvtqZ13jWCckikyXJ
|
||||
SACvkGCQUCJqOceESbg6IHdRzQdoccE4P3sbvNsf9BlbdJKM+neCxabqKaU1PPje
|
||||
4P0tHT57t6yJrMuUh9NxEz3Bgh1srNHVS7saKvwHmcKm79jc+wxlioPmEQvQagjn
|
||||
y7oTkyLt0sn4LGxBjrcv2JoHOC9f1pxX7l47MaiN0/ctRau7Nr3PFn+pkB4Yf6Z0
|
||||
VyicVJbaUSz39Qo4HQWl1L2hiBP3CS1oKs2Yk0O1aOCMExWrhZQan+ZgHqL1rhgm
|
||||
kPpw2/zwwPt5Vf9CSakvHwg198EXuTTXtkzYduuIJAm8yp969iEIiG2xTwIDAQAB
|
||||
MA0GCSqGSIb3DQEBCwUAA4ICAQBnMSIo+kujkeXPh+iErFBmNtu/7EA+i/QnFPbN
|
||||
lSLngclYYBJAGQI+DhirJI8ghDi6vmlHB2THewDaOJXEKvC1czE8064wioIcA9HJ
|
||||
l3QJ3YYOFRctYdSHBU4TWdJbPgkLWDzYP5smjOfw8nDdr4WO/5jh9qRFcFpTFmQf
|
||||
DyU3xgWLsQnNK3qXLdJjWG75pEhHR+7TGo+Ob/RUho/1RX/P89Ux7/oVbzdKqqFu
|
||||
SErXAsjEIEFzWOM2uDOt6hrxDF6q+8/zudwQNEo422poEcTT9tDEFxMQ391CzZRi
|
||||
nozBm4igRn1f5S3YZzLI6VEUns0s76BNy2CzvFWn40DziTqNBExAMfFFj76wiMsX
|
||||
6fTIdcvkaTBa0S9SZB0vN99qahBdcG17rt4RssMHVRH1Wn7NXMwe476L0yXZ6gO7
|
||||
Z4uNAPxgaI3BRP75EPfslLutCLZ+BC4Zzu6MY0Salbpfl0Go462EhsKCxvYhE2Dg
|
||||
T477pICLfETZfA499Fd1tOaIsoLCrILAia/+Yd76uf94MuXUIqykDng/4H7xCc47
|
||||
BZhNFJiPC6XHaXzN7NYSEUNX9VOwY8ncxKwtP6TXga96PdMUy/p98KIM8RZlDoxB
|
||||
Xy9dcZBFNn/zrqjW7R0CCWCUriDIFSmEP0wDZ91YYa6BVuJMb5uL/USkTLpjZS4/
|
||||
HNGvug==
|
||||
-----END CERTIFICATE-----
|
||||
|
||||
10
test/fixtures/agent2-csr.pem
vendored
10
test/fixtures/agent2-csr.pem
vendored
@ -1,10 +0,0 @@
|
||||
-----BEGIN CERTIFICATE REQUEST-----
|
||||
MIIBXTCCAQcCAQAwfTELMAkGA1UEBhMCVVMxCzAJBgNVBAgTAkNBMQswCQYDVQQH
|
||||
EwJTRjEPMA0GA1UEChMGSm95ZW50MRAwDgYDVQQLEwdOb2RlLmpzMQ8wDQYDVQQD
|
||||
EwZhZ2VudDIxIDAeBgkqhkiG9w0BCQEWEXJ5QHRpbnljbG91ZHMub3JnMFwwDQYJ
|
||||
KoZIhvcNAQEBBQADSwAwSAJBAMl2/Ba0XSm4ayi4C0rJ+tYtQu8O31VVXezkLJlf
|
||||
+6fVgdpVhYg5QlihlPUoiM/wOsDWQ1ALnNhPlcLaQk+etQECAwEAAaAlMCMGCSqG
|
||||
SIb3DQEJBzEWExRBIGNoYWxsZW5nZSBwYXNzd29yZDANBgkqhkiG9w0BAQUFAANB
|
||||
AJnll2pt5l0pzskQSpjjLVTlFDFmJr/AZ3UK8v0WxBjYjCe5Jx4YehkChpxIyDUm
|
||||
U3J9q9MDUf0+Y2+EGkssFfk=
|
||||
-----END CERTIFICATE REQUEST-----
|
||||
32
test/fixtures/agent2-key.pem
vendored
32
test/fixtures/agent2-key.pem
vendored
@ -1,9 +1,27 @@
|
||||
-----BEGIN RSA PRIVATE KEY-----
|
||||
MIIBOgIBAAJBAMl2/Ba0XSm4ayi4C0rJ+tYtQu8O31VVXezkLJlf+6fVgdpVhYg5
|
||||
QlihlPUoiM/wOsDWQ1ALnNhPlcLaQk+etQECAwEAAQJBAMT6Bf34+UHKY1ObpsbH
|
||||
9u2jsVblFq1rWvs8GPMY6oertzvwm3DpuSUp7PTgOB1nLTLYtCERbQ4ovtN8tn3p
|
||||
OHUCIQDzIEGsoCr5vlxXvy2zJwu+fxYuhTZWMVuo1397L0VyhwIhANQh+yzqUgaf
|
||||
WRtSB4T2W7ADtJI35ET61jKBty3CqJY3AiAIwju7dVW3A5WeD6Qc1SZGKZvp9yCb
|
||||
AFI2BfVwwaY11wIgXF3PeGcvACMyMWsuSv7aPXHfliswAbkWuzcwA4TW01ECIGWa
|
||||
cgsDvVFxmfM5NPSuT/UDTa6R5BFISB5ea0N0AR3I
|
||||
MIIEpQIBAAKCAQEAvSQq3d8AeZMTvtqZ13jWCckikyXJSACvkGCQUCJqOceESbg6
|
||||
IHdRzQdoccE4P3sbvNsf9BlbdJKM+neCxabqKaU1PPje4P0tHT57t6yJrMuUh9Nx
|
||||
Ez3Bgh1srNHVS7saKvwHmcKm79jc+wxlioPmEQvQagjny7oTkyLt0sn4LGxBjrcv
|
||||
2JoHOC9f1pxX7l47MaiN0/ctRau7Nr3PFn+pkB4Yf6Z0VyicVJbaUSz39Qo4HQWl
|
||||
1L2hiBP3CS1oKs2Yk0O1aOCMExWrhZQan+ZgHqL1rhgmkPpw2/zwwPt5Vf9CSakv
|
||||
Hwg198EXuTTXtkzYduuIJAm8yp969iEIiG2xTwIDAQABAoIBAGPIw/C/qJF7HYyv
|
||||
6T+7GTiaa2o0IiehbP3/Y8NTFLWc49a8obXlHTvMr7Zr2I/tE+ojtIzkH9K1SjkN
|
||||
eelqsNj9tsOPDI6oIvftsflpxkxqLtclnt8m0oMhoObf4OaONDT/N8dP4SBiSdsM
|
||||
ZDmacnMFx5NZVWiup4sVf2CYexx7qks9FhyN2K5PArCQ4S9LHjFhSJVH4DSEpv7E
|
||||
Ykbp30rhpqV7wSwjgUsm8ZYvI2NOlmffzLSiPdt3vy2K5Q25S/MVEAicg83rfDgK
|
||||
6EluHjeygRI1xU6DJ0hU7tnU7zE9KURoHPUycO3BKzZnzUH26AA36I58Pu4fXWw/
|
||||
Cgmbv2ECgYEA+og9E4ziKCEi3p8gqjIfwTRgWZxDLjEzooB/K0UhEearn/xiX29A
|
||||
FiSzEHKfCB4uSrw5OENg2ckDs8uy08Qmxx7xFXL7AtufAl5fIYaWa0sNSqCaIk7p
|
||||
ebbUmPcaYhKiLzIEd1EYEL38sXVZ62wvSVMRSWvEMq44g1qnoRlDa/8CgYEAwUTt
|
||||
talYNwVmR9ZdkVEWm9ZxirdzoM6NaM6u4Tf34ygptpapdmIFSUhfq4iOiEnRGNg/
|
||||
tuNqhNCIb3LNpJbhRPEzqN7E7qiF/mp7AcJgbuxLZBm12QuLuJdG3nrisKPFXcY1
|
||||
lA4A7CFmNgH3E4THFfgwzyDXsBOxVLXleTqn+rECgYEA9up1P6J3dtOJuV2d5P/3
|
||||
ugRz/X173LfTSxJXw36jZDAy8D/feG19/RT4gnplcKvGNhQiVOhbOOnbw0U8n2fQ
|
||||
TCmbs+cZqyxnH/+AxNsPvvk+RVHZ93xMsY/XIldP4l65B8jFDA+Zp06IESI2mEeM
|
||||
pzi+bd1Phh+dRSCA2865W2MCgYEAlxYsgmQ1WyX0dFpHYU+zzfXRYzDQyrhOYc2Z
|
||||
duVK+yCto1iad7pfCY/zgmRJkI+sT7DV9kJIRjXDQuTLkEyHJF8vFGe6KhxCS8aw
|
||||
DIsI2g4NTd6vg1J8UryoIUqNpqsQoqNNxUVBQVdG0ReuMGsPO8R/W50AIFz0txVP
|
||||
o/rP0LECgYEA7e/mOwCnR+ovmS/CAksmos3oIqvkRkXNKpKe513FVmp3TpTU38ex
|
||||
cBkFNU3hEO31FyrX1hGIKp3N5mHYSQ1lyODHM6teHW0OLWWTwIe8rIGvR2jfRLe0
|
||||
bbkdj40atYVkfeFmpz9uHHG24CUYxJdPc360jbXTVp4i3q8zqgL5aMY=
|
||||
-----END RSA PRIVATE KEY-----
|
||||
|
||||
19
test/fixtures/agent2.cnf
vendored
19
test/fixtures/agent2.cnf
vendored
@ -1,19 +0,0 @@
|
||||
[ req ]
|
||||
default_bits = 1024
|
||||
days = 999
|
||||
distinguished_name = req_distinguished_name
|
||||
attributes = req_attributes
|
||||
prompt = no
|
||||
|
||||
[ req_distinguished_name ]
|
||||
C = US
|
||||
ST = CA
|
||||
L = SF
|
||||
O = Joyent
|
||||
OU = Node.js
|
||||
CN = agent2
|
||||
emailAddress = ry@tinyclouds.org
|
||||
|
||||
[ req_attributes ]
|
||||
challengePassword = A challenge password
|
||||
|
||||
@ -251,7 +251,7 @@ describe('lib/http-proxy/common.js', function () {
|
||||
|
||||
expect(outgoing.path).to.eql('/' + google);
|
||||
});
|
||||
|
||||
|
||||
it('should not replace :\ to :\\ when no http word before', function () {
|
||||
var outgoing = {};
|
||||
var google = 'http://google.com:/join/join.js'
|
||||
@ -262,7 +262,7 @@ describe('lib/http-proxy/common.js', function () {
|
||||
|
||||
expect(outgoing.path).to.eql('/' + google);
|
||||
});
|
||||
|
||||
|
||||
describe('when using ignorePath', function () {
|
||||
it('should ignore the path of the `req.url` passed in but use the target path', function () {
|
||||
var outgoing = {};
|
||||
@ -347,6 +347,16 @@ describe('lib/http-proxy/common.js', function () {
|
||||
expect(outgoing.secureProtocol).eql('my-secure-protocol');
|
||||
});
|
||||
|
||||
it('should handle overriding the `method` of the http request', function () {
|
||||
var outgoing = {};
|
||||
common.setupOutgoing(outgoing, {
|
||||
target: url.parse('https://whooooo.com'),
|
||||
method: 'POST' ,
|
||||
}, { method: 'GET', url: '' });
|
||||
|
||||
expect(outgoing.method).eql('POST');
|
||||
});
|
||||
|
||||
// url.parse('').path => null
|
||||
it('should not pass null as last arg to #urlJoin', function(){
|
||||
var outgoing = {};
|
||||
|
||||
@ -1,6 +1,9 @@
|
||||
var webPasses = require('../lib/http-proxy/passes/web-incoming'),
|
||||
httpProxy = require('../lib/http-proxy'),
|
||||
expect = require('expect.js'),
|
||||
concat = require('concat-stream'),
|
||||
async = require('async'),
|
||||
url = require('url'),
|
||||
http = require('http');
|
||||
|
||||
describe('lib/http-proxy/passes/web.js', function() {
|
||||
@ -123,6 +126,50 @@ describe('#createProxyServer.web() using own http server', function () {
|
||||
http.request('http://127.0.0.1:8081', function() {}).end();
|
||||
});
|
||||
|
||||
it('should skip proxyReq event when handling a request with header "expect: 100-continue" [https://www.npmjs.com/advisories/1486]', function (done) {
|
||||
var proxy = httpProxy.createProxyServer({
|
||||
target: 'http://127.0.0.1:8080',
|
||||
});
|
||||
|
||||
proxy.on('proxyReq', function(proxyReq, req, res, options) {
|
||||
proxyReq.setHeader('X-Special-Proxy-Header', 'foobar');
|
||||
});
|
||||
|
||||
function requestHandler(req, res) {
|
||||
proxy.web(req, res);
|
||||
}
|
||||
|
||||
var proxyServer = http.createServer(requestHandler);
|
||||
|
||||
var source = http.createServer(function(req, res) {
|
||||
source.close();
|
||||
proxyServer.close();
|
||||
expect(req.headers['x-special-proxy-header']).to.not.eql('foobar');
|
||||
done();
|
||||
});
|
||||
|
||||
proxyServer.listen('8081');
|
||||
source.listen('8080');
|
||||
|
||||
const postData = ''.padStart(1025, 'x');
|
||||
|
||||
const postOptions = {
|
||||
hostname: '127.0.0.1',
|
||||
port: 8081,
|
||||
path: '/',
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/x-www-form-urlencoded',
|
||||
'Content-Length': Buffer.byteLength(postData),
|
||||
'expect': '100-continue'
|
||||
}
|
||||
};
|
||||
|
||||
const req = http.request(postOptions, function() {});
|
||||
req.write(postData);
|
||||
req.end();
|
||||
});
|
||||
|
||||
it('should proxy the request and handle error via callback', function(done) {
|
||||
var proxy = httpProxy.createProxyServer({
|
||||
target: 'http://127.0.0.1:8080'
|
||||
@ -177,6 +224,35 @@ describe('#createProxyServer.web() using own http server', function () {
|
||||
}, function() {}).end();
|
||||
});
|
||||
|
||||
it('should forward the request and handle error via event listener', function(done) {
|
||||
var proxy = httpProxy.createProxyServer({
|
||||
forward: 'http://127.0.0.1:8080'
|
||||
});
|
||||
|
||||
var proxyServer = http.createServer(requestHandler);
|
||||
|
||||
function requestHandler(req, res) {
|
||||
proxy.once('error', function (err, errReq, errRes) {
|
||||
proxyServer.close();
|
||||
expect(err).to.be.an(Error);
|
||||
expect(errReq).to.be.equal(req);
|
||||
expect(errRes).to.be.equal(res);
|
||||
expect(err.code).to.be('ECONNREFUSED');
|
||||
done();
|
||||
});
|
||||
|
||||
proxy.web(req, res);
|
||||
}
|
||||
|
||||
proxyServer.listen('8083');
|
||||
|
||||
http.request({
|
||||
hostname: '127.0.0.1',
|
||||
port: '8083',
|
||||
method: 'GET',
|
||||
}, function() {}).end();
|
||||
});
|
||||
|
||||
it('should proxy the request and handle timeout error (proxyTimeout)', function(done) {
|
||||
var proxy = httpProxy.createProxyServer({
|
||||
target: 'http://127.0.0.1:45000',
|
||||
@ -286,6 +362,44 @@ describe('#createProxyServer.web() using own http server', function () {
|
||||
http.request('http://127.0.0.1:8086', function() {}).end();
|
||||
});
|
||||
|
||||
it('should proxy the request and provide and respond to manual user response when using modifyResponse', function(done) {
|
||||
var proxy = httpProxy.createProxyServer({
|
||||
target: 'http://127.0.0.1:8080',
|
||||
selfHandleResponse: true
|
||||
});
|
||||
|
||||
function requestHandler(req, res) {
|
||||
proxy.once('proxyRes', function (proxyRes, pReq, pRes) {
|
||||
proxyRes.pipe(concat(function (body) {
|
||||
expect(body.toString('utf8')).eql('Response');
|
||||
pRes.end(Buffer.from('my-custom-response'));
|
||||
}))
|
||||
});
|
||||
|
||||
proxy.web(req, res);
|
||||
}
|
||||
|
||||
var proxyServer = http.createServer(requestHandler);
|
||||
|
||||
var source = http.createServer(function(req, res) {
|
||||
res.end('Response');
|
||||
});
|
||||
|
||||
async.parallel([
|
||||
next => proxyServer.listen(8086, next),
|
||||
next => source.listen(8080, next)
|
||||
], function (err) {
|
||||
http.get('http://127.0.0.1:8086', function(res) {
|
||||
res.pipe(concat(function(body) {
|
||||
expect(body.toString('utf8')).eql('my-custom-response');
|
||||
source.close();
|
||||
proxyServer.close();
|
||||
done();
|
||||
}));
|
||||
}).once('error', done);
|
||||
})
|
||||
});
|
||||
|
||||
it('should proxy the request and handle changeOrigin option', function (done) {
|
||||
var proxy = httpProxy.createProxyServer({
|
||||
target: 'http://127.0.0.1:8080',
|
||||
@ -338,4 +452,85 @@ describe('#createProxyServer.web() using own http server', function () {
|
||||
|
||||
http.request('http://127.0.0.1:8081', function() {}).end();
|
||||
});
|
||||
|
||||
it('should proxy requests to multiple servers with different options', function (done) {
|
||||
var proxy = httpProxy.createProxyServer();
|
||||
|
||||
// proxies to two servers depending on url, rewriting the url as well
|
||||
// http://127.0.0.1:8080/s1/ -> http://127.0.0.1:8081/
|
||||
// http://127.0.0.1:8080/ -> http://127.0.0.1:8082/
|
||||
function requestHandler(req, res) {
|
||||
if (req.url.indexOf('/s1/') === 0) {
|
||||
proxy.web(req, res, {
|
||||
ignorePath: true,
|
||||
target: 'http://127.0.0.1:8081' + req.url.substring(3)
|
||||
});
|
||||
} else {
|
||||
proxy.web(req, res, {
|
||||
target: 'http://127.0.0.1:8082'
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
var proxyServer = http.createServer(requestHandler);
|
||||
|
||||
var source1 = http.createServer(function(req, res) {
|
||||
expect(req.method).to.eql('GET');
|
||||
expect(req.headers.host.split(':')[1]).to.eql('8080');
|
||||
expect(req.url).to.eql('/test1');
|
||||
});
|
||||
|
||||
var source2 = http.createServer(function(req, res) {
|
||||
source1.close();
|
||||
source2.close();
|
||||
proxyServer.close();
|
||||
expect(req.method).to.eql('GET');
|
||||
expect(req.headers.host.split(':')[1]).to.eql('8080');
|
||||
expect(req.url).to.eql('/test2');
|
||||
done();
|
||||
});
|
||||
|
||||
proxyServer.listen('8080');
|
||||
source1.listen('8081');
|
||||
source2.listen('8082');
|
||||
|
||||
http.request('http://127.0.0.1:8080/s1/test1', function() {}).end();
|
||||
http.request('http://127.0.0.1:8080/test2', function() {}).end();
|
||||
});
|
||||
});
|
||||
|
||||
describe('#followRedirects', function () {
|
||||
it('should proxy the request follow redirects', function (done) {
|
||||
var proxy = httpProxy.createProxyServer({
|
||||
target: 'http://127.0.0.1:8080',
|
||||
followRedirects: true
|
||||
});
|
||||
|
||||
function requestHandler(req, res) {
|
||||
proxy.web(req, res);
|
||||
}
|
||||
|
||||
var proxyServer = http.createServer(requestHandler);
|
||||
|
||||
var source = http.createServer(function(req, res) {
|
||||
|
||||
if (url.parse(req.url).pathname === '/redirect') {
|
||||
res.writeHead(200, { 'Content-Type': 'text/plain' });
|
||||
res.end('ok');
|
||||
}
|
||||
|
||||
res.writeHead(301, { 'Location': '/redirect' });
|
||||
res.end();
|
||||
});
|
||||
|
||||
proxyServer.listen('8081');
|
||||
source.listen('8080');
|
||||
|
||||
http.request('http://127.0.0.1:8081', function(res) {
|
||||
source.close();
|
||||
proxyServer.close();
|
||||
expect(res.statusCode).to.eql(200);
|
||||
done();
|
||||
}).end();
|
||||
});
|
||||
});
|
||||
|
||||
@ -6,25 +6,25 @@ describe('lib/http-proxy/passes/web-outgoing.js', function () {
|
||||
beforeEach(function() {
|
||||
this.req = {
|
||||
headers: {
|
||||
host: "ext-auto.com"
|
||||
host: 'ext-auto.com'
|
||||
}
|
||||
};
|
||||
this.proxyRes = {
|
||||
statusCode: 301,
|
||||
headers: {
|
||||
location: "http://backend.com/"
|
||||
location: 'http://backend.com/'
|
||||
}
|
||||
};
|
||||
this.options = {
|
||||
target: "http://backend.com"
|
||||
target: 'http://backend.com'
|
||||
};
|
||||
});
|
||||
|
||||
context('rewrites location host with hostRewrite', function() {
|
||||
beforeEach(function() {
|
||||
this.options.hostRewrite = "ext-manual.com";
|
||||
this.options.hostRewrite = 'ext-manual.com';
|
||||
});
|
||||
[301, 302, 307, 308].forEach(function(code) {
|
||||
[201, 301, 302, 307, 308].forEach(function(code) {
|
||||
it('on ' + code, function() {
|
||||
this.proxyRes.statusCode = code;
|
||||
httpProxy.setRedirectHostRewrite(this.req, {}, this.proxyRes, this.options);
|
||||
@ -52,14 +52,14 @@ describe('lib/http-proxy/passes/web-outgoing.js', function () {
|
||||
|
||||
it('not when the redirected location does not match target host', function() {
|
||||
this.proxyRes.statusCode = 302;
|
||||
this.proxyRes.headers.location = "http://some-other/";
|
||||
this.proxyRes.headers.location = 'http://some-other/';
|
||||
httpProxy.setRedirectHostRewrite(this.req, {}, this.proxyRes, this.options);
|
||||
expect(this.proxyRes.headers.location).to.eql('http://some-other/');
|
||||
});
|
||||
|
||||
it('not when the redirected location does not match target port', function() {
|
||||
this.proxyRes.statusCode = 302;
|
||||
this.proxyRes.headers.location = "http://backend.com:8080/";
|
||||
this.proxyRes.headers.location = 'http://backend.com:8080/';
|
||||
httpProxy.setRedirectHostRewrite(this.req, {}, this.proxyRes, this.options);
|
||||
expect(this.proxyRes.headers.location).to.eql('http://backend.com:8080/');
|
||||
});
|
||||
@ -69,7 +69,7 @@ describe('lib/http-proxy/passes/web-outgoing.js', function () {
|
||||
beforeEach(function() {
|
||||
this.options.autoRewrite = true;
|
||||
});
|
||||
[301, 302, 307, 308].forEach(function(code) {
|
||||
[201, 301, 302, 307, 308].forEach(function(code) {
|
||||
it('on ' + code, function() {
|
||||
this.proxyRes.statusCode = code;
|
||||
httpProxy.setRedirectHostRewrite(this.req, {}, this.proxyRes, this.options);
|
||||
@ -91,14 +91,14 @@ describe('lib/http-proxy/passes/web-outgoing.js', function () {
|
||||
|
||||
it('not when the redirected location does not match target host', function() {
|
||||
this.proxyRes.statusCode = 302;
|
||||
this.proxyRes.headers.location = "http://some-other/";
|
||||
this.proxyRes.headers.location = 'http://some-other/';
|
||||
httpProxy.setRedirectHostRewrite(this.req, {}, this.proxyRes, this.options);
|
||||
expect(this.proxyRes.headers.location).to.eql('http://some-other/');
|
||||
});
|
||||
|
||||
it('not when the redirected location does not match target port', function() {
|
||||
this.proxyRes.statusCode = 302;
|
||||
this.proxyRes.headers.location = "http://backend.com:8080/";
|
||||
this.proxyRes.headers.location = 'http://backend.com:8080/';
|
||||
httpProxy.setRedirectHostRewrite(this.req, {}, this.proxyRes, this.options);
|
||||
expect(this.proxyRes.headers.location).to.eql('http://backend.com:8080/');
|
||||
});
|
||||
@ -108,7 +108,7 @@ describe('lib/http-proxy/passes/web-outgoing.js', function () {
|
||||
beforeEach(function() {
|
||||
this.options.protocolRewrite = 'https';
|
||||
});
|
||||
[301, 302, 307, 308].forEach(function(code) {
|
||||
[201, 301, 302, 307, 308].forEach(function(code) {
|
||||
it('on ' + code, function() {
|
||||
this.proxyRes.statusCode = code;
|
||||
httpProxy.setRedirectHostRewrite(this.req, {}, this.proxyRes, this.options);
|
||||
@ -129,13 +129,13 @@ describe('lib/http-proxy/passes/web-outgoing.js', function () {
|
||||
});
|
||||
|
||||
it('works together with hostRewrite', function() {
|
||||
this.options.hostRewrite = 'ext-manual.com'
|
||||
this.options.hostRewrite = 'ext-manual.com';
|
||||
httpProxy.setRedirectHostRewrite(this.req, {}, this.proxyRes, this.options);
|
||||
expect(this.proxyRes.headers.location).to.eql('https://ext-manual.com/');
|
||||
});
|
||||
|
||||
it('works together with autoRewrite', function() {
|
||||
this.options.autoRewrite = true
|
||||
this.options.autoRewrite = true;
|
||||
httpProxy.setRedirectHostRewrite(this.req, {}, this.proxyRes, this.options);
|
||||
expect(this.proxyRes.headers.location).to.eql('https://ext-auto.com/');
|
||||
});
|
||||
@ -191,6 +191,28 @@ describe('lib/http-proxy/passes/web-outgoing.js', function () {
|
||||
expect(proxyRes.headers.connection).to.eql('keep-alive');
|
||||
});
|
||||
|
||||
it('don`t set connection with 2.0 if exist', function() {
|
||||
var proxyRes = { headers: {} };
|
||||
httpProxy.setConnection({
|
||||
httpVersion: '2.0',
|
||||
headers: {
|
||||
connection: 'namstey'
|
||||
}
|
||||
}, {}, proxyRes);
|
||||
|
||||
expect(proxyRes.headers.connection).to.eql(undefined);
|
||||
});
|
||||
|
||||
it('don`t set connection with 2.0 if doesn`t exist', function() {
|
||||
var proxyRes = { headers: {} };
|
||||
httpProxy.setConnection({
|
||||
httpVersion: '2.0',
|
||||
headers: {}
|
||||
}, {}, proxyRes);
|
||||
|
||||
expect(proxyRes.headers.connection).to.eql(undefined);
|
||||
})
|
||||
|
||||
});
|
||||
|
||||
describe('#writeStatusCode', function () {
|
||||
@ -199,31 +221,189 @@ describe('lib/http-proxy/passes/web-outgoing.js', function () {
|
||||
writeHead: function(n) {
|
||||
expect(n).to.eql(200);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
httpProxy.writeStatusCode({}, res, { statusCode: 200 });
|
||||
});
|
||||
});
|
||||
|
||||
describe('#writeHeaders', function() {
|
||||
var proxyRes = {
|
||||
headers: {
|
||||
hey: 'hello',
|
||||
how: 'are you?'
|
||||
}
|
||||
};
|
||||
beforeEach(function() {
|
||||
this.proxyRes = {
|
||||
headers: {
|
||||
hey: 'hello',
|
||||
how: 'are you?',
|
||||
'set-cookie': [
|
||||
'hello; domain=my.domain; path=/',
|
||||
'there; domain=my.domain; path=/'
|
||||
]
|
||||
}
|
||||
};
|
||||
this.rawProxyRes = {
|
||||
headers: {
|
||||
hey: 'hello',
|
||||
how: 'are you?',
|
||||
'set-cookie': [
|
||||
'hello; domain=my.domain; path=/',
|
||||
'there; domain=my.domain; path=/'
|
||||
]
|
||||
},
|
||||
rawHeaders: [
|
||||
'Hey', 'hello',
|
||||
'How', 'are you?',
|
||||
'Set-Cookie', 'hello; domain=my.domain; path=/',
|
||||
'Set-Cookie', 'there; domain=my.domain; path=/'
|
||||
]
|
||||
};
|
||||
this.res = {
|
||||
setHeader: function(k, v) {
|
||||
// https://nodejs.org/api/http.html#http_message_headers
|
||||
// Header names are lower-cased
|
||||
this.headers[k.toLowerCase()] = v;
|
||||
},
|
||||
headers: {}
|
||||
};
|
||||
});
|
||||
|
||||
var res = {
|
||||
setHeader: function(k, v) {
|
||||
this.headers[k] = v;
|
||||
},
|
||||
headers: {}
|
||||
};
|
||||
it('writes headers', function() {
|
||||
var options = {};
|
||||
httpProxy.writeHeaders({}, this.res, this.proxyRes, options);
|
||||
|
||||
httpProxy.writeHeaders({}, res, proxyRes);
|
||||
expect(this.res.headers.hey).to.eql('hello');
|
||||
expect(this.res.headers.how).to.eql('are you?');
|
||||
|
||||
expect(res.headers.hey).to.eql('hello');
|
||||
expect(res.headers.how).to.eql('are you?');
|
||||
expect(this.res.headers).to.have.key('set-cookie');
|
||||
expect(this.res.headers['set-cookie']).to.be.an(Array);
|
||||
expect(this.res.headers['set-cookie']).to.have.length(2);
|
||||
});
|
||||
|
||||
it('writes raw headers', function() {
|
||||
var options = {};
|
||||
httpProxy.writeHeaders({}, this.res, this.rawProxyRes, options);
|
||||
|
||||
expect(this.res.headers.hey).to.eql('hello');
|
||||
expect(this.res.headers.how).to.eql('are you?');
|
||||
|
||||
expect(this.res.headers).to.have.key('set-cookie');
|
||||
expect(this.res.headers['set-cookie']).to.be.an(Array);
|
||||
expect(this.res.headers['set-cookie']).to.have.length(2);
|
||||
});
|
||||
|
||||
it('rewrites path', function() {
|
||||
var options = {
|
||||
cookiePathRewrite: '/dummyPath'
|
||||
};
|
||||
|
||||
httpProxy.writeHeaders({}, this.res, this.proxyRes, options);
|
||||
|
||||
expect(this.res.headers['set-cookie'])
|
||||
.to.contain('hello; domain=my.domain; path=/dummyPath');
|
||||
});
|
||||
|
||||
it('does not rewrite path', function() {
|
||||
var options = {};
|
||||
|
||||
httpProxy.writeHeaders({}, this.res, this.proxyRes, options);
|
||||
|
||||
expect(this.res.headers['set-cookie'])
|
||||
.to.contain('hello; domain=my.domain; path=/');
|
||||
});
|
||||
|
||||
it('removes path', function() {
|
||||
var options = {
|
||||
cookiePathRewrite: ''
|
||||
};
|
||||
|
||||
httpProxy.writeHeaders({}, this.res, this.proxyRes, options);
|
||||
|
||||
expect(this.res.headers['set-cookie'])
|
||||
.to.contain('hello; domain=my.domain');
|
||||
});
|
||||
|
||||
it('does not rewrite domain', function() {
|
||||
var options = {};
|
||||
|
||||
httpProxy.writeHeaders({}, this.res, this.proxyRes, options);
|
||||
|
||||
expect(this.res.headers['set-cookie'])
|
||||
.to.contain('hello; domain=my.domain; path=/');
|
||||
});
|
||||
|
||||
it('rewrites domain', function() {
|
||||
var options = {
|
||||
cookieDomainRewrite: 'my.new.domain'
|
||||
};
|
||||
|
||||
httpProxy.writeHeaders({}, this.res, this.proxyRes, options);
|
||||
|
||||
expect(this.res.headers['set-cookie'])
|
||||
.to.contain('hello; domain=my.new.domain; path=/');
|
||||
});
|
||||
|
||||
it('removes domain', function() {
|
||||
var options = {
|
||||
cookieDomainRewrite: ''
|
||||
};
|
||||
|
||||
httpProxy.writeHeaders({}, this.res, this.proxyRes, options);
|
||||
|
||||
expect(this.res.headers['set-cookie'])
|
||||
.to.contain('hello; path=/');
|
||||
});
|
||||
|
||||
it('rewrites headers with advanced configuration', function() {
|
||||
var options = {
|
||||
cookieDomainRewrite: {
|
||||
'*': '',
|
||||
'my.old.domain': 'my.new.domain',
|
||||
'my.special.domain': 'my.special.domain'
|
||||
}
|
||||
};
|
||||
this.proxyRes.headers['set-cookie'] = [
|
||||
'hello-on-my.domain; domain=my.domain; path=/',
|
||||
'hello-on-my.old.domain; domain=my.old.domain; path=/',
|
||||
'hello-on-my.special.domain; domain=my.special.domain; path=/'
|
||||
];
|
||||
httpProxy.writeHeaders({}, this.res, this.proxyRes, options);
|
||||
|
||||
expect(this.res.headers['set-cookie'])
|
||||
.to.contain('hello-on-my.domain; path=/');
|
||||
expect(this.res.headers['set-cookie'])
|
||||
.to.contain('hello-on-my.old.domain; domain=my.new.domain; path=/');
|
||||
expect(this.res.headers['set-cookie'])
|
||||
.to.contain('hello-on-my.special.domain; domain=my.special.domain; path=/');
|
||||
});
|
||||
|
||||
it('rewrites raw headers with advanced configuration', function() {
|
||||
var options = {
|
||||
cookieDomainRewrite: {
|
||||
'*': '',
|
||||
'my.old.domain': 'my.new.domain',
|
||||
'my.special.domain': 'my.special.domain'
|
||||
}
|
||||
};
|
||||
this.rawProxyRes.headers['set-cookie'] = [
|
||||
'hello-on-my.domain; domain=my.domain; path=/',
|
||||
'hello-on-my.old.domain; domain=my.old.domain; path=/',
|
||||
'hello-on-my.special.domain; domain=my.special.domain; path=/'
|
||||
];
|
||||
this.rawProxyRes.rawHeaders = this.rawProxyRes.rawHeaders.concat([
|
||||
'Set-Cookie',
|
||||
'hello-on-my.domain; domain=my.domain; path=/',
|
||||
'Set-Cookie',
|
||||
'hello-on-my.old.domain; domain=my.old.domain; path=/',
|
||||
'Set-Cookie',
|
||||
'hello-on-my.special.domain; domain=my.special.domain; path=/'
|
||||
]);
|
||||
httpProxy.writeHeaders({}, this.res, this.rawProxyRes, options);
|
||||
|
||||
expect(this.res.headers['set-cookie'])
|
||||
.to.contain('hello-on-my.domain; path=/');
|
||||
expect(this.res.headers['set-cookie'])
|
||||
.to.contain('hello-on-my.old.domain; domain=my.new.domain; path=/');
|
||||
expect(this.res.headers['set-cookie'])
|
||||
.to.contain('hello-on-my.special.domain; domain=my.special.domain; path=/');
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
@ -241,4 +421,3 @@ describe('lib/http-proxy/passes/web-outgoing.js', function () {
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
|
||||
@ -1,7 +1,8 @@
|
||||
var httpProxy = require('../lib/http-proxy'),
|
||||
expect = require('expect.js'),
|
||||
http = require('http'),
|
||||
ws = require('ws')
|
||||
net = require('net'),
|
||||
ws = require('ws'),
|
||||
io = require('socket.io'),
|
||||
SSE = require('sse'),
|
||||
ioClient = require('socket.io-client');
|
||||
@ -17,7 +18,6 @@ Object.defineProperty(gen, 'port', {
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
describe('lib/http-proxy.js', function() {
|
||||
describe('#createProxyServer', function() {
|
||||
it.skip('should throw without options', function() {
|
||||
@ -130,7 +130,8 @@ describe('lib/http-proxy.js', function() {
|
||||
it('should make the request, handle response and finish it', function(done) {
|
||||
var ports = { source: gen.port, proxy: gen.port };
|
||||
var proxy = httpProxy.createProxyServer({
|
||||
target: 'http://127.0.0.1:' + ports.source
|
||||
target: 'http://127.0.0.1:' + ports.source,
|
||||
preserveHeaderKeyCase: true
|
||||
}).listen(ports.proxy);
|
||||
|
||||
var source = http.createServer(function(req, res) {
|
||||
@ -148,6 +149,11 @@ describe('lib/http-proxy.js', function() {
|
||||
method: 'GET'
|
||||
}, function(res) {
|
||||
expect(res.statusCode).to.eql(200);
|
||||
expect(res.headers['content-type']).to.eql('text/plain');
|
||||
if (res.rawHeaders != undefined) {
|
||||
expect(res.rawHeaders.indexOf('Content-Type')).not.to.eql(-1);
|
||||
expect(res.rawHeaders.indexOf('text/plain')).not.to.eql(-1);
|
||||
}
|
||||
|
||||
res.on('data', function (data) {
|
||||
expect(data.toString()).to.eql('Hello from ' + ports.source);
|
||||
@ -223,11 +229,54 @@ describe('lib/http-proxy.js', function() {
|
||||
});
|
||||
|
||||
testReq.end();
|
||||
});
|
||||
});
|
||||
|
||||
describe('#createProxyServer with xfwd option', function () {
|
||||
it('should not throw on empty http host header', function (done) {
|
||||
var ports = { source: gen.port, proxy: gen.port };
|
||||
var proxy = httpProxy.createProxyServer({
|
||||
forward: 'http://127.0.0.1:' + ports.source,
|
||||
xfwd: true
|
||||
}).listen(ports.proxy);
|
||||
|
||||
var source = http.createServer(function(req, res) {
|
||||
expect(req.method).to.eql('GET');
|
||||
expect(req.headers.host.split(':')[1]).to.eql(ports.source);
|
||||
source.close();
|
||||
proxy.close();
|
||||
done();
|
||||
});
|
||||
|
||||
source.listen(ports.source);
|
||||
|
||||
var socket = net.connect({port: ports.proxy}, function()
|
||||
{
|
||||
socket.write('GET / HTTP/1.0\r\n\r\n');
|
||||
});
|
||||
|
||||
// handle errors
|
||||
socket.on('error', function()
|
||||
{
|
||||
expect.fail('Unexpected socket error');
|
||||
});
|
||||
|
||||
socket.on('data', function(data)
|
||||
{
|
||||
socket.end();
|
||||
});
|
||||
|
||||
socket.on('end', function()
|
||||
{
|
||||
expect('Socket to finish').to.be.ok();
|
||||
});
|
||||
|
||||
// http.request('http://127.0.0.1:' + ports.proxy, function() {}).end();
|
||||
})
|
||||
})
|
||||
});
|
||||
|
||||
// describe('#createProxyServer using the web-incoming passes', function () {
|
||||
// it('should emit events correclty', function(done) {
|
||||
// it('should emit events correctly', function(done) {
|
||||
// var proxy = httpProxy.createProxyServer({
|
||||
// target: 'http://127.0.0.1:8080'
|
||||
// }),
|
||||
@ -366,7 +415,6 @@ describe('lib/http-proxy.js', function() {
|
||||
|
||||
client.on('error', function (err) {
|
||||
expect(err).to.be.an(Error);
|
||||
expect(err.code).to.be('ECONNRESET');
|
||||
proxyServer.close();
|
||||
done();
|
||||
});
|
||||
@ -434,6 +482,7 @@ describe('lib/http-proxy.js', function() {
|
||||
proxyServer.on('close', function() {
|
||||
proxyServer.close();
|
||||
server.close();
|
||||
destiny.close();
|
||||
if (count == 1) { done(); }
|
||||
});
|
||||
|
||||
@ -451,7 +500,7 @@ describe('lib/http-proxy.js', function() {
|
||||
proxyServer = proxy.listen(ports.proxy),
|
||||
destiny = new ws.Server({ port: ports.source }, function () {
|
||||
var key = new Buffer(Math.random().toString()).toString('base64');
|
||||
|
||||
|
||||
var requestOptions = {
|
||||
port: ports.proxy,
|
||||
host: '127.0.0.1',
|
||||
@ -465,15 +514,15 @@ describe('lib/http-proxy.js', function() {
|
||||
};
|
||||
|
||||
var req = http.request(requestOptions);
|
||||
|
||||
|
||||
req.on('upgrade', function (res, socket, upgradeHead) {
|
||||
expect(res.headers['set-cookie'].length).to.be(2);
|
||||
done();
|
||||
});
|
||||
|
||||
|
||||
req.end();
|
||||
});
|
||||
|
||||
|
||||
destiny.on('headers', function (headers) {
|
||||
headers.push('Set-Cookie: test1=test1');
|
||||
headers.push('Set-Cookie: test2=test2');
|
||||
@ -513,8 +562,8 @@ describe('lib/http-proxy.js', function() {
|
||||
});
|
||||
});
|
||||
|
||||
destiny.on('connection', function (socket) {
|
||||
expect(socket.upgradeReq.headers['x-special-proxy-header']).to.eql('foobar');
|
||||
destiny.on('connection', function (socket, upgradeReq) {
|
||||
expect(upgradeReq.headers['x-special-proxy-header']).to.eql('foobar');
|
||||
|
||||
socket.on('message', function (msg) {
|
||||
expect(msg).to.be('hello there');
|
||||
@ -554,7 +603,7 @@ describe('lib/http-proxy.js', function() {
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
it('should forward continuation frames with big payload (including on node 4.x)', function (done) {
|
||||
var payload = Array(65530).join('0');
|
||||
var ports = { source: gen.port, proxy: gen.port };
|
||||
|
||||
@ -19,7 +19,7 @@ Object.defineProperty(gen, 'port', {
|
||||
|
||||
describe('lib/http-proxy.js', function() {
|
||||
describe('HTTPS #createProxyServer', function() {
|
||||
describe('HTTPS to HTTP', function () {
|
||||
describe('HTTPS to HTTP', function () {
|
||||
it('should proxy the request en send back the response', function (done) {
|
||||
var ports = { source: gen.port, proxy: gen.port };
|
||||
var source = http.createServer(function(req, res) {
|
||||
@ -168,7 +168,7 @@ describe('lib/http-proxy.js', function() {
|
||||
proxy.on('error', function (err, req, res) {
|
||||
expect(err).to.be.an(Error);
|
||||
if (semver.gt(process.versions.node, '0.12.0')) {
|
||||
expect(err.toString()).to.be('Error: self signed certificate')
|
||||
expect(err.toString()).to.be('Error: unable to verify the first certificate')
|
||||
} else {
|
||||
expect(err.toString()).to.be('Error: DEPTH_ZERO_SELF_SIGNED_CERT')
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user