mirror of
https://github.com/http-party/node-http-proxy.git
synced 2025-12-08 20:59:18 +00:00
Merge remote-tracking branch 'origin/caronte' into caronte-merge
This commit is contained in:
commit
0b642d4cf7
7
.gitignore
vendored
Normal file
7
.gitignore
vendored
Normal file
@ -0,0 +1,7 @@
|
||||
node_modules
|
||||
*.swp
|
||||
cov
|
||||
atest.js
|
||||
notes
|
||||
primus-proxy.js
|
||||
tes.js
|
||||
12
.travis.yml
Normal file
12
.travis.yml
Normal file
@ -0,0 +1,12 @@
|
||||
language: node_js
|
||||
node_js:
|
||||
- "0.10"
|
||||
- "0.11"
|
||||
|
||||
notifications:
|
||||
email:
|
||||
- travis@nodejitsu.com
|
||||
irc: "irc.freenode.org#nodejitsu"
|
||||
|
||||
script:
|
||||
npm test
|
||||
4
CHANGELOG.md
Normal file
4
CHANGELOG.md
Normal file
@ -0,0 +1,4 @@
|
||||
### v 1.0.0-alpha
|
||||
|
||||
- Complete refactor with new API
|
||||
|
||||
23
LICENSE
Normal file
23
LICENSE
Normal file
@ -0,0 +1,23 @@
|
||||
|
||||
node-http-proxy
|
||||
|
||||
Copyright (c) Nodejitsu 2013
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a copy of this software and associated documentation files (the
|
||||
"Software"), to deal in the Software without restriction, including
|
||||
without limitation the rights to use, copy, modify, merge, publish,
|
||||
distribute, sublicense, and/or sell copies of the Software, and to
|
||||
permit persons to whom the Software is furnished to do so, subject to
|
||||
the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be
|
||||
included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
322
README.md
Normal file
322
README.md
Normal file
@ -0,0 +1,322 @@
|
||||
<p align="center">
|
||||
<img src="doc/logo.png?raw=true"/>
|
||||
</p>
|
||||
|
||||
node-http-proxy
|
||||
=======
|
||||
|
||||
`node-http-proxy` is an HTTP programmable proxying library that supports
|
||||
websockets. It is suitable for implementing components such as
|
||||
proxies and load balancers.
|
||||
|
||||
### Build Status
|
||||
|
||||
<p align="center">
|
||||
<a href="https://travis-ci.org/nodejitsu/node-http-proxy" target="_blank">
|
||||
<img src="https://travis-ci.org/nodejitsu/node-http-proxy.png?branch=caronte"/></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?branch=caronte"/></a>
|
||||
</p>
|
||||
|
||||
### Looking to Upgrade from 0.8.x ? 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#L26-L39))
|
||||
|
||||
```javascript
|
||||
var httpProxy = require('http-proxy');
|
||||
|
||||
var proxy = httpProxy.createProxyServer(options);
|
||||
```
|
||||
|
||||
An object will be returned with four values:
|
||||
|
||||
* web `req, res, [options]` (used for proxying regular HTTP(S) requests)
|
||||
* ws `req, socket, head, [options]` (used for proxying WS(S) requests)
|
||||
* listen `port` (a function that wraps the object in a webserver, for your convenience)
|
||||
|
||||
Is it then possible to proxy requests by calling these functions
|
||||
|
||||
```javascript
|
||||
require('http').createServer(function(req, res) {
|
||||
proxy.web(req, res, { target: 'http://mytarget.com:8080' });
|
||||
});
|
||||
```
|
||||
|
||||
Errors can be listened on either using the Event Emitter API
|
||||
|
||||
```javascript
|
||||
proxy.on('error', function(e) {
|
||||
...
|
||||
});
|
||||
```
|
||||
|
||||
or using the callback API
|
||||
|
||||
```javascript
|
||||
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 second pipeline (outgoing) is responsible for the creation and manipulation of the stream that, from your target, returns data
|
||||
to the client.
|
||||
|
||||
|
||||
#### Setup a basic stand-alone proxy server
|
||||
|
||||
```js
|
||||
var http = require('http'),
|
||||
httpProxy = require('http-proxy');
|
||||
//
|
||||
// Create your proxy server and set the target in the options.
|
||||
//
|
||||
httpProxy.createProxyServer({target:'http://localhost:9000'}).listen(8000);
|
||||
|
||||
//
|
||||
// Create your target server
|
||||
//
|
||||
http.createServer(function (req, res) {
|
||||
res.writeHead(200, { 'Content-Type': 'text/plain' });
|
||||
res.write('request successfully proxied!' + '\n' + JSON.stringify(req.headers, true, 2));
|
||||
res.end();
|
||||
}).listen(9000);
|
||||
```
|
||||
|
||||
#### Setup a stand-alone proxy server with custom server logic
|
||||
This example show how you can proxy a request using your own HTTP server
|
||||
and also you can put your own logic to handle the request.
|
||||
|
||||
```js
|
||||
var http = require('http'),
|
||||
httpProxy = require('http-proxy');
|
||||
|
||||
//
|
||||
// Create a proxy server with custom application logic
|
||||
//
|
||||
var proxy = httpProxy.createProxyServer({});
|
||||
|
||||
//
|
||||
// Create your custom server and just call `proxy.web()` to proxy
|
||||
// a web request to the target passed in the options
|
||||
// also you can use `proxy.ws()` to proxy a websockets request
|
||||
//
|
||||
var server = require('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' });
|
||||
});
|
||||
|
||||
console.log("listening on port 5050")
|
||||
server.listen(5050);
|
||||
```
|
||||
|
||||
#### Setup a stand-alone proxy server with latency
|
||||
|
||||
```js
|
||||
var http = require('http'),
|
||||
httpProxy = require('http-proxy');
|
||||
|
||||
//
|
||||
// Create a proxy server with latency
|
||||
//
|
||||
var proxy = httpProxy.createProxyServer();
|
||||
|
||||
//
|
||||
// Create your server that make an operation that take a while
|
||||
// and then proxy de request
|
||||
//
|
||||
http.createServer(function (req, res) {
|
||||
// This simulate an operation that take 500ms in execute
|
||||
setTimeout(function () {
|
||||
proxy.web(req, res, {
|
||||
target: 'http://localhost:9008'
|
||||
});
|
||||
}, 500);
|
||||
}).listen(8008);
|
||||
|
||||
//
|
||||
// Create your target server
|
||||
//
|
||||
http.createServer(function (req, res) {
|
||||
res.writeHead(200, { 'Content-Type': 'text/plain' });
|
||||
res.write('request successfully proxied to: ' + req.url + '\n' + JSON.stringify(req.headers, true, 2));
|
||||
res.end();
|
||||
}).listen(9008);
|
||||
```
|
||||
|
||||
#### Listening for proxy events
|
||||
|
||||
* `error`: The error event is emitted if the request to the target fail.
|
||||
* `proxyRes`: This event is emitted if the request to the target got a response.
|
||||
|
||||
```js
|
||||
var httpProxy = require('http-proxy');
|
||||
// Error example
|
||||
//
|
||||
// Http Proxy Server with bad target
|
||||
//
|
||||
var proxy = httpProxy.createServer({
|
||||
target:'http://localhost:9005'
|
||||
});
|
||||
|
||||
proxy.listen(8005);
|
||||
|
||||
//
|
||||
// Listen for the `error` event on `proxy`.
|
||||
proxy.on('error', function (err, req, res) {
|
||||
res.writeHead(500, {
|
||||
'Content-Type': 'text/plain'
|
||||
});
|
||||
|
||||
res.end('Something went wrong. And we are reporting a custom error message.');
|
||||
});
|
||||
|
||||
//
|
||||
// Listen for the `proxyRes` event on `proxy`.
|
||||
//
|
||||
proxy.on('proxyRes', function (res) {
|
||||
console.log('RAW Response from the target', JSON.stringify(res.headers, true, 2));
|
||||
});
|
||||
|
||||
```
|
||||
|
||||
#### 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.
|
||||
|
||||
##### HTTPS -> HTTP
|
||||
|
||||
```js
|
||||
//
|
||||
// Create the HTTPS proxy server in front of a HTTP server
|
||||
//
|
||||
httpProxy.createServer({
|
||||
target: {
|
||||
host: 'localhost',
|
||||
port: 9009
|
||||
},
|
||||
ssl: {
|
||||
key: fs.readFileSync('valid-ssl-key.pem'), 'utf8'),
|
||||
cert: fs.readFileSync('valid-ssl-cert.pem'), 'utf8')
|
||||
}
|
||||
}).listen(8009);
|
||||
```
|
||||
|
||||
##### HTTPS -> HTTPS
|
||||
|
||||
```js
|
||||
//
|
||||
// Create the proxy server listening on port 443
|
||||
//
|
||||
httpProxy.createServer({
|
||||
ssl: {
|
||||
key: fs.readFileSync('valid-ssl-key.pem'), 'utf8'),
|
||||
cert: fs.readFileSync('valid-ssl-cert.pem'), 'utf8')
|
||||
},
|
||||
target: 'https://localhost:9010',
|
||||
secure: true // Depends on your needs, could be false.
|
||||
}).listen(443);
|
||||
```
|
||||
|
||||
#### Proxying WebSockets
|
||||
You can activate the websocket support for the proxy using `ws:true` in the options.
|
||||
|
||||
```js
|
||||
//
|
||||
// Create a proxy server for websockets
|
||||
//
|
||||
httpProxy.createServer({
|
||||
target: 'ws://localhost:9014',
|
||||
ws: true
|
||||
}).listen(8014);
|
||||
```
|
||||
|
||||
Also you can proxy the websocket requests just calling the `ws(req, socket, head)` method.
|
||||
|
||||
```js
|
||||
//
|
||||
// Setup our server to proxy standard HTTP requests
|
||||
//
|
||||
var proxy = new httpProxy.createProxyServer({
|
||||
target: {
|
||||
host: 'localhost',
|
||||
port: 9015
|
||||
}
|
||||
});
|
||||
var proxyServer = http.createServer(function (req, res) {
|
||||
proxy.web(req, res);
|
||||
});
|
||||
|
||||
//
|
||||
// Listen to the `upgrade` event and proxy the
|
||||
// WebSocket requests as well.
|
||||
//
|
||||
proxyServer.on('upgrade', function (req, socket, head) {
|
||||
proxy.ws(req, socket, head);
|
||||
});
|
||||
|
||||
proxyServer.listen(8015);
|
||||
```
|
||||
|
||||
### Contributing and Issues
|
||||
|
||||
* Search on Google/Github
|
||||
* If you can't find anything, open an issue
|
||||
* If you feel comfortable about fixing the issue, fork the repo
|
||||
* Commit to your local branch (which must be different from `master`)
|
||||
* Submit your Pull Request (be sure to include tests and update documentation)
|
||||
|
||||
### Options
|
||||
|
||||
`httpProxy.createProxyServer` supports the following options:
|
||||
|
||||
* **target**: url string to be parsed with the url module
|
||||
* **forward**: url string to be parsed with the url module
|
||||
* **agent**: object to be passed to http(s).request (see Node's [https agent](http://nodejs.org/api/https.html#https_class_https_agent) and [http agent](http://nodejs.org/api/http.html#http_class_http_agent) objects)
|
||||
* **secure**: true/false, if you want to verify the SSL Certs
|
||||
|
||||
If you are using the `proxyServer.listen` method, the following options are also applicable:
|
||||
|
||||
* **ssl**: object to be passed to https.createServer()
|
||||
* **ws**: true/false, if you want to proxy websockets
|
||||
* **xfwd**: true/false, adds x-forward headers
|
||||
|
||||
|
||||
### Test
|
||||
|
||||
```
|
||||
$ npm test
|
||||
```
|
||||
|
||||
### Logo
|
||||
|
||||
Logo created by [Diego Pasquali](http://dribbble.com/diegopq)
|
||||
|
||||
### License
|
||||
|
||||
>The MIT License (MIT)
|
||||
>
|
||||
>Copyright (c) 2010 - 2013 Nodejitsu Inc.
|
||||
>
|
||||
>Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
>of this software and associated documentation files (the "Software"), to deal
|
||||
>in the Software without restriction, including without limitation the rights
|
||||
>to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
>copies of the Software, and to permit persons to whom the Software is
|
||||
>furnished to do so, subject to the following conditions:
|
||||
>
|
||||
>The above copyright notice and this permission notice shall be included in
|
||||
>all copies or substantial portions of the Software.
|
||||
>
|
||||
>THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
>IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
>FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
>AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
>LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
>OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
>THE SOFTWARE.
|
||||
|
||||
|
||||
96
UPGRADING.md
Normal file
96
UPGRADING.md
Normal file
@ -0,0 +1,96 @@
|
||||
Looking to upgrade from `http-proxy@0.x.x` to `http-proxy@1.0`? You've come to the right place!
|
||||
`http-proxy@1.0` is a from-scratch implementation of `http-proxy` and, as such
|
||||
brings some breaking changes to APIs.
|
||||
|
||||
## Server creation
|
||||
|
||||
Available through `.createServer()` or `.createProxyServer()`.
|
||||
|
||||
```javascript
|
||||
httpProxy.createServer({
|
||||
target:'http://localhost:9003'
|
||||
}).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.
|
||||
|
||||
## Proxying
|
||||
|
||||
Web proying 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)
|
||||
|
||||
```javascript
|
||||
//
|
||||
// Create a HTTP Proxy server with a HTTPS target
|
||||
//
|
||||
httpProxy.createProxyServer({
|
||||
target: 'https://google.com',
|
||||
agent : https.globalAgent,
|
||||
headers: {
|
||||
host: 'google.com'
|
||||
}
|
||||
}).listen(8011);
|
||||
|
||||
```
|
||||
|
||||
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!
|
||||
|
||||
```javascript
|
||||
var proxy = new httpProxy.createProxyServer({
|
||||
target: {
|
||||
host: 'localhost',
|
||||
port: 9015
|
||||
}
|
||||
});
|
||||
var proxyServer = http.createServer(function (req, res) {
|
||||
proxy.web(req, res);
|
||||
});
|
||||
|
||||
//
|
||||
// Listen to the `upgrade` event and proxy the
|
||||
// WebSocket requests as well.
|
||||
//
|
||||
proxyServer.on('upgrade', function (req, socket, head) {
|
||||
proxy.ws(req, socket, head);
|
||||
});
|
||||
```
|
||||
|
||||
## Error Handling
|
||||
|
||||
It is possible to listen globally on the `error` event on the server. In alternative, a
|
||||
callback passed to `.web()` or `.ws()` as last parameter is also accepted.
|
||||
|
||||
```javascript
|
||||
var proxy = httpProxy.createServer({
|
||||
target:'http://localhost:9005'
|
||||
});
|
||||
|
||||
//
|
||||
// Tell the proxy to listen on port 8000
|
||||
//
|
||||
proxy.listen(8005);
|
||||
|
||||
//
|
||||
// Listen for the `error` event on `proxy`.
|
||||
proxy.on('error', function (err, req, res) {
|
||||
res.writeHead(500, {
|
||||
'Content-Type': 'text/plain'
|
||||
});
|
||||
|
||||
res.end('Something went wrong. And we are reporting a custom error message.');
|
||||
});
|
||||
```
|
||||
|
||||
## Dropped
|
||||
|
||||
Since the API was rewritten to be extremely flexible we decided to drop some features
|
||||
which were in the core and delegate them to eventual "userland" modules.
|
||||
|
||||
- Middleware API
|
||||
- ProxyTable API
|
||||
|
||||
### 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)
|
||||
|
||||
|
||||
|
||||
33
benchmark/README.md
Normal file
33
benchmark/README.md
Normal file
@ -0,0 +1,33 @@
|
||||
# Benchmarking `node-http-proxy`
|
||||
|
||||
The long-term goal of these scripts and documentation is to provide a consistent and well understood benchmarking process for `node-http-proxy` so that performance does not degrade over time. They were initially created to compare the performance of `v0.10.3` and `v1.0.0` (which was a significant rewrite).
|
||||
|
||||
## Pre-requisites
|
||||
|
||||
All benchmarking shall be done with [wrk](https://github.com/wg/wrk) which _is the same tool used for performance testing by the node.js core team._ **Make sure you have `wrk` installed before continuing**.
|
||||
|
||||
```
|
||||
$ wrk
|
||||
Usage: wrk <options> <url>
|
||||
Options:
|
||||
-c, --connections <n> Connections to keep open
|
||||
-r, --requests <n> Total requests to make
|
||||
-t, --threads <n> Number of threads to use
|
||||
|
||||
-H, --header <h> Add header to request
|
||||
-v, --version Print version details
|
||||
|
||||
Numeric arguments may include a SI unit (2k, 2M, 2G)
|
||||
```
|
||||
|
||||
## Benchmarks
|
||||
|
||||
1. [Simple HTTP benchmark](#simple-http)
|
||||
|
||||
### Simple HTTP
|
||||
|
||||
_This benchmark requires three terminals running:_
|
||||
|
||||
1. **A proxy server:** `node benchmark/scripts/proxy.js`
|
||||
2. **A target server:** `node benchmark/scripts/hello.js`
|
||||
3. **A wrk process:** `wrk -c 20 -r 10000 -t 2 http://127.0.0.1:8000`
|
||||
3
benchmark/scripts/hello.js
Normal file
3
benchmark/scripts/hello.js
Normal file
@ -0,0 +1,3 @@
|
||||
require('http').createServer(function(req, res) {
|
||||
res.end('Hello world!');
|
||||
}).listen(9000);
|
||||
6
benchmark/scripts/proxy.js
Normal file
6
benchmark/scripts/proxy.js
Normal file
@ -0,0 +1,6 @@
|
||||
var http = require('http'),
|
||||
httpProxy = require('../../');
|
||||
//
|
||||
// Create your proxy server
|
||||
//
|
||||
httpProxy.createProxyServer({ target: 'http://localhost:9000' }).listen(8000);
|
||||
88
benchmark/scripts/websockets-throughput.js
Normal file
88
benchmark/scripts/websockets-throughput.js
Normal file
@ -0,0 +1,88 @@
|
||||
var crypto = require('crypto'),
|
||||
WebSocket = require('ws'),
|
||||
async = require('async'),
|
||||
httpProxy = require('../../');
|
||||
|
||||
var SERVER_PORT = 8415,
|
||||
PROXY_PORT = 8514;
|
||||
|
||||
var testSets = [
|
||||
{
|
||||
size: 1024 * 1024, // 1 MB
|
||||
count: 128 // 128 MB
|
||||
},
|
||||
{
|
||||
size: 1024, // 1 KB,
|
||||
count: 1024 // 1 MB
|
||||
},
|
||||
{
|
||||
size: 128, // 128 B
|
||||
count: 1024 * 8 // 1 MB
|
||||
}
|
||||
];
|
||||
|
||||
testSets.forEach(function (set) {
|
||||
set.buffer = new Buffer(crypto.randomBytes(set.size));
|
||||
|
||||
set.buffers = [];
|
||||
for (var i = 0; i < set.count; i++) {
|
||||
set.buffers.push(set.buffer);
|
||||
}
|
||||
});
|
||||
|
||||
function runSet(set, callback) {
|
||||
function runAgainst(port, callback) {
|
||||
function send(sock) {
|
||||
sock.send(set.buffers[got++]);
|
||||
if (got === set.count) {
|
||||
t = new Date() - t;
|
||||
|
||||
server.close();
|
||||
proxy.close();
|
||||
|
||||
callback(null, t);
|
||||
}
|
||||
}
|
||||
|
||||
var server = new WebSocket.Server({ port: SERVER_PORT }),
|
||||
proxy = httpProxy.createServer(SERVER_PORT, 'localhost').listen(PROXY_PORT),
|
||||
client = new WebSocket('ws://localhost:' + port),
|
||||
got = 0,
|
||||
t = new Date();
|
||||
|
||||
server.on('connection', function (ws) {
|
||||
send(ws);
|
||||
|
||||
ws.on('message', function (msg) {
|
||||
send(ws);
|
||||
});
|
||||
});
|
||||
|
||||
client.on('message', function () {
|
||||
send(client);
|
||||
});
|
||||
}
|
||||
|
||||
async.series({
|
||||
server: async.apply(runAgainst, SERVER_PORT),
|
||||
proxy: async.apply(runAgainst, PROXY_PORT)
|
||||
}, function (err, results) {
|
||||
if (err) {
|
||||
throw err;
|
||||
}
|
||||
|
||||
var mb = (set.size * set.count) / (1024 * 1024);
|
||||
console.log(set.size / (1024) + ' KB * ' + set.count + ' (' + mb + ' MB)');
|
||||
|
||||
Object.keys(results).forEach(function (key) {
|
||||
var t = results[key],
|
||||
throughput = mb / (t / 1000);
|
||||
|
||||
console.log(' ' + key + ' took ' + t + ' ms (' + throughput + ' MB/s)');
|
||||
});
|
||||
|
||||
callback();
|
||||
});
|
||||
}
|
||||
|
||||
async.forEachLimit(testSets, 1, runSet);
|
||||
BIN
doc/logo.png
Normal file
BIN
doc/logo.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 46 KiB |
84
examples/balancer/simple-balancer-with-websockets.js
Normal file
84
examples/balancer/simple-balancer-with-websockets.js
Normal file
@ -0,0 +1,84 @@
|
||||
/*
|
||||
simple-balancer.js: Example of a simple round robin balancer for websockets
|
||||
|
||||
Copyright (c) Nodejitsu 2013
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a copy of this software and associated documentation files (the
|
||||
"Software"), to deal in the Software without restriction, including
|
||||
without limitation the rights to use, copy, modify, merge, publish,
|
||||
distribute, sublicense, and/or sell copies of the Software, and to
|
||||
permit persons to whom the Software is furnished to do so, subject to
|
||||
the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be
|
||||
included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
*/
|
||||
|
||||
var http = require('http'),
|
||||
httpProxy = require('../../lib/http-proxy');
|
||||
|
||||
//
|
||||
// A simple round-robin load balancing strategy.
|
||||
//
|
||||
// First, list the servers you want to use in your rotation.
|
||||
//
|
||||
var addresses = [
|
||||
{
|
||||
host: 'ws1.0.0.0',
|
||||
port: 80
|
||||
},
|
||||
{
|
||||
host: 'ws2.0.0.0',
|
||||
port: 80
|
||||
}
|
||||
];
|
||||
|
||||
//
|
||||
// Create a HttpProxy object for each target
|
||||
//
|
||||
|
||||
var proxies = addresses.map(function (target) {
|
||||
return new httpProxy.createProxyServer({
|
||||
target: target
|
||||
});
|
||||
});
|
||||
|
||||
//
|
||||
// Get the proxy at the front of the array, put it at the end and return it
|
||||
// If you want a fancier balancer, put your code here
|
||||
//
|
||||
|
||||
function nextProxy() {
|
||||
var proxy = proxies.shift();
|
||||
proxies.push(proxy);
|
||||
return proxy;
|
||||
}
|
||||
|
||||
//
|
||||
// Get the 'next' proxy and send the http request
|
||||
//
|
||||
|
||||
var server = http.createServer(function (req, res) {
|
||||
nextProxy().web(req, res);
|
||||
});
|
||||
|
||||
//
|
||||
// Get the 'next' proxy and send the upgrade request
|
||||
//
|
||||
|
||||
server.on('upgrade', function (req, socket, head) {
|
||||
nextProxy().ws(req, socket, head);
|
||||
});
|
||||
|
||||
server.listen(8001);
|
||||
|
||||
64
examples/balancer/simple-balancer.js
Normal file
64
examples/balancer/simple-balancer.js
Normal file
@ -0,0 +1,64 @@
|
||||
/*
|
||||
simple-balancer.js: Example of a simple round robin balancer
|
||||
|
||||
Copyright (c) Nodejitsu 2013
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a copy of this software and associated documentation files (the
|
||||
"Software"), to deal in the Software without restriction, including
|
||||
without limitation the rights to use, copy, modify, merge, publish,
|
||||
distribute, sublicense, and/or sell copies of the Software, and to
|
||||
permit persons to whom the Software is furnished to do so, subject to
|
||||
the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be
|
||||
included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
*/
|
||||
|
||||
var http = require('http'),
|
||||
httpProxy = require('../../lib/http-proxy');
|
||||
//
|
||||
// A simple round-robin load balancing strategy.
|
||||
//
|
||||
// First, list the servers you want to use in your rotation.
|
||||
//
|
||||
var addresses = [
|
||||
{
|
||||
host: 'ws1.0.0.0',
|
||||
port: 80
|
||||
},
|
||||
{
|
||||
host: 'ws2.0.0.0',
|
||||
port: 80
|
||||
}
|
||||
];
|
||||
var proxy = httpProxy.createServer();
|
||||
|
||||
http.createServer(function (req, res) {
|
||||
//
|
||||
// On each request, get the first location from the list...
|
||||
//
|
||||
var target = { target: addresses.shift() };
|
||||
|
||||
//
|
||||
// ...then proxy to the server whose 'turn' it is...
|
||||
//
|
||||
console.log('balancing request to: ', target);
|
||||
proxy.web(req, res, target);
|
||||
|
||||
//
|
||||
// ...and then the server you just used becomes the last item in the list.
|
||||
//
|
||||
addresses.push(target);
|
||||
}).listen(8021);
|
||||
|
||||
// Rinse; repeat; enjoy.
|
||||
64
examples/helpers/store.js
Normal file
64
examples/helpers/store.js
Normal file
@ -0,0 +1,64 @@
|
||||
|
||||
//
|
||||
// just to make these example a little bit interesting,
|
||||
// make a little key value store with an http interface
|
||||
// (see couchbd for a grown-up version of this)
|
||||
//
|
||||
// API:
|
||||
// GET /
|
||||
// retrive list of keys
|
||||
//
|
||||
// GET /[url]
|
||||
// retrive object stored at [url]
|
||||
// will respond with 404 if there is nothing stored at [url]
|
||||
//
|
||||
// POST /[url]
|
||||
//
|
||||
// JSON.parse the body and store it under [url]
|
||||
// will respond 400 (bad request) if body is not valid json.
|
||||
//
|
||||
// TODO: cached map-reduce views and auto-magic sharding.
|
||||
//
|
||||
var Store = module.exports = function Store () {
|
||||
this.store = {};
|
||||
};
|
||||
|
||||
Store.prototype = {
|
||||
get: function (key) {
|
||||
return this.store[key]
|
||||
},
|
||||
set: function (key, value) {
|
||||
return this.store[key] = value
|
||||
},
|
||||
handler:function () {
|
||||
var store = this
|
||||
return function (req, res) {
|
||||
function send (obj, status) {
|
||||
res.writeHead(200 || status,{'Content-Type': 'application/json'})
|
||||
res.write(JSON.stringify(obj) + '\n')
|
||||
res.end()
|
||||
}
|
||||
var url = req.url.split('?').shift()
|
||||
if (url === '/') {
|
||||
console.log('get index')
|
||||
return send(Object.keys(store.store))
|
||||
} else if (req.method == 'GET') {
|
||||
var obj = store.get (url)
|
||||
send(obj || {error: 'not_found', url: url}, obj ? 200 : 404)
|
||||
} else {
|
||||
//post: buffer body, and parse.
|
||||
var body = '', obj
|
||||
req.on('data', function (c) { body += c})
|
||||
req.on('end', function (c) {
|
||||
try {
|
||||
obj = JSON.parse(body)
|
||||
} catch (err) {
|
||||
return send (err, 400)
|
||||
}
|
||||
store.set(url, obj)
|
||||
send({ok: true})
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
60
examples/http/basic-proxy.js
Normal file
60
examples/http/basic-proxy.js
Normal file
@ -0,0 +1,60 @@
|
||||
/*
|
||||
basic-proxy.js: Basic example of proxying over HTTP
|
||||
|
||||
Copyright (c) Nodejitsu 2013
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a copy of this software and associated documentation files (the
|
||||
"Software"), to deal in the Software without restriction, including
|
||||
without limitation the rights to use, copy, modify, merge, publish,
|
||||
distribute, sublicense, and/or sell copies of the Software, and to
|
||||
permit persons to whom the Software is furnished to do so, subject to
|
||||
the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be
|
||||
included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
*/
|
||||
|
||||
var util = require('util'),
|
||||
colors = require('colors'),
|
||||
http = require('http'),
|
||||
httpProxy = require('../../lib/http-proxy');
|
||||
|
||||
var welcome = [
|
||||
'# # ##### ##### ##### ##### ##### #### # # # #',
|
||||
'# # # # # # # # # # # # # # # # ',
|
||||
'###### # # # # ##### # # # # # # ## # ',
|
||||
'# # # # ##### ##### ##### # # ## # ',
|
||||
'# # # # # # # # # # # # # ',
|
||||
'# # # # # # # # #### # # # '
|
||||
].join('\n');
|
||||
|
||||
util.puts(welcome.rainbow.bold);
|
||||
|
||||
//
|
||||
// Basic Http Proxy Server
|
||||
//
|
||||
httpProxy.createServer({
|
||||
target:'http://localhost:9003'
|
||||
}).listen(8003);
|
||||
|
||||
//
|
||||
// Target Http Server
|
||||
//
|
||||
http.createServer(function (req, res) {
|
||||
res.writeHead(200, { 'Content-Type': 'text/plain' });
|
||||
res.write('request successfully proxied to: ' + req.url + '\n' + JSON.stringify(req.headers, true, 2));
|
||||
res.end();
|
||||
}).listen(9003);
|
||||
|
||||
util.puts('http proxy server'.blue + ' started '.green.bold + 'on port '.blue + '8003'.yellow);
|
||||
util.puts('http server '.blue + 'started '.green.bold + 'on port '.blue + '9003 '.yellow);
|
||||
68
examples/http/concurrent-proxy.js
Normal file
68
examples/http/concurrent-proxy.js
Normal file
@ -0,0 +1,68 @@
|
||||
/*
|
||||
concurrent-proxy.js: check levelof concurrency through proxy.
|
||||
|
||||
Copyright (c) Nodejitsu 2013
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a copy of this software and associated documentation files (the
|
||||
"Software"), to deal in the Software without restriction, including
|
||||
without limitation the rights to use, copy, modify, merge, publish,
|
||||
distribute, sublicense, and/or sell copies of the Software, and to
|
||||
permit persons to whom the Software is furnished to do so, subject to
|
||||
the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be
|
||||
included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
*/
|
||||
|
||||
var util = require('util'),
|
||||
colors = require('colors'),
|
||||
http = require('http'),
|
||||
httpProxy = require('../../lib/http-proxy');
|
||||
|
||||
//
|
||||
// Basic Http Proxy Server
|
||||
//
|
||||
httpProxy.createServer({
|
||||
target:'http://localhost:9004'
|
||||
}).listen(8004);
|
||||
|
||||
//
|
||||
// Target Http Server
|
||||
//
|
||||
// to check apparent problems with concurrent connections
|
||||
// make a server which only responds when there is a given nubmer on connections
|
||||
//
|
||||
|
||||
|
||||
var connections = [],
|
||||
go;
|
||||
|
||||
http.createServer(function (req, res) {
|
||||
connections.push(function () {
|
||||
res.writeHead(200, { 'Content-Type': 'text/plain' });
|
||||
res.write('request successfully proxied to: ' + req.url + '\n' + JSON.stringify(req.headers, true, 2));
|
||||
res.end();
|
||||
});
|
||||
|
||||
process.stdout.write(connections.length + ', ');
|
||||
|
||||
if (connections.length > 110 || go) {
|
||||
go = true;
|
||||
while (connections.length) {
|
||||
connections.shift()();
|
||||
}
|
||||
}
|
||||
}).listen(9004);
|
||||
|
||||
util.puts('http proxy server'.blue + ' started '.green.bold + 'on port '.blue + '8004'.yellow);
|
||||
util.puts('http server '.blue + 'started '.green.bold + 'on port '.blue + '9004 '.yellow);
|
||||
55
examples/http/custom-proxy-error.js
Normal file
55
examples/http/custom-proxy-error.js
Normal file
@ -0,0 +1,55 @@
|
||||
/*
|
||||
custom-proxy-error.js: Example of using the custom `proxyError` event.
|
||||
|
||||
Copyright (c) Nodejitsu 2013
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a copy of this software and associated documentation files (the
|
||||
"Software"), to deal in the Software without restriction, including
|
||||
without limitation the rights to use, copy, modify, merge, publish,
|
||||
distribute, sublicense, and/or sell copies of the Software, and to
|
||||
permit persons to whom the Software is furnished to do so, subject to
|
||||
the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be
|
||||
included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
*/
|
||||
|
||||
var util = require('util'),
|
||||
colors = require('colors'),
|
||||
http = require('http'),
|
||||
httpProxy = require('../../lib/http-proxy');
|
||||
|
||||
//
|
||||
// Http Proxy Server with bad target
|
||||
//
|
||||
var proxy = httpProxy.createServer({
|
||||
target:'http://localhost:9005'
|
||||
});
|
||||
|
||||
//
|
||||
// Tell the proxy to listen on port 8000
|
||||
//
|
||||
proxy.listen(8005);
|
||||
|
||||
//
|
||||
// Listen for the `error` event on `proxy`.
|
||||
proxy.on('error', function (err, req, res) {
|
||||
res.writeHead(500, {
|
||||
'Content-Type': 'text/plain'
|
||||
});
|
||||
|
||||
res.end('Something went wrong. And we are reporting a custom error message.');
|
||||
});
|
||||
|
||||
|
||||
util.puts('http proxy server '.blue + 'started '.green.bold + 'on port '.blue + '8005 '.yellow + 'with custom error message'.magenta.underline);
|
||||
63
examples/http/error-handling.js
Normal file
63
examples/http/error-handling.js
Normal file
@ -0,0 +1,63 @@
|
||||
/*
|
||||
error-handling.js: Example of handle erros for HTTP and WebSockets
|
||||
|
||||
Copyright (c) Nodejitsu 2013
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a copy of this software and associated documentation files (the
|
||||
"Software"), to deal in the Software without restriction, including
|
||||
without limitation the rights to use, copy, modify, merge, publish,
|
||||
distribute, sublicense, and/or sell copies of the Software, and to
|
||||
permit persons to whom the Software is furnished to do so, subject to
|
||||
the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be
|
||||
included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
*/
|
||||
|
||||
var util = require('util'),
|
||||
colors = require('colors'),
|
||||
http = require('http'),
|
||||
httpProxy = require('../../lib/http-proxy');
|
||||
|
||||
//
|
||||
// HTTP Proxy Server
|
||||
//
|
||||
var proxy = httpProxy.createProxyServer({target:'http://localhost:9000', ws:true});
|
||||
|
||||
//
|
||||
// Example of error handling
|
||||
//
|
||||
function requestHandler(req, res) {
|
||||
// Pass a callback to the web proxy method
|
||||
// and catch the error there.
|
||||
proxy.web(req, res, function (err) {
|
||||
// Now you can get the err
|
||||
// and handle it by your self
|
||||
// if (err) throw err;
|
||||
res.writeHead(502);
|
||||
res.end("There was an error proxying your request");
|
||||
});
|
||||
|
||||
// In a websocket request case
|
||||
req.on('upgrade', function (req, socket, head) {
|
||||
proxy.ws(req, socket, head, function (err) {
|
||||
// Now you can get the err
|
||||
// and handle it by your self
|
||||
// if (err) throw err;
|
||||
socket.close();
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
http.createServer(requestHandler).listen(8000);
|
||||
util.puts('http proxy server'.blue + ' started '.green.bold + 'on port '.blue + '8000'.yellow);
|
||||
67
examples/http/forward-and-target-proxy.js
Normal file
67
examples/http/forward-and-target-proxy.js
Normal file
@ -0,0 +1,67 @@
|
||||
/*
|
||||
forward-and-target-proxy.js: Example of proxying over HTTP with additional forward proxy
|
||||
|
||||
Copyright (c) Nodejitsu 2013
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a copy of this software and associated documentation files (the
|
||||
"Software"), to deal in the Software without restriction, including
|
||||
without limitation the rights to use, copy, modify, merge, publish,
|
||||
distribute, sublicense, and/or sell copies of the Software, and to
|
||||
permit persons to whom the Software is furnished to do so, subject to
|
||||
the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be
|
||||
included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
*/
|
||||
|
||||
var util = require('util'),
|
||||
colors = require('colors'),
|
||||
http = require('http'),
|
||||
httpProxy = require('../../lib/http-proxy');
|
||||
|
||||
//
|
||||
// Setup proxy server with forwarding
|
||||
//
|
||||
httpProxy.createServer({
|
||||
target: {
|
||||
port: 9006,
|
||||
host: 'localhost'
|
||||
},
|
||||
forward: {
|
||||
port: 9007,
|
||||
host: 'localhost'
|
||||
}
|
||||
}).listen(8006);
|
||||
|
||||
//
|
||||
// Target Http Server
|
||||
//
|
||||
http.createServer(function (req, res) {
|
||||
res.writeHead(200, { 'Content-Type': 'text/plain' });
|
||||
res.write('request successfully proxied to: ' + req.url + '\n' + JSON.stringify(req.headers, true, 2));
|
||||
res.end();
|
||||
}).listen(9006);
|
||||
|
||||
//
|
||||
// Target Http Forwarding Server
|
||||
//
|
||||
http.createServer(function (req, res) {
|
||||
util.puts('Receiving forward for: ' + req.url);
|
||||
res.writeHead(200, { 'Content-Type': 'text/plain' });
|
||||
res.write('request successfully forwarded to: ' + req.url + '\n' + JSON.stringify(req.headers, true, 2));
|
||||
res.end();
|
||||
}).listen(9007);
|
||||
|
||||
util.puts('http proxy server '.blue + 'started '.green.bold + 'on port '.blue + '8006 '.yellow + 'with forward proxy'.magenta.underline);
|
||||
util.puts('http server '.blue + 'started '.green.bold + 'on port '.blue + '9006 '.yellow);
|
||||
util.puts('http forward server '.blue + 'started '.green.bold + 'on port '.blue + '9007 '.yellow);
|
||||
53
examples/http/forward-proxy.js
Normal file
53
examples/http/forward-proxy.js
Normal file
@ -0,0 +1,53 @@
|
||||
/*
|
||||
forward-proxy.js: Example of proxying over HTTP with additional forward proxy
|
||||
|
||||
Copyright (c) Nodejitsu 2013
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a copy of this software and associated documentation files (the
|
||||
"Software"), to deal in the Software without restriction, including
|
||||
without limitation the rights to use, copy, modify, merge, publish,
|
||||
distribute, sublicense, and/or sell copies of the Software, and to
|
||||
permit persons to whom the Software is furnished to do so, subject to
|
||||
the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be
|
||||
included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
*/
|
||||
|
||||
var util = require('util'),
|
||||
colors = require('colors'),
|
||||
http = require('http'),
|
||||
httpProxy = require('../../lib/http-proxy');
|
||||
|
||||
//
|
||||
// Setup proxy server with forwarding
|
||||
//
|
||||
httpProxy.createServer({
|
||||
forward: {
|
||||
port: 9019,
|
||||
host: 'localhost'
|
||||
}
|
||||
}).listen(8019);
|
||||
|
||||
//
|
||||
// Target Http Forwarding Server
|
||||
//
|
||||
http.createServer(function (req, res) {
|
||||
util.puts('Receiving forward for: ' + req.url);
|
||||
res.writeHead(200, { 'Content-Type': 'text/plain' });
|
||||
res.write('request successfully forwarded to: ' + req.url + '\n' + JSON.stringify(req.headers, true, 2));
|
||||
res.end();
|
||||
}).listen(9019);
|
||||
|
||||
util.puts('http proxy server '.blue + 'started '.green.bold + 'on port '.blue + '8019 '.yellow + 'with forward proxy'.magenta.underline);
|
||||
util.puts('http forward server '.blue + 'started '.green.bold + 'on port '.blue + '9019 '.yellow);
|
||||
54
examples/http/latent-proxy.js
Normal file
54
examples/http/latent-proxy.js
Normal file
@ -0,0 +1,54 @@
|
||||
/*
|
||||
latent-proxy.js: Example of proxying over HTTP with latency
|
||||
|
||||
Copyright (c) Nodejitsu 2013
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a copy of this software and associated documentation files (the
|
||||
"Software"), to deal in the Software without restriction, including
|
||||
without limitation the rights to use, copy, modify, merge, publish,
|
||||
distribute, sublicense, and/or sell copies of the Software, and to
|
||||
permit persons to whom the Software is furnished to do so, subject to
|
||||
the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be
|
||||
included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
*/
|
||||
|
||||
var util = require('util'),
|
||||
colors = require('colors'),
|
||||
http = require('http'),
|
||||
httpProxy = require('../../lib/http-proxy');
|
||||
|
||||
//
|
||||
// Http Proxy Server with Latency
|
||||
//
|
||||
var proxy = httpProxy.createProxyServer();
|
||||
http.createServer(function (req, res) {
|
||||
setTimeout(function () {
|
||||
proxy.web(req, res, {
|
||||
target: 'http://localhost:9008'
|
||||
});
|
||||
}, 500);
|
||||
}).listen(8008);
|
||||
|
||||
//
|
||||
// Target Http Server
|
||||
//
|
||||
http.createServer(function (req, res) {
|
||||
res.writeHead(200, { 'Content-Type': 'text/plain' });
|
||||
res.write('request successfully proxied to: ' + req.url + '\n' + JSON.stringify(req.headers, true, 2));
|
||||
res.end();
|
||||
}).listen(9008);
|
||||
|
||||
util.puts('http proxy server '.blue + 'started '.green.bold + 'on port '.blue + '8008 '.yellow + 'with latency'.magenta.underline);
|
||||
util.puts('http server '.blue + 'started '.green.bold + 'on port '.blue + '9008 '.yellow);
|
||||
46
examples/http/proxy-http-to-https.js
Normal file
46
examples/http/proxy-http-to-https.js
Normal file
@ -0,0 +1,46 @@
|
||||
/*
|
||||
proxy-http-to-https.js: Basic example of proxying over HTTP to a target HTTPS server
|
||||
|
||||
Copyright (c) Nodejitsu 2013
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a copy of this software and associated documentation files (the
|
||||
"Software"), to deal in the Software without restriction, including
|
||||
without limitation the rights to use, copy, modify, merge, publish,
|
||||
distribute, sublicense, and/or sell copies of the Software, and to
|
||||
permit persons to whom the Software is furnished to do so, subject to
|
||||
the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be
|
||||
included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
*/
|
||||
|
||||
var https = require('https'),
|
||||
http = require('http'),
|
||||
util = require('util'),
|
||||
path = require('path'),
|
||||
fs = require('fs'),
|
||||
colors = require('colors'),
|
||||
httpProxy = require('../../lib/http-proxy');
|
||||
|
||||
//
|
||||
// Create a HTTP Proxy server with a HTTPS target
|
||||
//
|
||||
httpProxy.createProxyServer({
|
||||
target: 'https://google.com',
|
||||
agent : https.globalAgent,
|
||||
headers: {
|
||||
host: 'google.com'
|
||||
}
|
||||
}).listen(8011);
|
||||
|
||||
util.puts('http proxy server'.blue + ' started '.green.bold + 'on port '.blue + '8011'.yellow);
|
||||
60
examples/http/proxy-https-to-http.js
Normal file
60
examples/http/proxy-https-to-http.js
Normal file
@ -0,0 +1,60 @@
|
||||
/*
|
||||
proxy-https-to-http.js: Basic example of proxying over HTTPS to a target HTTP server
|
||||
|
||||
Copyright (c) Nodejitsu 2013
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a copy of this software and associated documentation files (the
|
||||
"Software"), to deal in the Software without restriction, including
|
||||
without limitation the rights to use, copy, modify, merge, publish,
|
||||
distribute, sublicense, and/or sell copies of the Software, and to
|
||||
permit persons to whom the Software is furnished to do so, subject to
|
||||
the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be
|
||||
included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
*/
|
||||
|
||||
var https = require('https'),
|
||||
http = require('http'),
|
||||
util = require('util'),
|
||||
path = require('path'),
|
||||
fs = require('fs'),
|
||||
colors = require('colors'),
|
||||
httpProxy = require('../../lib/http-proxy'),
|
||||
fixturesDir = path.join(__dirname, '..', '..', 'test', 'fixtures');
|
||||
|
||||
//
|
||||
// Create the target HTTP server
|
||||
//
|
||||
http.createServer(function (req, res) {
|
||||
res.writeHead(200, { 'Content-Type': 'text/plain' });
|
||||
res.write('hello http over https\n');
|
||||
res.end();
|
||||
}).listen(9009);
|
||||
|
||||
//
|
||||
// Create the HTTPS proxy server listening on port 8000
|
||||
//
|
||||
httpProxy.createServer({
|
||||
target: {
|
||||
host: 'localhost',
|
||||
port: 9009
|
||||
},
|
||||
ssl: {
|
||||
key: fs.readFileSync(path.join(fixturesDir, 'agent2-key.pem'), 'utf8'),
|
||||
cert: fs.readFileSync(path.join(fixturesDir, 'agent2-cert.pem'), 'utf8')
|
||||
}
|
||||
}).listen(8009);
|
||||
|
||||
util.puts('https proxy server'.blue + ' started '.green.bold + 'on port '.blue + '8009'.yellow);
|
||||
util.puts('http server '.blue + 'started '.green.bold + 'on port '.blue + '9009 '.yellow);
|
||||
59
examples/http/proxy-https-to-https.js
Normal file
59
examples/http/proxy-https-to-https.js
Normal file
@ -0,0 +1,59 @@
|
||||
/*
|
||||
proxy-https-to-https.js: Basic example of proxying over HTTPS to a target HTTPS server
|
||||
|
||||
Copyright (c) Nodejitsu 2013
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a copy of this software and associated documentation files (the
|
||||
"Software"), to deal in the Software without restriction, including
|
||||
without limitation the rights to use, copy, modify, merge, publish,
|
||||
distribute, sublicense, and/or sell copies of the Software, and to
|
||||
permit persons to whom the Software is furnished to do so, subject to
|
||||
the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be
|
||||
included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
*/
|
||||
|
||||
var https = require('https'),
|
||||
http = require('http'),
|
||||
util = require('util'),
|
||||
fs = require('fs'),
|
||||
path = require('path'),
|
||||
colors = require('colors'),
|
||||
httpProxy = require('../../lib/http-proxy'),
|
||||
fixturesDir = path.join(__dirname, '..', '..', 'test', 'fixtures'),
|
||||
httpsOpts = {
|
||||
key: fs.readFileSync(path.join(fixturesDir, 'agent2-key.pem'), 'utf8'),
|
||||
cert: fs.readFileSync(path.join(fixturesDir, 'agent2-cert.pem'), 'utf8')
|
||||
};
|
||||
|
||||
//
|
||||
// Create the target HTTPS server
|
||||
//
|
||||
https.createServer(httpsOpts, function (req, res) {
|
||||
res.writeHead(200, { 'Content-Type': 'text/plain' });
|
||||
res.write('hello https\n');
|
||||
res.end();
|
||||
}).listen(9010);
|
||||
|
||||
//
|
||||
// Create the proxy server listening on port 443
|
||||
//
|
||||
httpProxy.createServer({
|
||||
ssl: httpsOpts,
|
||||
target: 'https://localhost:9010',
|
||||
secure: false
|
||||
}).listen(8010);
|
||||
|
||||
util.puts('https proxy server'.blue + ' started '.green.bold + 'on port '.blue + '8010'.yellow);
|
||||
util.puts('https server '.blue + 'started '.green.bold + 'on port '.blue + '9010 '.yellow);
|
||||
54
examples/http/standalone-proxy.js
Normal file
54
examples/http/standalone-proxy.js
Normal file
@ -0,0 +1,54 @@
|
||||
/*
|
||||
standalone-proxy.js: Example of proxying over HTTP with a standalone HTTP server.
|
||||
|
||||
Copyright (c) Nodejitsu 2013
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a copy of this software and associated documentation files (the
|
||||
"Software"), to deal in the Software without restriction, including
|
||||
without limitation the rights to use, copy, modify, merge, publish,
|
||||
distribute, sublicense, and/or sell copies of the Software, and to
|
||||
permit persons to whom the Software is furnished to do so, subject to
|
||||
the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be
|
||||
included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
*/
|
||||
|
||||
var util = require('util'),
|
||||
colors = require('colors'),
|
||||
http = require('http'),
|
||||
httpProxy = require('../../lib/http-proxy');
|
||||
|
||||
//
|
||||
// Http Server with proxyRequest Handler and Latency
|
||||
//
|
||||
var proxy = new httpProxy.createProxyServer();
|
||||
http.createServer(function (req, res) {
|
||||
setTimeout(function () {
|
||||
proxy.web(req, res, {
|
||||
target: 'http://localhost:9002'
|
||||
});
|
||||
}, 200);
|
||||
}).listen(8002);
|
||||
|
||||
//
|
||||
// Target Http Server
|
||||
//
|
||||
http.createServer(function (req, res) {
|
||||
res.writeHead(200, { 'Content-Type': 'text/plain' });
|
||||
res.write('request successfully proxied to: ' + req.url + '\n' + JSON.stringify(req.headers, true, 2));
|
||||
res.end();
|
||||
}).listen(9002);
|
||||
|
||||
util.puts('http server '.blue + 'started '.green.bold + 'on port '.blue + '8002 '.yellow + 'with proxy.web() handler'.cyan.underline + ' and latency'.magenta);
|
||||
util.puts('http server '.blue + 'started '.green.bold + 'on port '.blue + '9001 '.yellow);
|
||||
119
examples/middleware/bodyDecoder-middleware.js
Normal file
119
examples/middleware/bodyDecoder-middleware.js
Normal file
@ -0,0 +1,119 @@
|
||||
/*
|
||||
bodyDecoder-middleware.js: Basic example of `connect.bodyParser()` middleware in node-http-proxy
|
||||
|
||||
Copyright (c) Nodejitsu 2013
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a copy of this software and associated documentation files (the
|
||||
"Software"), to deal in the Software without restriction, including
|
||||
without limitation the rights to use, copy, modify, merge, publish,
|
||||
distribute, sublicense, and/or sell copies of the Software, and to
|
||||
permit persons to whom the Software is furnished to do so, subject to
|
||||
the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be
|
||||
included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
*/
|
||||
|
||||
var http = require('http'),
|
||||
connect = require('connect'),
|
||||
request = require('request'),
|
||||
colors = require('colors'),
|
||||
util = require('util'),
|
||||
Store = require('../helpers/store'),
|
||||
httpProxy = require('../../lib/http-proxy'),
|
||||
proxy = httpProxy.createProxyServer({});
|
||||
|
||||
http.createServer(new Store().handler()).listen(7531, function () {
|
||||
util.puts('http '.blue + 'greetings '.green + 'server'.blue + ' started '.green.bold + 'on port '.blue + '7531'.yellow);
|
||||
//try these commands:
|
||||
// get index:
|
||||
// curl localhost:7531
|
||||
// []
|
||||
//
|
||||
// get a doc:
|
||||
// curl localhost:7531/foo
|
||||
// {"error":"not_found"}
|
||||
//
|
||||
// post an doc:
|
||||
// curl -X POST localhost:7531/foo -d '{"content": "hello", "type": "greeting"}'
|
||||
// {"ok":true}
|
||||
//
|
||||
// get index (now, not empty)
|
||||
// curl localhost:7531
|
||||
// ["/foo"]
|
||||
//
|
||||
// get doc
|
||||
// curl localhost:7531/foo
|
||||
// {"content": "hello", "type": "greeting"}
|
||||
|
||||
//
|
||||
// now, suppose we wanted to direct all objects where type == "greeting" to a different store
|
||||
// than where type == "insult"
|
||||
//
|
||||
// we can use connect connect-bodyDecoder and some custom logic to send insults to another Store.
|
||||
|
||||
//insult server:
|
||||
|
||||
http.createServer(new Store().handler()).listen(2600, function () {
|
||||
util.puts('http '.blue + 'insults '.red + 'server'.blue + ' started '.green.bold + 'on port '.blue + '2600'.yellow);
|
||||
|
||||
//greetings -> 7531, insults-> 2600
|
||||
|
||||
// now, start a proxy server.
|
||||
|
||||
//don't worry about incoming contont type
|
||||
//bodyParser.parse[''] = JSON.parse
|
||||
|
||||
connect.createServer(
|
||||
//refactor the body parser and re-streamer into a separate package
|
||||
connect.bodyParser(),
|
||||
//body parser absorbs the data and end events before passing control to the next
|
||||
// middleware. if we want to proxy it, we'll need to re-emit these events after
|
||||
//passing control to the middleware.
|
||||
require('connect-restreamer')(),
|
||||
function (req, res) {
|
||||
//if your posting an obect which contains type: "insult"
|
||||
//it will get redirected to port 2600.
|
||||
//normal get requests will go to 7531 nad will not return insults.
|
||||
var port = (req.body && req.body.type === 'insult' ? 2600 : 7531)
|
||||
proxy.web(req, res, { target: { host: 'localhost', port: port }});
|
||||
}
|
||||
).listen(1337, function () {
|
||||
util.puts('http proxy server'.blue + ' started '.green.bold + 'on port '.blue + '1337'.yellow);
|
||||
//bodyParser needs content-type set to application/json
|
||||
//if we use request, it will set automatically if we use the 'json:' field.
|
||||
function post (greeting, type) {
|
||||
request.post({
|
||||
url: 'http://localhost:1337/' + greeting,
|
||||
json: {content: greeting, type: type || "greeting"}
|
||||
})
|
||||
}
|
||||
post("hello")
|
||||
post("g'day")
|
||||
post("kiora")
|
||||
post("houdy")
|
||||
post("java", "insult")
|
||||
|
||||
//now, the insult should have been proxied to 2600
|
||||
|
||||
//curl localhost:2600
|
||||
//["/java"]
|
||||
|
||||
//but the greetings will be sent to 7531
|
||||
|
||||
//curl localhost:7531
|
||||
//["/hello","/g%27day","/kiora","/houdy"]
|
||||
|
||||
})
|
||||
})
|
||||
});
|
||||
65
examples/middleware/gzip-middleware.js
Normal file
65
examples/middleware/gzip-middleware.js
Normal file
@ -0,0 +1,65 @@
|
||||
/*
|
||||
gzip-middleware.js: Basic example of `connect-gzip` middleware in node-http-proxy
|
||||
|
||||
Copyright (c) Nodejitsu 2013
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a copy of this software and associated documentation files (the
|
||||
"Software"), to deal in the Software without restriction, including
|
||||
without limitation the rights to use, copy, modify, merge, publish,
|
||||
distribute, sublicense, and/or sell copies of the Software, and to
|
||||
permit persons to whom the Software is furnished to do so, subject to
|
||||
the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be
|
||||
included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
*/
|
||||
|
||||
var util = require('util'),
|
||||
colors = require('colors'),
|
||||
http = require('http'),
|
||||
connect = require('connect')
|
||||
httpProxy = require('../../lib/http-proxy');
|
||||
|
||||
//
|
||||
// Basic Connect App
|
||||
//
|
||||
connect.createServer(
|
||||
connect.compress({
|
||||
// Pass to connect.compress() the options
|
||||
// that you need, just for show the example
|
||||
// we use threshold to 1
|
||||
threshold: 1
|
||||
}),
|
||||
function (req, res) {
|
||||
proxy.web(req, res);
|
||||
}
|
||||
).listen(8012);
|
||||
|
||||
//
|
||||
// Basic Http Proxy Server
|
||||
//
|
||||
var proxy = httpProxy.createProxyServer({
|
||||
target: 'http://localhost:9012'
|
||||
});
|
||||
|
||||
//
|
||||
// Target Http Server
|
||||
//
|
||||
http.createServer(function (req, res) {
|
||||
res.writeHead(200, { 'Content-Type': 'text/plain' });
|
||||
res.write('request successfully proxied to: ' + req.url + '\n' + JSON.stringify(req.headers, true, 2));
|
||||
res.end();
|
||||
}).listen(9012);
|
||||
|
||||
util.puts('http proxy server'.blue + ' started '.green.bold + 'on port '.blue + '8012'.yellow);
|
||||
util.puts('http server '.blue + 'started '.green.bold + 'on port '.blue + '9012 '.yellow);
|
||||
67
examples/middleware/modifyResponse-middleware.js
Normal file
67
examples/middleware/modifyResponse-middleware.js
Normal file
@ -0,0 +1,67 @@
|
||||
/*
|
||||
modifyBody-middleware.js: Example of middleware which modifies response
|
||||
|
||||
Copyright (c) Nodejitsu 2013
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a copy of this software and associated documentation files (the
|
||||
"Software"), to deal in the Software without restriction, including
|
||||
without limitation the rights to use, copy, modify, merge, publish,
|
||||
distribute, sublicense, and/or sell copies of the Software, and to
|
||||
permit persons to whom the Software is furnished to do so, subject to
|
||||
the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be
|
||||
included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
*/
|
||||
|
||||
var util = require('util'),
|
||||
colors = require('colors'),
|
||||
http = require('http'),
|
||||
connect = require('connect'),
|
||||
httpProxy = require('../../lib/http-proxy');
|
||||
|
||||
//
|
||||
// Basic Connect App
|
||||
//
|
||||
connect.createServer(
|
||||
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);
|
||||
}
|
||||
).listen(8013);
|
||||
|
||||
//
|
||||
// Basic Http Proxy Server
|
||||
//
|
||||
var proxy = httpProxy.createProxyServer({
|
||||
target: 'http://localhost:9013'
|
||||
});
|
||||
|
||||
//
|
||||
// Target Http Server
|
||||
//
|
||||
http.createServer(function (req, res) {
|
||||
res.writeHead(200, { 'Content-Type': 'text/plain' });
|
||||
res.end('Hello, I know Ruby\n');
|
||||
}).listen(9013);
|
||||
|
||||
util.puts('http proxy server'.blue + ' started '.green.bold + 'on port '.blue + '8013'.yellow);
|
||||
util.puts('http server '.blue + 'started '.green.bold + 'on port '.blue + '9013 '.yellow);
|
||||
|
||||
13
examples/package.json
Normal file
13
examples/package.json
Normal file
@ -0,0 +1,13 @@
|
||||
{
|
||||
"name": "http-proxy-examples",
|
||||
"description": "packages required to run the examples",
|
||||
"version": "0.0.0",
|
||||
"dependencies": {
|
||||
"colors": "~0.6.2",
|
||||
"socket.io": "~0.9.16",
|
||||
"socket.io-client": "~0.9.16",
|
||||
"connect": "~2.11.0",
|
||||
"request": "~2.27.0",
|
||||
"connect-restreamer": "~1.0.0"
|
||||
}
|
||||
}
|
||||
91
examples/websocket/latent-websocket-proxy.js
Normal file
91
examples/websocket/latent-websocket-proxy.js
Normal file
@ -0,0 +1,91 @@
|
||||
/*
|
||||
standalone-websocket-proxy.js: Example of proxying websockets over HTTP with a standalone HTTP server.
|
||||
|
||||
Copyright (c) Nodejitsu 2013
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a copy of this software and associated documentation files (the
|
||||
"Software"), to deal in the Software without restriction, including
|
||||
without limitation the rights to use, copy, modify, merge, publish,
|
||||
distribute, sublicense, and/or sell copies of the Software, and to
|
||||
permit persons to whom the Software is furnished to do so, subject to
|
||||
the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be
|
||||
included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
*/
|
||||
|
||||
var util = require('util'),
|
||||
http = require('http'),
|
||||
colors = require('colors'),
|
||||
httpProxy = require('../../lib/http-proxy');
|
||||
|
||||
try {
|
||||
var io = require('socket.io'),
|
||||
client = require('socket.io-client');
|
||||
}
|
||||
catch (ex) {
|
||||
console.error('Socket.io is required for this example:');
|
||||
console.error('npm ' + 'install'.green);
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
//
|
||||
// Create the target HTTP server and setup
|
||||
// socket.io on it.
|
||||
//
|
||||
var server = io.listen(9016);
|
||||
server.sockets.on('connection', function (client) {
|
||||
util.debug('Got websocket connection');
|
||||
|
||||
client.on('message', function (msg) {
|
||||
util.debug('Got message from client: ' + msg);
|
||||
});
|
||||
|
||||
client.send('from server');
|
||||
});
|
||||
|
||||
//
|
||||
// Setup our server to proxy standard HTTP requests
|
||||
//
|
||||
var proxy = new httpProxy.createProxyServer({
|
||||
target: {
|
||||
host: 'localhost',
|
||||
port: 9016
|
||||
}
|
||||
});
|
||||
|
||||
var proxyServer = http.createServer(function (req, res) {
|
||||
proxy.web(req, res);
|
||||
});
|
||||
|
||||
//
|
||||
// Listen to the `upgrade` event and proxy the
|
||||
// WebSocket requests as well.
|
||||
//
|
||||
proxyServer.on('upgrade', function (req, socket, head) {
|
||||
setTimeout(function () {
|
||||
proxy.ws(req, socket, head);
|
||||
}, 1000);
|
||||
});
|
||||
|
||||
proxyServer.listen(8016);
|
||||
|
||||
//
|
||||
// Setup the socket.io client against our proxy
|
||||
//
|
||||
var ws = client.connect('ws://localhost:8016');
|
||||
|
||||
ws.on('message', function (msg) {
|
||||
util.debug('Got message: ' + msg);
|
||||
ws.send('I am the client');
|
||||
});
|
||||
88
examples/websocket/standalone-websocket-proxy.js
Normal file
88
examples/websocket/standalone-websocket-proxy.js
Normal file
@ -0,0 +1,88 @@
|
||||
/*
|
||||
standalone-websocket-proxy.js: Example of proxying websockets over HTTP with a standalone HTTP server.
|
||||
|
||||
Copyright (c) Nodejitsu 2013
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a copy of this software and associated documentation files (the
|
||||
"Software"), to deal in the Software without restriction, including
|
||||
without limitation the rights to use, copy, modify, merge, publish,
|
||||
distribute, sublicense, and/or sell copies of the Software, and to
|
||||
permit persons to whom the Software is furnished to do so, subject to
|
||||
the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be
|
||||
included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
*/
|
||||
|
||||
var util = require('util'),
|
||||
http = require('http'),
|
||||
colors = require('colors'),
|
||||
httpProxy = require('../../lib/http-proxy');
|
||||
|
||||
try {
|
||||
var io = require('socket.io'),
|
||||
client = require('socket.io-client');
|
||||
}
|
||||
catch (ex) {
|
||||
console.error('Socket.io is required for this example:');
|
||||
console.error('npm ' + 'install'.green);
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
//
|
||||
// Create the target HTTP server and setup
|
||||
// socket.io on it.
|
||||
//
|
||||
var server = io.listen(9015);
|
||||
server.sockets.on('connection', function (client) {
|
||||
util.debug('Got websocket connection');
|
||||
|
||||
client.on('message', function (msg) {
|
||||
util.debug('Got message from client: ' + msg);
|
||||
});
|
||||
|
||||
client.send('from server');
|
||||
});
|
||||
|
||||
//
|
||||
// Setup our server to proxy standard HTTP requests
|
||||
//
|
||||
var proxy = new httpProxy.createProxyServer({
|
||||
target: {
|
||||
host: 'localhost',
|
||||
port: 9015
|
||||
}
|
||||
});
|
||||
var proxyServer = http.createServer(function (req, res) {
|
||||
proxy.web(req, res);
|
||||
});
|
||||
|
||||
//
|
||||
// Listen to the `upgrade` event and proxy the
|
||||
// WebSocket requests as well.
|
||||
//
|
||||
proxyServer.on('upgrade', function (req, socket, head) {
|
||||
proxy.ws(req, socket, head);
|
||||
});
|
||||
|
||||
proxyServer.listen(8015);
|
||||
|
||||
//
|
||||
// Setup the socket.io client against our proxy
|
||||
//
|
||||
var ws = client.connect('ws://localhost:8015');
|
||||
|
||||
ws.on('message', function (msg) {
|
||||
util.debug('Got message: ' + msg);
|
||||
ws.send('I am the client');
|
||||
});
|
||||
70
examples/websocket/websocket-proxy.js
Normal file
70
examples/websocket/websocket-proxy.js
Normal file
@ -0,0 +1,70 @@
|
||||
/*
|
||||
web-socket-proxy.js: Example of proxying over HTTP and WebSockets.
|
||||
|
||||
Copyright (c) Nodejitsu 2013
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a copy of this software and associated documentation files (the
|
||||
"Software"), to deal in the Software without restriction, including
|
||||
without limitation the rights to use, copy, modify, merge, publish,
|
||||
distribute, sublicense, and/or sell copies of the Software, and to
|
||||
permit persons to whom the Software is furnished to do so, subject to
|
||||
the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be
|
||||
included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
*/
|
||||
|
||||
var util = require('util'),
|
||||
http = require('http'),
|
||||
colors = require('colors'),
|
||||
httpProxy = require('../../lib/http-proxy');
|
||||
|
||||
try {
|
||||
var io = require('socket.io'),
|
||||
client = require('socket.io-client');
|
||||
}
|
||||
catch (ex) {
|
||||
console.error('Socket.io is required for this example:');
|
||||
console.error('npm ' + 'install'.green);
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
//
|
||||
// Create the target HTTP server and setup
|
||||
// socket.io on it.
|
||||
//
|
||||
var server = io.listen(9014);
|
||||
server.sockets.on('connection', function (client) {
|
||||
util.debug('Got websocket connection');
|
||||
|
||||
client.on('message', function (msg) {
|
||||
util.debug('Got message from client: ' + msg);
|
||||
});
|
||||
|
||||
client.send('from server');
|
||||
});
|
||||
|
||||
//
|
||||
// Create a proxy server with node-http-proxy
|
||||
//
|
||||
httpProxy.createServer({ target: 'ws://localhost:9014', ws: true }).listen(8014);
|
||||
|
||||
//
|
||||
// Setup the socket.io client against our proxy
|
||||
//
|
||||
var ws = client.connect('ws://localhost:8014');
|
||||
|
||||
ws.on('message', function (msg) {
|
||||
util.debug('Got message: ' + msg);
|
||||
ws.send('I am the client');
|
||||
});
|
||||
13
index.js
Normal file
13
index.js
Normal file
@ -0,0 +1,13 @@
|
||||
/*!
|
||||
* Caron dimonio, con occhi di bragia
|
||||
* loro accennando, tutte le raccoglie;
|
||||
* batte col remo qualunque s’adagia
|
||||
*
|
||||
* Charon the demon, with the eyes of glede,
|
||||
* Beckoning to them, collects them all together,
|
||||
* Beats with his oar whoever lags behind
|
||||
*
|
||||
* Dante - The Divine Comedy (Canto III)
|
||||
*/
|
||||
|
||||
module.exports = require('./lib/http-proxy');
|
||||
48
lib/http-proxy.js
Normal file
48
lib/http-proxy.js
Normal file
@ -0,0 +1,48 @@
|
||||
var http = require('http'),
|
||||
https = require('https'),
|
||||
url = require('url'),
|
||||
httpProxy = require('./http-proxy/');
|
||||
|
||||
/**
|
||||
* Export the the proxy "Server" as the main export
|
||||
*/
|
||||
module.exports = httpProxy.Server;
|
||||
|
||||
/**
|
||||
* Creates the proxy server.
|
||||
*
|
||||
* Examples:
|
||||
*
|
||||
* httpProxy.createProxyServer({ .. }, 8000)
|
||||
* // => '{ web: [Function], ws: [Function] ... }'
|
||||
*
|
||||
* @param {Object} Options Config object passed to the proxy
|
||||
*
|
||||
* @return {Object} Proxy Proxy object with handlers for `ws` and `web` requests
|
||||
*
|
||||
* @api public
|
||||
*/
|
||||
|
||||
module.exports.createProxyServer = module.exports.createServer = function createProxyServer(options) {
|
||||
/*
|
||||
* `options` is needed and it must have the following layout:
|
||||
*
|
||||
* {
|
||||
* target : <url string to be parsed with the url module>
|
||||
* forward: <url string to be parsed with the url module>
|
||||
* agent : <object to be passed to http(s).request>
|
||||
* ssl : <object to be passed to https.createServer()>
|
||||
* ws : <true/false, if you want to proxy websockets>
|
||||
* xfwd : <true/false, adds x-forward headers>
|
||||
* secure : <true/false, verify SSL certificate>
|
||||
* }
|
||||
*
|
||||
* NOTE: `options.ws` and `options.ssl` are optional.
|
||||
* `options.target and `options.forward` cannot be
|
||||
* both missing
|
||||
* }
|
||||
*/
|
||||
|
||||
return new httpProxy.Server(options);
|
||||
};
|
||||
|
||||
82
lib/http-proxy/common.js
Normal file
82
lib/http-proxy/common.js
Normal file
@ -0,0 +1,82 @@
|
||||
var common = exports,
|
||||
url = require('url'),
|
||||
extend = require('util')._extend;
|
||||
|
||||
/**
|
||||
* Copies the right headers from `options` and `req` to
|
||||
* `outgoing` which is then used to fire the proxied
|
||||
* request.
|
||||
*
|
||||
* Examples:
|
||||
*
|
||||
* common.setupOutgoing(outgoing, options, req)
|
||||
* // => { host: ..., hostname: ...}
|
||||
*
|
||||
* @param {Object} Outgoing Base object to be filled with required properties
|
||||
* @param {Object} Options Config object passed to the proxy
|
||||
* @param {ClientRequest} Req Request Object
|
||||
* @param {String} Forward String to select forward or target
|
||||
*
|
||||
* @return {Object} Outgoing Object with all required properties set
|
||||
*
|
||||
* @api private
|
||||
*/
|
||||
|
||||
common.setupOutgoing = function(outgoing, options, req, forward) {
|
||||
outgoing.port = options[forward || 'target'].port ||
|
||||
(~['https:', 'wss:'].indexOf(options[forward || 'target'].protocol) ? 443 : 80);
|
||||
|
||||
['host', 'hostname', 'socketPath'].forEach(
|
||||
function(e) { outgoing[e] = options[forward || 'target'][e]; }
|
||||
);
|
||||
|
||||
['method', 'headers'].forEach(
|
||||
function(e) { outgoing[e] = req[e]; }
|
||||
);
|
||||
|
||||
if (options.headers){
|
||||
extend(outgoing.headers, options.headers);
|
||||
}
|
||||
|
||||
if (options[forward || 'target'].protocol == 'https:') {
|
||||
outgoing.rejectUnauthorized = (typeof options.secure === "undefined") ? true : options.secure;
|
||||
}
|
||||
|
||||
|
||||
outgoing.agent = options.agent || false;
|
||||
outgoing.path = url.parse(req.url).path;
|
||||
return outgoing;
|
||||
};
|
||||
|
||||
/**
|
||||
* Set the proper configuration for sockets,
|
||||
* set no delay and set keep alive, also set
|
||||
* the timeout to 0.
|
||||
*
|
||||
* Examples:
|
||||
*
|
||||
* common.setupSocket(socket)
|
||||
* // => Socket
|
||||
*
|
||||
* @param {Socket} Socket instance to setup
|
||||
*
|
||||
* @return {Socket} Return the configured socket.
|
||||
*
|
||||
* @api private
|
||||
*/
|
||||
|
||||
common.setupSocket = function(socket) {
|
||||
socket.setTimeout(0);
|
||||
socket.setNoDelay(true);
|
||||
|
||||
socket.setKeepAlive(true, 0);
|
||||
|
||||
return socket;
|
||||
};
|
||||
|
||||
common.getPort = function(req) {
|
||||
var res = req.headers.host.match(/:(\d+)/);
|
||||
return res ?
|
||||
res[1] :
|
||||
req.connection.pair ? '443' : '80' ;
|
||||
}
|
||||
149
lib/http-proxy/index.js
Normal file
149
lib/http-proxy/index.js
Normal file
@ -0,0 +1,149 @@
|
||||
var httpProxy = exports,
|
||||
extend = require('util')._extend,
|
||||
parse_url = require('url').parse,
|
||||
EE3 = require('eventemitter3').EventEmitter,
|
||||
http = require('http'),
|
||||
https = require('https'),
|
||||
web = require('./passes/web-incoming'),
|
||||
ws = require('./passes/ws-incoming');
|
||||
|
||||
httpProxy.Server = ProxyServer;
|
||||
|
||||
/**
|
||||
* Returns a function that creates the loader for
|
||||
* either `ws` or `web`'s passes.
|
||||
*
|
||||
* Examples:
|
||||
*
|
||||
* httpProxy.createRightProxy('ws')
|
||||
* // => [Function]
|
||||
*
|
||||
* @param {String} Type Either 'ws' or 'web'
|
||||
*
|
||||
* @return {Function} Loader Function that when called returns an iterator for the right passes
|
||||
*
|
||||
* @api private
|
||||
*/
|
||||
|
||||
function createRightProxy(type) {
|
||||
return function(options) {
|
||||
return function(req, res /*, [head], [opts] */) {
|
||||
var passes = (type === 'ws') ? this.wsPasses : this.webPasses,
|
||||
args = [].slice.call(arguments),
|
||||
cntr = args.length - 1,
|
||||
head, cbl;
|
||||
|
||||
/* optional args parse begin */
|
||||
if(typeof args[cntr] === 'function') {
|
||||
cbl = args[cntr];
|
||||
|
||||
cntr--;
|
||||
}
|
||||
|
||||
if(
|
||||
!(args[cntr] instanceof Buffer) &&
|
||||
args[cntr] !== res
|
||||
) {
|
||||
//Copy global options
|
||||
options = extend({}, options);
|
||||
//Overwrite with request options
|
||||
extend(options, args[cntr]);
|
||||
|
||||
cntr--;
|
||||
}
|
||||
|
||||
if(args[cntr] instanceof Buffer) {
|
||||
head = args[cntr];
|
||||
}
|
||||
|
||||
/* optional args parse end */
|
||||
|
||||
['target', 'forward'].forEach(function(e) {
|
||||
if (typeof options[e] === 'string')
|
||||
options[e] = parse_url(options[e]);
|
||||
});
|
||||
|
||||
|
||||
for(var i=0; i < passes.length; i++) {
|
||||
/**
|
||||
* Call of passes functions
|
||||
* pass(req, res, options, head)
|
||||
*
|
||||
* In WebSockets case the `res` variable
|
||||
* refer to the connection socket
|
||||
* pass(req, socket, options, head)
|
||||
*/
|
||||
if(passes[i](req, res, options, head, cbl ? false : this, cbl)) { // passes can return a truthy value to halt the loop
|
||||
break;
|
||||
}
|
||||
}
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
function ProxyServer(options) {
|
||||
EE3.call(this);
|
||||
|
||||
this.web = this.proxyRequest = createRightProxy('web')(options);
|
||||
this.ws = this.proxyWebsocketRequest = createRightProxy('ws')(options);
|
||||
this.options = options;
|
||||
|
||||
this.webPasses = Object.keys(web).map(function(pass) {
|
||||
return web[pass];
|
||||
});
|
||||
|
||||
this.wsPasses = Object.keys(ws).map(function(pass) {
|
||||
return ws[pass];
|
||||
});
|
||||
}
|
||||
|
||||
require('util').inherits(ProxyServer, EE3);
|
||||
|
||||
ProxyServer.prototype.listen = function(port) {
|
||||
var self = this,
|
||||
closure = function(req, res) { self.web(req, res); };
|
||||
|
||||
this._server = this.options.ssl ?
|
||||
https.createServer(this.options.ssl, closure) :
|
||||
http.createServer(closure);
|
||||
|
||||
if(this.options.ws) {
|
||||
this._server.on('upgrade', function(req, socket, head) { self.ws(req, socket, head); });
|
||||
}
|
||||
|
||||
this._server.listen(port);
|
||||
|
||||
return this;
|
||||
};
|
||||
|
||||
ProxyServer.prototype.before = function(type, passName, callback) {
|
||||
if (type !== 'ws' || type !== 'web') {
|
||||
throw new Error('type must be `web` or `ws`');
|
||||
}
|
||||
var passes = (type === 'ws') ? this.wsPasses : this.webPasses,
|
||||
i = false;
|
||||
|
||||
passes.forEach(function(v, idx) {
|
||||
if(v.name === passName) i = idx;
|
||||
})
|
||||
|
||||
if(!i) throw new Error('No such pass');
|
||||
|
||||
passes.splice(i, 0, callback);
|
||||
};
|
||||
ProxyServer.prototype.after = function(type, passName, callback) {
|
||||
if (type !== 'ws' || type !== 'web') {
|
||||
throw new Error('type must be `web` or `ws`');
|
||||
}
|
||||
var passes = (type === 'ws') ? this.wsPasses : this.webPasses,
|
||||
i = false;
|
||||
|
||||
passes.forEach(function(v, idx) {
|
||||
if(v.name === passName) i = idx;
|
||||
})
|
||||
|
||||
if(!i) throw new Error('No such pass');
|
||||
|
||||
passes.splice(i++, 0, callback);
|
||||
};
|
||||
134
lib/http-proxy/passes/web-incoming.js
Normal file
134
lib/http-proxy/passes/web-incoming.js
Normal file
@ -0,0 +1,134 @@
|
||||
var http = require('http'),
|
||||
https = require('https'),
|
||||
web_o = require('./web-outgoing'),
|
||||
common = require('../common'),
|
||||
passes = exports;
|
||||
|
||||
web_o = Object.keys(web_o).map(function(pass) {
|
||||
return web_o[pass];
|
||||
});
|
||||
|
||||
/*!
|
||||
* Array of passes.
|
||||
*
|
||||
* A `pass` is just a function that is executed on `req, res, options`
|
||||
* so that you can easily add new checks while still keeping the base
|
||||
* flexible.
|
||||
*/
|
||||
|
||||
[ // <--
|
||||
|
||||
/**
|
||||
* Sets `content-length` to '0' if request is of DELETE type.
|
||||
*
|
||||
* @param {ClientRequest} Req Request object
|
||||
* @param {IncomingMessage} Res Response object
|
||||
* @param {Object} Options Config object passed to the proxy
|
||||
*
|
||||
* @api private
|
||||
*/
|
||||
|
||||
function deleteLength(req, res, options) {
|
||||
if(req.method === 'DELETE' && !req.headers['content-length']) {
|
||||
req.headers['content-length'] = '0';
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Sets timeout in request socket if it was specified in options.
|
||||
*
|
||||
* @param {ClientRequest} Req Request object
|
||||
* @param {IncomingMessage} Res Response object
|
||||
* @param {Object} Options Config object passed to the proxy
|
||||
*
|
||||
* @api private
|
||||
*/
|
||||
|
||||
function timeout(req, res, options) {
|
||||
if(options.timeout) {
|
||||
req.socket.setTimeout(options.timeout);
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Sets `x-forwarded-*` headers if specified in config.
|
||||
*
|
||||
* @param {ClientRequest} Req Request object
|
||||
* @param {IncomingMessage} Res Response object
|
||||
* @param {Object} Options Config object passed to the proxy
|
||||
*
|
||||
* @api private
|
||||
*/
|
||||
|
||||
function XHeaders(req, res, options) {
|
||||
if(!options.xfwd) return;
|
||||
|
||||
var values = {
|
||||
for : req.connection.remoteAddress || req.socket.remoteAddress,
|
||||
port : common.getPort(req),
|
||||
proto: req.isSpdy ? 'https' : (req.connection.pair ? 'https' : 'http')
|
||||
};
|
||||
|
||||
['for', 'port', 'proto'].forEach(function(header) {
|
||||
req.headers['x-forwarded-' + header] =
|
||||
(req.headers['x-forwarded-' + header] || '') +
|
||||
(req.headers['x-forwarded-' + header] ? ',' : '') +
|
||||
values[header];
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* Does the actual proxying. If `forward` is enabled fires up
|
||||
* a ForwardStream, same happens for ProxyStream. The request
|
||||
* just dies otherwise.
|
||||
*
|
||||
* @param {ClientRequest} Req Request object
|
||||
* @param {IncomingMessage} Res Response object
|
||||
* @param {Object} Options Config object passed to the proxy
|
||||
*
|
||||
* @api private
|
||||
*/
|
||||
|
||||
function stream(req, res, options, _, server, clb) {
|
||||
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')
|
||||
);
|
||||
(options.buffer || req).pipe(forwardReq);
|
||||
if(!options.target) { return res.end(); }
|
||||
}
|
||||
|
||||
// Request initalization
|
||||
var proxyReq = (options.target.protocol === 'https:' ? https : http).request(
|
||||
common.setupOutgoing(options.ssl || {}, options, req)
|
||||
);
|
||||
|
||||
// Error Handler
|
||||
proxyReq.on('error', function(err){
|
||||
if(options.buffer) { options.buffer.destroy(); }
|
||||
if (clb) {
|
||||
clb(err);
|
||||
} else {
|
||||
server.emit('error', err, req, res);
|
||||
}
|
||||
});
|
||||
|
||||
(options.buffer || req).pipe(proxyReq);
|
||||
|
||||
proxyReq.on('response', function(proxyRes) {
|
||||
server.emit('proxyRes', proxyRes);
|
||||
for(var i=0; i < web_o.length; i++) {
|
||||
if(web_o[i](req, res, proxyRes)) { break; }
|
||||
}
|
||||
|
||||
proxyRes.pipe(res);
|
||||
});
|
||||
|
||||
//proxyReq.end();
|
||||
}
|
||||
|
||||
] // <--
|
||||
.forEach(function(func) {
|
||||
passes[func.name] = func;
|
||||
});
|
||||
78
lib/http-proxy/passes/web-outgoing.js
Normal file
78
lib/http-proxy/passes/web-outgoing.js
Normal file
@ -0,0 +1,78 @@
|
||||
var passes = exports;
|
||||
|
||||
/*!
|
||||
* Array of passes.
|
||||
*
|
||||
* A `pass` is just a function that is executed on `req, res, options`
|
||||
* so that you can easily add new checks while still keeping the base
|
||||
* flexible.
|
||||
*/
|
||||
|
||||
[ // <--
|
||||
|
||||
/**
|
||||
* If is a HTTP 1.0 request, remove chunk headers
|
||||
*
|
||||
* @param {ClientRequest} Req Request object
|
||||
* @param {IncomingMessage} Res Response object
|
||||
* @param {proxyResponse} Res Response object from the proxy request
|
||||
*
|
||||
* @api private
|
||||
*/
|
||||
function removeChunked(req, res, proxyRes) {
|
||||
if(req.httpVersion === '1.0') {
|
||||
delete proxyRes.headers['transfer-encoding'];
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* If is a HTTP 1.0 request, set the correct connection header
|
||||
* or if connection header not present, then use `keep-alive`
|
||||
*
|
||||
* @param {ClientRequest} Req Request object
|
||||
* @param {IncomingMessage} Res Response object
|
||||
* @param {proxyResponse} Res Response object from the proxy request
|
||||
*
|
||||
* @api private
|
||||
*/
|
||||
function setConnection(req, res, proxyRes) {
|
||||
if (req.httpVersion === '1.0') {
|
||||
proxyRes.headers.connection = req.headers.connection || 'close';
|
||||
} else if (!proxyRes.headers.connection) {
|
||||
proxyRes.headers.connection = req.headers.connection || 'keep-alive';
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Copy headers from proxyResponse to response
|
||||
* set each header in response object.
|
||||
*
|
||||
* @param {ClientRequest} Req Request object
|
||||
* @param {IncomingMessage} Res Response object
|
||||
* @param {proxyResponse} Res Response object from the proxy request
|
||||
*
|
||||
* @api private
|
||||
*/
|
||||
function writeHeaders(req, res, proxyRes) {
|
||||
Object.keys(proxyRes.headers).forEach(function(key) {
|
||||
res.setHeader(key, proxyRes.headers[key]);
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* Set the statusCode from the proxyResponse
|
||||
*
|
||||
* @param {ClientRequest} Req Request object
|
||||
* @param {IncomingMessage} Res Response object
|
||||
* @param {proxyResponse} Res Response object from the proxy request
|
||||
*
|
||||
* @api private
|
||||
*/
|
||||
function writeStatusCode(req, res, proxyRes) {
|
||||
res.writeHead(proxyRes.statusCode);
|
||||
}
|
||||
|
||||
] // <--
|
||||
.forEach(function(func) {
|
||||
passes[func.name] = func;
|
||||
});
|
||||
121
lib/http-proxy/passes/ws-incoming.js
Normal file
121
lib/http-proxy/passes/ws-incoming.js
Normal file
@ -0,0 +1,121 @@
|
||||
var http = require('http'),
|
||||
https = require('https'),
|
||||
common = require('../common'),
|
||||
passes = exports;
|
||||
|
||||
/*!
|
||||
* Array of passes.
|
||||
*
|
||||
* A `pass` is just a function that is executed on `req, socket, options`
|
||||
* so that you can easily add new checks while still keeping the base
|
||||
* flexible.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Websockets Passes
|
||||
*
|
||||
*/
|
||||
|
||||
var passes = exports;
|
||||
|
||||
[
|
||||
/**
|
||||
* WebSocket requests must have the `GET` method and
|
||||
* the `upgrade:websocket` header
|
||||
*
|
||||
* @param {ClientRequest} Req Request object
|
||||
* @param {Socket} Websocket
|
||||
*
|
||||
* @api private
|
||||
*/
|
||||
|
||||
function checkMethodAndHeader (req, socket) {
|
||||
if (req.method !== 'GET' || !req.headers.upgrade) {
|
||||
socket.destroy();
|
||||
return true;
|
||||
}
|
||||
|
||||
if (req.headers.upgrade.toLowerCase() !== 'websocket') {
|
||||
socket.destroy();
|
||||
return true;
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Sets `x-forwarded-*` headers if specified in config.
|
||||
*
|
||||
* @param {ClientRequest} Req Request object
|
||||
* @param {Socket} Websocket
|
||||
* @param {Object} Options Config object passed to the proxy
|
||||
*
|
||||
* @api private
|
||||
*/
|
||||
|
||||
function XHeaders(req, socket, options) {
|
||||
if(!options.xfwd) return;
|
||||
|
||||
var values = {
|
||||
for : req.connection.remoteAddress || req.socket.remoteAddress,
|
||||
port : common.getPort(req),
|
||||
proto: req.connection.pair ? 'wss' : 'ws'
|
||||
};
|
||||
|
||||
['for', 'port', 'proto'].forEach(function(header) {
|
||||
req.headers['x-forwarded-' + header] =
|
||||
(req.headers['x-forwarded-' + header] || '') +
|
||||
(req.headers['x-forwarded-' + header] ? ',' : '') +
|
||||
values[header];
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* Does the actual proxying. Make the request and upgrade it
|
||||
* send the Switching Protocols request and pipe the sockets.
|
||||
*
|
||||
* @param {ClientRequest} Req Request object
|
||||
* @param {Socket} Websocket
|
||||
* @param {Object} Options Config object passed to the proxy
|
||||
*
|
||||
* @api private
|
||||
*/
|
||||
function stream(req, socket, options, server, head, clb) {
|
||||
common.setupSocket(socket);
|
||||
|
||||
if (head && head.length) socket.unshift(head);
|
||||
|
||||
|
||||
var proxyReq = (~['https:', 'wss:'].indexOf(options.target.protocol) ? https : http).request(
|
||||
common.setupOutgoing(options.ssl || {}, options, req)
|
||||
);
|
||||
// Error Handler
|
||||
proxyReq.on('error', onError);
|
||||
|
||||
proxyReq.on('upgrade', function(proxyRes, proxySocket, proxyHead) {
|
||||
proxySocket.on('error', onError);
|
||||
|
||||
common.setupSocket(proxySocket);
|
||||
|
||||
if (proxyHead && proxyHead.length) proxySocket.unshift(proxyHead);
|
||||
|
||||
socket.write('HTTP/1.1 101 Switching Protocols\r\n');
|
||||
socket.write(Object.keys(proxyRes.headers).map(function(i) {
|
||||
return i + ": " + proxyRes.headers[i];
|
||||
}).join('\r\n') + '\r\n\r\n');
|
||||
proxySocket.pipe(socket).pipe(proxySocket);
|
||||
});
|
||||
|
||||
return proxyReq.end(); // XXX: CHECK IF THIS IS THIS CORRECT
|
||||
|
||||
function onError(err) {
|
||||
if (clb) {
|
||||
clb(err);
|
||||
} else {
|
||||
server.emit('error', err, req, socket);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
] // <--
|
||||
.forEach(function(func) {
|
||||
passes[func.name] = func;
|
||||
});
|
||||
40
package.json
Normal file
40
package.json
Normal file
@ -0,0 +1,40 @@
|
||||
{
|
||||
"name" : "http-proxy",
|
||||
"version" : "1.0.0",
|
||||
"description" : "HTTP proxying for the masses",
|
||||
"author": "Nodejitsu Inc. <info@nodejitsu.com>",
|
||||
"maintainers" : [
|
||||
"yawnt <yawnt@nodejitsu.com>",
|
||||
"indexzero <charlie@nodejitsu.com>"
|
||||
],
|
||||
|
||||
"main" : "index.js",
|
||||
|
||||
"dependencies" : {
|
||||
"eventemitter3" : "*"
|
||||
},
|
||||
"devDependencies": {
|
||||
"mocha" : "*",
|
||||
"expect.js" : "*",
|
||||
"dox" : "*",
|
||||
"coveralls" : "*",
|
||||
"mocha-lcov-reporter": "*",
|
||||
"blanket" : "*",
|
||||
"ws" : "*",
|
||||
"socket.io" : "*",
|
||||
"socket.io-client" : "*",
|
||||
"async" : "*"
|
||||
},
|
||||
"scripts" : {
|
||||
"coveralls" : "mocha --require blanket --reporter mocha-lcov-reporter | ./node_modules/coveralls/bin/coveralls.js",
|
||||
"blanket" : { "pattern": "lib/http-proxy" },
|
||||
"test" : "mocha -R landing test/*-test.js",
|
||||
"test-cov" : "mocha --require blanket -R html-cov > cov/coverage.html"
|
||||
},
|
||||
|
||||
"engines" : {
|
||||
"node" : ">=0.10.0"
|
||||
},
|
||||
|
||||
"license" : "MIT"
|
||||
}
|
||||
71
test/examples-test.js
Normal file
71
test/examples-test.js
Normal file
@ -0,0 +1,71 @@
|
||||
/*
|
||||
examples-test.js: Test to run all the examples
|
||||
|
||||
Copyright (c) Nodejitsu 2013
|
||||
|
||||
*/
|
||||
var path = require('path'),
|
||||
fs = require('fs'),
|
||||
spawn = require('child_process').spawn,
|
||||
expect = require('expect.js'),
|
||||
async = require('async');
|
||||
|
||||
var rootDir = path.join(__dirname, '..'),
|
||||
examplesDir = path.join(rootDir, 'examples');
|
||||
|
||||
describe.skip('http-proxy examples', function () {
|
||||
describe('Before testing examples', function () {
|
||||
// Set a timeout to avoid this error
|
||||
this.timeout(30 * 1000);
|
||||
it('should have installed dependencies', function (done) {
|
||||
async.waterfall([
|
||||
//
|
||||
// 1. Read files in examples dir
|
||||
//
|
||||
async.apply(fs.readdir, examplesDir),
|
||||
//
|
||||
// 2. If node_modules exists, continue. Otherwise
|
||||
// exec `npm` to install them
|
||||
//
|
||||
function checkNodeModules(files, next) {
|
||||
if (files.indexOf('node_modules') !== -1) {
|
||||
return next();
|
||||
}
|
||||
|
||||
console.log('Warning: installing dependencies, this operation could take a while');
|
||||
|
||||
var child = spawn('npm', ['install', '-f'], {
|
||||
cwd: examplesDir
|
||||
});
|
||||
|
||||
child.on('exit', function (code) {
|
||||
return code
|
||||
? next(new Error('npm install exited with non-zero exit code'))
|
||||
: next();
|
||||
});
|
||||
},
|
||||
//
|
||||
// 3. Read files in examples dir again to ensure the install
|
||||
// worked as expected.
|
||||
//
|
||||
async.apply(fs.readdir, examplesDir),
|
||||
], done);
|
||||
})
|
||||
});
|
||||
|
||||
describe('Requiring all the examples', function () {
|
||||
it('should have no errors', function (done) {
|
||||
async.each(['balancer', 'http', 'middleware', 'websocket'], function (dir, cb) {
|
||||
var name = 'examples/' + dir,
|
||||
files = fs.readdirSync(path.join(rootDir, 'examples', dir));
|
||||
|
||||
async.each(files, function (file, callback) {
|
||||
var example;
|
||||
expect(function () { example = require(path.join(examplesDir, dir, file)); }).to.not.throwException();
|
||||
expect(example).to.be.an('object');
|
||||
callback();
|
||||
}, cb);
|
||||
}, done);
|
||||
})
|
||||
})
|
||||
})
|
||||
13
test/fixtures/agent2-cert.pem
vendored
Normal file
13
test/fixtures/agent2-cert.pem
vendored
Normal file
@ -0,0 +1,13 @@
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIIB7DCCAZYCCQC7gs0MDNn6MTANBgkqhkiG9w0BAQUFADB9MQswCQYDVQQGEwJV
|
||||
UzELMAkGA1UECBMCQ0ExCzAJBgNVBAcTAlNGMQ8wDQYDVQQKEwZKb3llbnQxEDAO
|
||||
BgNVBAsTB05vZGUuanMxDzANBgNVBAMTBmFnZW50MjEgMB4GCSqGSIb3DQEJARYR
|
||||
cnlAdGlueWNsb3Vkcy5vcmcwHhcNMTEwMzE0MTgyOTEyWhcNMzgwNzI5MTgyOTEy
|
||||
WjB9MQswCQYDVQQGEwJVUzELMAkGA1UECBMCQ0ExCzAJBgNVBAcTAlNGMQ8wDQYD
|
||||
VQQKEwZKb3llbnQxEDAOBgNVBAsTB05vZGUuanMxDzANBgNVBAMTBmFnZW50MjEg
|
||||
MB4GCSqGSIb3DQEJARYRcnlAdGlueWNsb3Vkcy5vcmcwXDANBgkqhkiG9w0BAQEF
|
||||
AANLADBIAkEAyXb8FrRdKbhrKLgLSsn61i1C7w7fVVVd7OQsmV/7p9WB2lWFiDlC
|
||||
WKGU9SiIz/A6wNZDUAuc2E+VwtpCT561AQIDAQABMA0GCSqGSIb3DQEBBQUAA0EA
|
||||
C8HzpuNhFLCI3A5KkBS5zHAQax6TFUOhbpBCR0aTDbJ6F1liDTK1lmU/BjvPoj+9
|
||||
1LHwrmh29rK8kBPEjmymCQ==
|
||||
-----END CERTIFICATE-----
|
||||
10
test/fixtures/agent2-csr.pem
vendored
Normal file
10
test/fixtures/agent2-csr.pem
vendored
Normal file
@ -0,0 +1,10 @@
|
||||
-----BEGIN CERTIFICATE REQUEST-----
|
||||
MIIBXTCCAQcCAQAwfTELMAkGA1UEBhMCVVMxCzAJBgNVBAgTAkNBMQswCQYDVQQH
|
||||
EwJTRjEPMA0GA1UEChMGSm95ZW50MRAwDgYDVQQLEwdOb2RlLmpzMQ8wDQYDVQQD
|
||||
EwZhZ2VudDIxIDAeBgkqhkiG9w0BCQEWEXJ5QHRpbnljbG91ZHMub3JnMFwwDQYJ
|
||||
KoZIhvcNAQEBBQADSwAwSAJBAMl2/Ba0XSm4ayi4C0rJ+tYtQu8O31VVXezkLJlf
|
||||
+6fVgdpVhYg5QlihlPUoiM/wOsDWQ1ALnNhPlcLaQk+etQECAwEAAaAlMCMGCSqG
|
||||
SIb3DQEJBzEWExRBIGNoYWxsZW5nZSBwYXNzd29yZDANBgkqhkiG9w0BAQUFAANB
|
||||
AJnll2pt5l0pzskQSpjjLVTlFDFmJr/AZ3UK8v0WxBjYjCe5Jx4YehkChpxIyDUm
|
||||
U3J9q9MDUf0+Y2+EGkssFfk=
|
||||
-----END CERTIFICATE REQUEST-----
|
||||
9
test/fixtures/agent2-key.pem
vendored
Normal file
9
test/fixtures/agent2-key.pem
vendored
Normal file
@ -0,0 +1,9 @@
|
||||
-----BEGIN RSA PRIVATE KEY-----
|
||||
MIIBOgIBAAJBAMl2/Ba0XSm4ayi4C0rJ+tYtQu8O31VVXezkLJlf+6fVgdpVhYg5
|
||||
QlihlPUoiM/wOsDWQ1ALnNhPlcLaQk+etQECAwEAAQJBAMT6Bf34+UHKY1ObpsbH
|
||||
9u2jsVblFq1rWvs8GPMY6oertzvwm3DpuSUp7PTgOB1nLTLYtCERbQ4ovtN8tn3p
|
||||
OHUCIQDzIEGsoCr5vlxXvy2zJwu+fxYuhTZWMVuo1397L0VyhwIhANQh+yzqUgaf
|
||||
WRtSB4T2W7ADtJI35ET61jKBty3CqJY3AiAIwju7dVW3A5WeD6Qc1SZGKZvp9yCb
|
||||
AFI2BfVwwaY11wIgXF3PeGcvACMyMWsuSv7aPXHfliswAbkWuzcwA4TW01ECIGWa
|
||||
cgsDvVFxmfM5NPSuT/UDTa6R5BFISB5ea0N0AR3I
|
||||
-----END RSA PRIVATE KEY-----
|
||||
19
test/fixtures/agent2.cnf
vendored
Normal file
19
test/fixtures/agent2.cnf
vendored
Normal file
@ -0,0 +1,19 @@
|
||||
[ 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
|
||||
|
||||
103
test/lib-http-proxy-common-test.js
Normal file
103
test/lib-http-proxy-common-test.js
Normal file
@ -0,0 +1,103 @@
|
||||
var common = require('../lib/http-proxy/common'),
|
||||
expect = require('expect.js');
|
||||
|
||||
describe('lib/http-proxy/common.js', function () {
|
||||
describe('#setupOutgoing', function () {
|
||||
it('should setup the correct headers', function () {
|
||||
var outgoing = {};
|
||||
common.setupOutgoing(outgoing,
|
||||
{
|
||||
agent : '?',
|
||||
target: {
|
||||
host : 'hey',
|
||||
hostname : 'how',
|
||||
socketPath: 'are',
|
||||
port : 'you',
|
||||
},
|
||||
headers: {'fizz': 'bang', 'overwritten':true},
|
||||
},
|
||||
{
|
||||
method : 'i',
|
||||
url : 'am',
|
||||
headers : {'pro':'xy','overwritten':false}
|
||||
});
|
||||
|
||||
expect(outgoing.host).to.eql('hey');
|
||||
expect(outgoing.hostname).to.eql('how');
|
||||
expect(outgoing.socketPath).to.eql('are');
|
||||
expect(outgoing.port).to.eql('you');
|
||||
expect(outgoing.agent).to.eql('?');
|
||||
|
||||
expect(outgoing.method).to.eql('i');
|
||||
expect(outgoing.path).to.eql('am');
|
||||
|
||||
expect(outgoing.headers.pro).to.eql('xy');
|
||||
expect(outgoing.headers.fizz).to.eql('bang');
|
||||
expect(outgoing.headers.overwritten).to.eql(true);
|
||||
});
|
||||
|
||||
it('should set the agent to false if none is given', function () {
|
||||
var outgoing = {};
|
||||
common.setupOutgoing(outgoing, {target:
|
||||
'http://localhost'
|
||||
}, { url: '/' });
|
||||
expect(outgoing.agent).to.eql(false);
|
||||
});
|
||||
|
||||
it('set the port according to the protocol', function () {
|
||||
var outgoing = {};
|
||||
common.setupOutgoing(outgoing,
|
||||
{
|
||||
agent : '?',
|
||||
target: {
|
||||
host : 'how',
|
||||
hostname : 'are',
|
||||
socketPath: 'you',
|
||||
protocol: 'https:'
|
||||
}
|
||||
},
|
||||
{
|
||||
method : 'i',
|
||||
url : 'am',
|
||||
headers : 'proxy'
|
||||
});
|
||||
|
||||
expect(outgoing.host).to.eql('how');
|
||||
expect(outgoing.hostname).to.eql('are');
|
||||
expect(outgoing.socketPath).to.eql('you');
|
||||
expect(outgoing.agent).to.eql('?');
|
||||
|
||||
expect(outgoing.method).to.eql('i');
|
||||
expect(outgoing.path).to.eql('am');
|
||||
expect(outgoing.headers).to.eql('proxy')
|
||||
|
||||
expect(outgoing.port).to.eql(443);
|
||||
});
|
||||
});
|
||||
|
||||
describe('#setupSocket', function () {
|
||||
it('should setup a socket', function () {
|
||||
var socketConfig = {
|
||||
timeout: null,
|
||||
nodelay: false,
|
||||
keepalive: false
|
||||
},
|
||||
stubSocket = {
|
||||
setTimeout: function (num) {
|
||||
socketConfig.timeout = num;
|
||||
},
|
||||
setNoDelay: function (bol) {
|
||||
socketConfig.nodelay = bol;
|
||||
},
|
||||
setKeepAlive: function (bol) {
|
||||
socketConfig.keepalive = bol;
|
||||
}
|
||||
}
|
||||
returnValue = common.setupSocket(stubSocket);
|
||||
|
||||
expect(socketConfig.timeout).to.eql(0);
|
||||
expect(socketConfig.nodelay).to.eql(true);
|
||||
expect(socketConfig.keepalive).to.eql(true);
|
||||
});
|
||||
});
|
||||
});
|
||||
130
test/lib-http-proxy-passes-web-incoming-test.js
Normal file
130
test/lib-http-proxy-passes-web-incoming-test.js
Normal file
@ -0,0 +1,130 @@
|
||||
var webPasses = require('../lib/http-proxy/passes/web-incoming'),
|
||||
httpProxy = require('../lib/http-proxy'),
|
||||
expect = require('expect.js'),
|
||||
http = require('http');
|
||||
|
||||
describe('lib/http-proxy/passes/web.js', function() {
|
||||
describe('#deleteLength', function() {
|
||||
it('should change `content-length`', function() {
|
||||
var stubRequest = {
|
||||
method: 'DELETE',
|
||||
headers: {}
|
||||
};
|
||||
webPasses.deleteLength(stubRequest, {}, {});
|
||||
expect(stubRequest.headers['content-length']).to.eql('0');
|
||||
})
|
||||
});
|
||||
|
||||
describe('#timeout', function() {
|
||||
it('should set timeout on the socket', function() {
|
||||
var done = false, stubRequest = {
|
||||
socket: {
|
||||
setTimeout: function(value) { done = value; }
|
||||
}
|
||||
}
|
||||
|
||||
webPasses.timeout(stubRequest, {}, { timeout: 5000});
|
||||
expect(done).to.eql(5000);
|
||||
});
|
||||
});
|
||||
|
||||
describe('#XHeaders', function () {
|
||||
var stubRequest = {
|
||||
connection: {
|
||||
remoteAddress: '192.168.1.2',
|
||||
remotePort: '8080'
|
||||
},
|
||||
headers: {
|
||||
host: '192.168.1.2:8080'
|
||||
}
|
||||
}
|
||||
|
||||
it('set the correct x-forwarded-* headers', function () {
|
||||
webPasses.XHeaders(stubRequest, {}, { xfwd: true });
|
||||
expect(stubRequest.headers['x-forwarded-for']).to.be('192.168.1.2');
|
||||
expect(stubRequest.headers['x-forwarded-port']).to.be('8080');
|
||||
expect(stubRequest.headers['x-forwarded-proto']).to.be('http');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('#createProxyServer.web() using own http server', function () {
|
||||
it('should proxy the request using the web proxy handler', function (done) {
|
||||
var proxy = httpProxy.createProxyServer({
|
||||
target: 'http://127.0.0.1:8080'
|
||||
});
|
||||
|
||||
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.method).to.eql('GET');
|
||||
expect(req.headers.host.split(':')[1]).to.eql('8081');
|
||||
done();
|
||||
});
|
||||
|
||||
proxyServer.listen('8081');
|
||||
source.listen('8080');
|
||||
|
||||
http.request('http://127.0.0.1:8081', function() {}).end();
|
||||
});
|
||||
|
||||
it('should proxy the request and handle error via callback', function(done) {
|
||||
var proxy = httpProxy.createProxyServer({
|
||||
target: 'http://127.0.0.1:8080'
|
||||
});
|
||||
|
||||
var proxyServer = http.createServer(requestHandler);
|
||||
|
||||
function requestHandler(req, res) {
|
||||
proxy.web(req, res, function (err) {
|
||||
proxyServer.close();
|
||||
expect(err).to.be.an(Error);
|
||||
expect(err.code).to.be('ECONNREFUSED');
|
||||
done();
|
||||
});
|
||||
}
|
||||
|
||||
proxyServer.listen('8082');
|
||||
|
||||
http.request({
|
||||
hostname: '127.0.0.1',
|
||||
port: '8082',
|
||||
method: 'GET',
|
||||
}, function() {}).end();
|
||||
});
|
||||
|
||||
it('should proxy the request and handle error via event listener', function(done) {
|
||||
var proxy = httpProxy.createProxyServer({
|
||||
target: '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();
|
||||
});
|
||||
});
|
||||
104
test/lib-http-proxy-passes-web-outgoing-test.js
Normal file
104
test/lib-http-proxy-passes-web-outgoing-test.js
Normal file
@ -0,0 +1,104 @@
|
||||
var httpProxy = require('../lib/http-proxy/passes/web-outgoing'),
|
||||
expect = require('expect.js');
|
||||
|
||||
describe('lib/http-proxy/passes/web-outgoing.js', function () {
|
||||
describe('#setConnection', function () {
|
||||
it('set the right connection with 1.0 - `close`', function() {
|
||||
var proxyRes = { headers: {} };
|
||||
httpProxy.setConnection({
|
||||
httpVersion: '1.0',
|
||||
headers: {
|
||||
connection: null
|
||||
}
|
||||
}, {}, proxyRes);
|
||||
|
||||
expect(proxyRes.headers.connection).to.eql('close');
|
||||
});
|
||||
|
||||
it('set the right connection with 1.0 - req.connection', function() {
|
||||
var proxyRes = { headers: {} };
|
||||
httpProxy.setConnection({
|
||||
httpVersion: '1.0',
|
||||
headers: {
|
||||
connection: 'hey'
|
||||
}
|
||||
}, {}, proxyRes);
|
||||
|
||||
expect(proxyRes.headers.connection).to.eql('hey');
|
||||
});
|
||||
|
||||
it('set the right connection - req.connection', function() {
|
||||
var proxyRes = { headers: {} };
|
||||
httpProxy.setConnection({
|
||||
httpVersion: null,
|
||||
headers: {
|
||||
connection: 'hola'
|
||||
}
|
||||
}, {}, proxyRes);
|
||||
|
||||
expect(proxyRes.headers.connection).to.eql('hola');
|
||||
});
|
||||
|
||||
it('set the right connection - `keep-alive`', function() {
|
||||
var proxyRes = { headers: {} };
|
||||
httpProxy.setConnection({
|
||||
httpVersion: null,
|
||||
headers: {
|
||||
connection: null
|
||||
}
|
||||
}, {}, proxyRes);
|
||||
|
||||
expect(proxyRes.headers.connection).to.eql('keep-alive');
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
describe('#writeStatusCode', function () {
|
||||
it('should write status code', function() {
|
||||
var res = {
|
||||
writeHead: function(n) {
|
||||
expect(n).to.eql(200);
|
||||
}
|
||||
}
|
||||
|
||||
httpProxy.writeStatusCode({}, res, { statusCode: 200 });
|
||||
});
|
||||
});
|
||||
|
||||
describe('#writeHeaders', function() {
|
||||
var proxyRes = {
|
||||
headers: {
|
||||
hey: 'hello',
|
||||
how: 'are you?'
|
||||
}
|
||||
};
|
||||
|
||||
var res = {
|
||||
setHeader: function(k, v) {
|
||||
this.headers[k] = v;
|
||||
},
|
||||
headers: {}
|
||||
};
|
||||
|
||||
httpProxy.writeHeaders({}, res, proxyRes);
|
||||
|
||||
expect(res.headers.hey).to.eql('hello');
|
||||
expect(res.headers.how).to.eql('are you?');
|
||||
});
|
||||
|
||||
|
||||
describe('#removeChunked', function() {
|
||||
var proxyRes = {
|
||||
headers: {
|
||||
'transfer-encoding': 'hello'
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
httpProxy.removeChunked({ httpVersion: '1.0' }, {}, proxyRes);
|
||||
|
||||
expect(proxyRes.headers['transfer-encoding']).to.eql(undefined);
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
120
test/lib-http-proxy-passes-ws-incoming-test.js
Normal file
120
test/lib-http-proxy-passes-ws-incoming-test.js
Normal file
@ -0,0 +1,120 @@
|
||||
var httpProxy = require('../lib/http-proxy/passes/ws-incoming'),
|
||||
expect = require('expect.js');
|
||||
|
||||
describe('lib/http-proxy/passes/ws-incoming.js', function () {
|
||||
describe('#checkMethodAndHeader', function () {
|
||||
it('should drop non-GET connections', function () {
|
||||
var destroyCalled = false,
|
||||
stubRequest = {
|
||||
method: 'DELETE',
|
||||
headers: {}
|
||||
},
|
||||
stubSocket = {
|
||||
destroy: function () {
|
||||
// Simulate Socket.destroy() method when call
|
||||
destroyCalled = true;
|
||||
}
|
||||
}
|
||||
returnValue = httpProxy.checkMethodAndHeader(stubRequest, stubSocket);
|
||||
expect(returnValue).to.be(true);
|
||||
expect(destroyCalled).to.be(true);
|
||||
})
|
||||
|
||||
it('should drop connections when no upgrade header', function () {
|
||||
var destroyCalled = false,
|
||||
stubRequest = {
|
||||
method: 'GET',
|
||||
headers: {}
|
||||
},
|
||||
stubSocket = {
|
||||
destroy: function () {
|
||||
// Simulate Socket.destroy() method when call
|
||||
destroyCalled = true;
|
||||
}
|
||||
}
|
||||
returnValue = httpProxy.checkMethodAndHeader(stubRequest, stubSocket);
|
||||
expect(returnValue).to.be(true);
|
||||
expect(destroyCalled).to.be(true);
|
||||
})
|
||||
|
||||
it('should drop connections when upgrade header is different of `websocket`', function () {
|
||||
var destroyCalled = false,
|
||||
stubRequest = {
|
||||
method: 'GET',
|
||||
headers: {
|
||||
upgrade: 'anotherprotocol'
|
||||
}
|
||||
},
|
||||
stubSocket = {
|
||||
destroy: function () {
|
||||
// Simulate Socket.destroy() method when call
|
||||
destroyCalled = true;
|
||||
}
|
||||
}
|
||||
returnValue = httpProxy.checkMethodAndHeader(stubRequest, stubSocket);
|
||||
expect(returnValue).to.be(true);
|
||||
expect(destroyCalled).to.be(true);
|
||||
})
|
||||
|
||||
it('should return nothing when all is ok', function () {
|
||||
var destroyCalled = false,
|
||||
stubRequest = {
|
||||
method: 'GET',
|
||||
headers: {
|
||||
upgrade: 'websocket'
|
||||
}
|
||||
},
|
||||
stubSocket = {
|
||||
destroy: function () {
|
||||
// Simulate Socket.destroy() method when call
|
||||
destroyCalled = true;
|
||||
}
|
||||
}
|
||||
returnValue = httpProxy.checkMethodAndHeader(stubRequest, stubSocket);
|
||||
expect(returnValue).to.be(undefined);
|
||||
expect(destroyCalled).to.be(false);
|
||||
})
|
||||
});
|
||||
|
||||
describe('#XHeaders', function () {
|
||||
it('return if no forward request', function () {
|
||||
var returnValue = httpProxy.XHeaders({}, {}, {});
|
||||
expect(returnValue).to.be(undefined);
|
||||
});
|
||||
|
||||
it('set the correct x-forwarded-* headers from req.connection', function () {
|
||||
var stubRequest = {
|
||||
connection: {
|
||||
remoteAddress: '192.168.1.2',
|
||||
remotePort: '8080'
|
||||
},
|
||||
headers: {
|
||||
host: '192.168.1.2:8080'
|
||||
}
|
||||
}
|
||||
httpProxy.XHeaders(stubRequest, {}, { xfwd: true });
|
||||
expect(stubRequest.headers['x-forwarded-for']).to.be('192.168.1.2');
|
||||
expect(stubRequest.headers['x-forwarded-port']).to.be('8080');
|
||||
expect(stubRequest.headers['x-forwarded-proto']).to.be('ws');
|
||||
});
|
||||
|
||||
it('set the correct x-forwarded-* headers from req.socket', function () {
|
||||
var stubRequest = {
|
||||
socket: {
|
||||
remoteAddress: '192.168.1.3',
|
||||
remotePort: '8181'
|
||||
},
|
||||
connection: {
|
||||
pair: true
|
||||
},
|
||||
headers: {
|
||||
host: '192.168.1.3:8181'
|
||||
}
|
||||
};
|
||||
httpProxy.XHeaders(stubRequest, {}, { xfwd: true });
|
||||
expect(stubRequest.headers['x-forwarded-for']).to.be('192.168.1.3');
|
||||
expect(stubRequest.headers['x-forwarded-port']).to.be('8181');
|
||||
expect(stubRequest.headers['x-forwarded-proto']).to.be('wss');
|
||||
});
|
||||
});
|
||||
});
|
||||
297
test/lib-http-proxy-test.js
Normal file
297
test/lib-http-proxy-test.js
Normal file
@ -0,0 +1,297 @@
|
||||
var httpProxy = require('../lib/http-proxy'),
|
||||
expect = require('expect.js'),
|
||||
http = require('http'),
|
||||
ws = require('ws')
|
||||
io = require('socket.io'),
|
||||
ioClient = require('socket.io-client');
|
||||
|
||||
//
|
||||
// Expose a port number generator.
|
||||
// thanks to @3rd-Eden
|
||||
//
|
||||
var initialPort = 1024, gen = {};
|
||||
Object.defineProperty(gen, 'port', {
|
||||
get: function get() {
|
||||
return initialPort++;
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
describe('lib/http-proxy.js', function() {
|
||||
describe('#createProxyServer', function() {
|
||||
it.skip('should throw without options', function() {
|
||||
var error;
|
||||
try {
|
||||
httpProxy.createProxyServer();
|
||||
} catch(e) {
|
||||
error = e;
|
||||
}
|
||||
|
||||
expect(error).to.be.an(Error);
|
||||
})
|
||||
|
||||
it('should return an object otherwise', function() {
|
||||
var obj = httpProxy.createProxyServer({
|
||||
target: 'http://www.google.com:80'
|
||||
});
|
||||
|
||||
expect(obj.web).to.be.a(Function);
|
||||
expect(obj.ws).to.be.a(Function);
|
||||
expect(obj.listen).to.be.a(Function);
|
||||
});
|
||||
});
|
||||
|
||||
describe('#createProxyServer with forward options and using web-incoming passes', function () {
|
||||
it('should pipe the request using web-incoming#stream method', function (done) {
|
||||
var ports = { source: gen.port, proxy: gen.port };
|
||||
var proxy = httpProxy.createProxyServer({
|
||||
forward: 'http://127.0.0.1:' + ports.source
|
||||
}).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.proxy);
|
||||
source.close();
|
||||
proxy._server.close();
|
||||
done();
|
||||
});
|
||||
|
||||
source.listen(ports.source);
|
||||
http.request('http://127.0.0.1:' + ports.proxy, function() {}).end();
|
||||
})
|
||||
});
|
||||
|
||||
describe('#createProxyServer using the web-incoming passes', function () {
|
||||
it('should make the request on pipe 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
|
||||
}).listen(ports.proxy);
|
||||
|
||||
var source = http.createServer(function(req, res) {
|
||||
expect(req.method).to.eql('POST');
|
||||
expect(req.headers['x-forwarded-for']).to.eql('127.0.0.1');
|
||||
expect(req.headers.host.split(':')[1]).to.eql(ports.proxy);
|
||||
source.close();
|
||||
proxy._server.close();
|
||||
done();
|
||||
});
|
||||
|
||||
source.listen(ports.source);
|
||||
|
||||
http.request({
|
||||
hostname: '127.0.0.1',
|
||||
port: ports.proxy,
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'x-forwarded-for': '127.0.0.1'
|
||||
}
|
||||
}, function() {}).end();
|
||||
});
|
||||
});
|
||||
|
||||
describe('#createProxyServer using the web-incoming passes', 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
|
||||
}).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.proxy);
|
||||
res.writeHead(200, {'Content-Type': 'text/plain'})
|
||||
res.end('Hello from ' + source.address().port);
|
||||
});
|
||||
|
||||
source.listen(ports.source);
|
||||
|
||||
http.request({
|
||||
hostname: '127.0.0.1',
|
||||
port: ports.proxy,
|
||||
method: 'GET'
|
||||
}, function(res) {
|
||||
expect(res.statusCode).to.eql(200);
|
||||
|
||||
res.on('data', function (data) {
|
||||
expect(data.toString()).to.eql('Hello from ' + ports.source);
|
||||
});
|
||||
|
||||
res.on('end', function () {
|
||||
source.close();
|
||||
proxy._server.close();
|
||||
done();
|
||||
});
|
||||
}).end();
|
||||
});
|
||||
});
|
||||
|
||||
describe('#createProxyServer() method with error response', function () {
|
||||
it('should make the request and emit the error event', function(done) {
|
||||
var ports = { source: gen.port, proxy: gen.port };
|
||||
var proxy = httpProxy.createProxyServer({
|
||||
target: 'http://127.0.0.1:' + ports.source
|
||||
});
|
||||
|
||||
proxy.on('error', function (err) {
|
||||
expect(err).to.be.an(Error);
|
||||
expect(err.code).to.be('ECONNREFUSED');
|
||||
proxy._server.close();
|
||||
done();
|
||||
})
|
||||
|
||||
proxy.listen(ports.proxy);
|
||||
|
||||
http.request({
|
||||
hostname: '127.0.0.1',
|
||||
port: ports.proxy,
|
||||
method: 'GET',
|
||||
}, function() {}).end();
|
||||
});
|
||||
});
|
||||
|
||||
describe('#createProxyServer setting the correct timeout value', function () {
|
||||
it('should hang up the socket at the timeout', function (done) {
|
||||
this.timeout(30);
|
||||
var ports = { source: gen.port, proxy: gen.port };
|
||||
var proxy = httpProxy.createProxyServer({
|
||||
target: 'http://127.0.0.1:' + ports.source,
|
||||
timeout: 3
|
||||
}).listen(ports.proxy);
|
||||
|
||||
var source = http.createServer(function(req, res) {
|
||||
setTimeout(function () {
|
||||
res.end('At this point the socket should be closed');
|
||||
}, 5)
|
||||
});
|
||||
|
||||
source.listen(ports.source);
|
||||
|
||||
var testReq = http.request({
|
||||
hostname: '127.0.0.1',
|
||||
port: ports.proxy,
|
||||
method: 'GET',
|
||||
}, function() {});
|
||||
|
||||
testReq.on('error', function (e) {
|
||||
expect(e).to.be.an(Error);
|
||||
expect(e.code).to.be.eql('ECONNRESET');
|
||||
proxy._server.close();
|
||||
source.close();
|
||||
done();
|
||||
});
|
||||
|
||||
testReq.end();
|
||||
})
|
||||
})
|
||||
|
||||
// describe('#createProxyServer using the web-incoming passes', function () {
|
||||
// it('should emit events correclty', function(done) {
|
||||
// var proxy = httpProxy.createProxyServer({
|
||||
// target: 'http://127.0.0.1:8080'
|
||||
// }),
|
||||
|
||||
// proxyServer = proxy.listen('8081'),
|
||||
|
||||
// source = http.createServer(function(req, res) {
|
||||
// expect(req.method).to.eql('GET');
|
||||
// expect(req.headers.host.split(':')[1]).to.eql('8081');
|
||||
// res.writeHead(200, {'Content-Type': 'text/plain'})
|
||||
// res.end('Hello from ' + source.address().port);
|
||||
// }),
|
||||
|
||||
// events = [];
|
||||
|
||||
// source.listen('8080');
|
||||
|
||||
// proxy.ee.on('http-proxy:**', function (uno, dos, tres) {
|
||||
// events.push(this.event);
|
||||
// })
|
||||
|
||||
// http.request({
|
||||
// hostname: '127.0.0.1',
|
||||
// port: '8081',
|
||||
// method: 'GET',
|
||||
// }, function(res) {
|
||||
// expect(res.statusCode).to.eql(200);
|
||||
|
||||
// res.on('data', function (data) {
|
||||
// expect(data.toString()).to.eql('Hello from 8080');
|
||||
// });
|
||||
|
||||
// res.on('end', function () {
|
||||
// expect(events).to.contain('http-proxy:outgoing:web:begin');
|
||||
// expect(events).to.contain('http-proxy:outgoing:web:end');
|
||||
// source.close();
|
||||
// proxyServer._server.close();
|
||||
// done();
|
||||
// });
|
||||
// }).end();
|
||||
// });
|
||||
// });
|
||||
|
||||
describe('#createProxyServer using the ws-incoming passes', function () {
|
||||
it('should proxy the websockets stream', function (done) {
|
||||
var ports = { source: gen.port, proxy: gen.port };
|
||||
var proxy = httpProxy.createProxyServer({
|
||||
target: 'ws://127.0.0.1:' + ports.source,
|
||||
ws: true
|
||||
}),
|
||||
proxyServer = proxy.listen(ports.proxy),
|
||||
destiny = new ws.Server({ port: ports.source }, function () {
|
||||
var client = new ws('ws://127.0.0.1:' + ports.proxy);
|
||||
|
||||
client.on('open', function () {
|
||||
client.send('hello there');
|
||||
});
|
||||
|
||||
client.on('message', function (msg) {
|
||||
expect(msg).to.be('Hello over websockets');
|
||||
client.close();
|
||||
proxyServer._server.close();
|
||||
destiny.close();
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
destiny.on('connection', function (socket) {
|
||||
socket.on('message', function (msg) {
|
||||
expect(msg).to.be('hello there');
|
||||
socket.send('Hello over websockets');
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('#createProxyServer using the ws-incoming passes', function () {
|
||||
it('should proxy a socket.io stream', function (done) {
|
||||
var ports = { source: gen.port, proxy: gen.port };
|
||||
var proxy = httpProxy.createProxyServer({
|
||||
target: 'ws://127.0.0.1:' + ports.source,
|
||||
ws: true
|
||||
}),
|
||||
proxyServer = proxy.listen(ports.proxy),
|
||||
destiny = io.listen(ports.source, function () {
|
||||
var client = ioClient.connect('ws://127.0.0.1:' + ports.proxy);
|
||||
|
||||
client.on('connect', function () {
|
||||
client.emit('incoming', 'hello there');
|
||||
});
|
||||
|
||||
client.on('outgoing', function (data) {
|
||||
expect(data).to.be('Hello over websockets');
|
||||
proxyServer._server.close();
|
||||
destiny.server.close();
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
destiny.sockets.on('connection', function (socket) {
|
||||
socket.on('incoming', function (msg) {
|
||||
expect(msg).to.be('hello there');
|
||||
socket.emit('outgoing', 'Hello over websockets');
|
||||
});
|
||||
})
|
||||
});
|
||||
})
|
||||
});
|
||||
222
test/lib-https-proxy-test.js
Normal file
222
test/lib-https-proxy-test.js
Normal file
@ -0,0 +1,222 @@
|
||||
var httpProxy = require('../lib/http-proxy'),
|
||||
expect = require('expect.js'),
|
||||
http = require('http')
|
||||
https = require('https'),
|
||||
path = require('path'),
|
||||
fs = require('fs');
|
||||
|
||||
//
|
||||
// Expose a port number generator.
|
||||
// thanks to @3rd-Eden
|
||||
//
|
||||
var initialPort = 1024, gen = {};
|
||||
Object.defineProperty(gen, 'port', {
|
||||
get: function get() {
|
||||
return initialPort++;
|
||||
}
|
||||
});
|
||||
|
||||
describe('lib/http-proxy.js', function() {
|
||||
describe('HTTPS #createProxyServer', 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) {
|
||||
expect(req.method).to.eql('GET');
|
||||
expect(req.headers.host.split(':')[1]).to.eql(ports.proxy);
|
||||
res.writeHead(200, { 'Content-Type': 'text/plain' });
|
||||
res.end('Hello from ' + ports.source);
|
||||
});
|
||||
|
||||
source.listen(ports.source);
|
||||
|
||||
var proxy = httpProxy.createProxyServer({
|
||||
target: 'http://127.0.0.1:' + ports.source,
|
||||
ssl: {
|
||||
key: fs.readFileSync(path.join(__dirname, 'fixtures', 'agent2-key.pem')),
|
||||
cert: fs.readFileSync(path.join(__dirname, 'fixtures', 'agent2-cert.pem')),
|
||||
}
|
||||
}).listen(ports.proxy);
|
||||
|
||||
https.request({
|
||||
host: 'localhost',
|
||||
port: ports.proxy,
|
||||
path: '/',
|
||||
method: 'GET',
|
||||
rejectUnauthorized: false
|
||||
}, function(res) {
|
||||
expect(res.statusCode).to.eql(200);
|
||||
|
||||
res.on('data', function (data) {
|
||||
expect(data.toString()).to.eql('Hello from ' + ports.source);
|
||||
});
|
||||
|
||||
res.on('end', function () {
|
||||
source.close();
|
||||
proxy._server.close();
|
||||
done();
|
||||
})
|
||||
}).end();
|
||||
})
|
||||
});
|
||||
describe('HTTP to HTTPS', function () {
|
||||
it('should proxy the request en send back the response', function (done) {
|
||||
var ports = { source: gen.port, proxy: gen.port };
|
||||
var source = https.createServer({
|
||||
key: fs.readFileSync(path.join(__dirname, 'fixtures', 'agent2-key.pem')),
|
||||
cert: fs.readFileSync(path.join(__dirname, 'fixtures', 'agent2-cert.pem')),
|
||||
}, function (req, res) {
|
||||
expect(req.method).to.eql('GET');
|
||||
expect(req.headers.host.split(':')[1]).to.eql(ports.proxy);
|
||||
res.writeHead(200, { 'Content-Type': 'text/plain' });
|
||||
res.end('Hello from ' + ports.source);
|
||||
});
|
||||
|
||||
source.listen(ports.source);
|
||||
|
||||
var proxy = httpProxy.createProxyServer({
|
||||
target: 'https://127.0.0.1:' + ports.source,
|
||||
// Allow to use SSL self signed
|
||||
secure: false
|
||||
}).listen(ports.proxy);
|
||||
|
||||
http.request({
|
||||
hostname: '127.0.0.1',
|
||||
port: ports.proxy,
|
||||
method: 'GET'
|
||||
}, function(res) {
|
||||
expect(res.statusCode).to.eql(200);
|
||||
|
||||
res.on('data', function (data) {
|
||||
expect(data.toString()).to.eql('Hello from ' + ports.source);
|
||||
});
|
||||
|
||||
res.on('end', function () {
|
||||
source.close();
|
||||
proxy._server.close();
|
||||
done();
|
||||
});
|
||||
}).end();
|
||||
})
|
||||
})
|
||||
describe('HTTPS to HTTPS', function () {
|
||||
it('should proxy the request en send back the response', function (done) {
|
||||
var ports = { source: gen.port, proxy: gen.port };
|
||||
var source = https.createServer({
|
||||
key: fs.readFileSync(path.join(__dirname, 'fixtures', 'agent2-key.pem')),
|
||||
cert: fs.readFileSync(path.join(__dirname, 'fixtures', 'agent2-cert.pem')),
|
||||
}, function(req, res) {
|
||||
expect(req.method).to.eql('GET');
|
||||
expect(req.headers.host.split(':')[1]).to.eql(ports.proxy);
|
||||
res.writeHead(200, { 'Content-Type': 'text/plain' });
|
||||
res.end('Hello from ' + ports.source);
|
||||
});
|
||||
|
||||
source.listen(ports.source);
|
||||
|
||||
var proxy = httpProxy.createProxyServer({
|
||||
target: 'https://127.0.0.1:' + ports.source,
|
||||
ssl: {
|
||||
key: fs.readFileSync(path.join(__dirname, 'fixtures', 'agent2-key.pem')),
|
||||
cert: fs.readFileSync(path.join(__dirname, 'fixtures', 'agent2-cert.pem')),
|
||||
},
|
||||
secure: false
|
||||
}).listen(ports.proxy);
|
||||
|
||||
https.request({
|
||||
host: 'localhost',
|
||||
port: ports.proxy,
|
||||
path: '/',
|
||||
method: 'GET',
|
||||
rejectUnauthorized: false
|
||||
}, function(res) {
|
||||
expect(res.statusCode).to.eql(200);
|
||||
|
||||
res.on('data', function (data) {
|
||||
expect(data.toString()).to.eql('Hello from ' + ports.source);
|
||||
});
|
||||
|
||||
res.on('end', function () {
|
||||
source.close();
|
||||
proxy._server.close();
|
||||
done();
|
||||
})
|
||||
}).end();
|
||||
})
|
||||
});
|
||||
describe('HTTPS not allow SSL self signed', function () {
|
||||
it('should fail with error', function (done) {
|
||||
var ports = { source: gen.port, proxy: gen.port };
|
||||
var source = https.createServer({
|
||||
key: fs.readFileSync(path.join(__dirname, 'fixtures', 'agent2-key.pem')),
|
||||
cert: fs.readFileSync(path.join(__dirname, 'fixtures', 'agent2-cert.pem')),
|
||||
}).listen(ports.source);
|
||||
|
||||
var proxy = httpProxy.createProxyServer({
|
||||
target: 'https://127.0.0.1:' + ports.source,
|
||||
secure: true
|
||||
});
|
||||
|
||||
proxy.listen(ports.proxy);
|
||||
|
||||
proxy.on('error', function (err, req, res) {
|
||||
expect(err).to.be.an(Error);
|
||||
expect(err.toString()).to.be('Error: DEPTH_ZERO_SELF_SIGNED_CERT')
|
||||
done();
|
||||
})
|
||||
|
||||
http.request({
|
||||
hostname: '127.0.0.1',
|
||||
port: ports.proxy,
|
||||
method: 'GET'
|
||||
}).end();
|
||||
})
|
||||
})
|
||||
describe('HTTPS to HTTP using own server', 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) {
|
||||
expect(req.method).to.eql('GET');
|
||||
expect(req.headers.host.split(':')[1]).to.eql(ports.proxy);
|
||||
res.writeHead(200, { 'Content-Type': 'text/plain' });
|
||||
res.end('Hello from ' + ports.source);
|
||||
});
|
||||
|
||||
source.listen(ports.source);
|
||||
|
||||
var proxy = httpProxy.createServer({
|
||||
agent: new http.Agent({ maxSockets: 2 })
|
||||
});
|
||||
|
||||
var ownServer = https.createServer({
|
||||
key: fs.readFileSync(path.join(__dirname, 'fixtures', 'agent2-key.pem')),
|
||||
cert: fs.readFileSync(path.join(__dirname, 'fixtures', 'agent2-cert.pem')),
|
||||
}, function (req, res) {
|
||||
proxy.web(req, res, {
|
||||
target: 'http://127.0.0.1:' + ports.source
|
||||
})
|
||||
}).listen(ports.proxy);
|
||||
|
||||
https.request({
|
||||
host: 'localhost',
|
||||
port: ports.proxy,
|
||||
path: '/',
|
||||
method: 'GET',
|
||||
rejectUnauthorized: false
|
||||
}, function(res) {
|
||||
expect(res.statusCode).to.eql(200);
|
||||
|
||||
res.on('data', function (data) {
|
||||
expect(data.toString()).to.eql('Hello from ' + ports.source);
|
||||
});
|
||||
|
||||
res.on('end', function () {
|
||||
source.close();
|
||||
ownServer.close();
|
||||
done();
|
||||
})
|
||||
}).end();
|
||||
})
|
||||
})
|
||||
});
|
||||
});
|
||||
Loading…
x
Reference in New Issue
Block a user