mirror of
https://github.com/http-party/node-http-proxy.git
synced 2025-12-08 20:59:18 +00:00
This adds two tests that send payloads below and at the threshold for continuation frames. Using node 0.12.7 both tests pass. Using node 4.1.2 the test below the threshold passes but the other fails.
556 lines
16 KiB
JavaScript
556 lines
16 KiB
JavaScript
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.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.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.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.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);
|
|
|
|
proxy.on('error', function (e) {
|
|
expect(e).to.be.an(Error);
|
|
expect(e.code).to.be.eql('ECONNRESET');
|
|
});
|
|
|
|
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.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.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.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');
|
|
});
|
|
});
|
|
});
|
|
|
|
it('should emit error on proxy error', function (done) {
|
|
var ports = { source: gen.port, proxy: gen.port };
|
|
var proxy = httpProxy.createProxyServer({
|
|
// note: we don't ever listen on this port
|
|
target: 'ws://127.0.0.1:' + ports.source,
|
|
ws: true
|
|
}),
|
|
proxyServer = proxy.listen(ports.proxy),
|
|
client = new ws('ws://127.0.0.1:' + ports.proxy);
|
|
|
|
client.on('open', function () {
|
|
client.send('hello there');
|
|
});
|
|
|
|
var count = 0;
|
|
function maybe_done () {
|
|
count += 1;
|
|
if (count === 2) done();
|
|
}
|
|
|
|
client.on('error', function (err) {
|
|
expect(err).to.be.an(Error);
|
|
expect(err.code).to.be('ECONNRESET');
|
|
maybe_done();
|
|
});
|
|
|
|
proxy.on('error', function (err) {
|
|
expect(err).to.be.an(Error);
|
|
expect(err.code).to.be('ECONNREFUSED');
|
|
proxyServer.close();
|
|
maybe_done();
|
|
});
|
|
});
|
|
|
|
it('should close client socket if upstream is closed before upgrade', function (done) {
|
|
var ports = { source: gen.port, proxy: gen.port };
|
|
var server = http.createServer();
|
|
server.on('upgrade', function (req, socket, head) {
|
|
var response = [
|
|
'HTTP/1.1 404 Not Found',
|
|
'Content-type: text/html',
|
|
'',
|
|
''
|
|
];
|
|
socket.write(response.join('\r\n'));
|
|
socket.end();
|
|
});
|
|
server.listen(ports.source);
|
|
|
|
var proxy = httpProxy.createProxyServer({
|
|
// note: we don't ever listen on this port
|
|
target: 'ws://127.0.0.1:' + ports.source,
|
|
ws: true
|
|
}),
|
|
proxyServer = proxy.listen(ports.proxy),
|
|
client = new ws('ws://127.0.0.1:' + ports.proxy);
|
|
|
|
client.on('open', function () {
|
|
client.send('hello there');
|
|
});
|
|
|
|
client.on('error', function (err) {
|
|
expect(err).to.be.an(Error);
|
|
expect(err.code).to.be('ECONNRESET');
|
|
proxyServer.close();
|
|
done();
|
|
});
|
|
});
|
|
|
|
|
|
it('should proxy a socket.io stream', function (done) {
|
|
var ports = { source: gen.port, proxy: gen.port },
|
|
proxy = httpProxy.createProxyServer({
|
|
target: 'ws://127.0.0.1:' + ports.source,
|
|
ws: true
|
|
}),
|
|
proxyServer = proxy.listen(ports.proxy),
|
|
server = http.createServer(),
|
|
destiny = io.listen(server);
|
|
|
|
function startSocketIo() {
|
|
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.close();
|
|
server.close();
|
|
done();
|
|
});
|
|
}
|
|
server.listen(ports.source);
|
|
server.on('listening', startSocketIo);
|
|
|
|
destiny.sockets.on('connection', function (socket) {
|
|
socket.on('incoming', function (msg) {
|
|
expect(msg).to.be('hello there');
|
|
socket.emit('outgoing', 'Hello over websockets');
|
|
});
|
|
})
|
|
});
|
|
|
|
|
|
it('should emit open and close events when socket.io client connects and disconnects', function (done) {
|
|
var ports = { source: gen.port, proxy: gen.port };
|
|
var proxy = httpProxy.createProxyServer({
|
|
target: 'ws://127.0.0.1:' + ports.source,
|
|
ws: true
|
|
});
|
|
var proxyServer = proxy.listen(ports.proxy);
|
|
var server = http.createServer();
|
|
var destiny = io.listen(server);
|
|
|
|
function startSocketIo() {
|
|
var client = ioClient.connect('ws://127.0.0.1:' + ports.proxy);
|
|
client.on('connect', function () {
|
|
client.disconnect();
|
|
});
|
|
}
|
|
var count = 0;
|
|
|
|
proxyServer.on('open', function() {
|
|
count += 1;
|
|
|
|
});
|
|
|
|
proxyServer.on('close', function() {
|
|
proxyServer.close();
|
|
server.close();
|
|
if (count == 1) { done(); }
|
|
});
|
|
|
|
server.listen(ports.source);
|
|
server.on('listening', startSocketIo);
|
|
|
|
});
|
|
|
|
it('should pass all set-cookie headers to client', 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 key = new Buffer(Math.random().toString()).toString('base64');
|
|
|
|
var requestOptions = {
|
|
port: ports.proxy,
|
|
host: '127.0.0.1',
|
|
headers: {
|
|
'Connection': 'Upgrade',
|
|
'Upgrade': 'websocket',
|
|
'Host': 'ws://127.0.0.1',
|
|
'Sec-WebSocket-Version': 13,
|
|
'Sec-WebSocket-Key': key
|
|
}
|
|
};
|
|
|
|
var req = http.request(requestOptions);
|
|
|
|
req.on('upgrade', function (res, socket, upgradeHead) {
|
|
expect(res.headers['set-cookie'].length).to.be(2);
|
|
done();
|
|
});
|
|
|
|
req.end();
|
|
});
|
|
|
|
destiny.on('headers', function (headers) {
|
|
headers.push('Set-Cookie: test1=test1');
|
|
headers.push('Set-Cookie: test2=test2');
|
|
});
|
|
});
|
|
|
|
it('should detect a proxyReq event and modify headers', function (done) {
|
|
var ports = { source: gen.port, proxy: gen.port },
|
|
proxy,
|
|
proxyServer,
|
|
destiny;
|
|
|
|
proxy = httpProxy.createProxyServer({
|
|
target: 'ws://127.0.0.1:' + ports.source,
|
|
ws: true
|
|
});
|
|
|
|
proxy.on('proxyReqWs', function(proxyReq, req, socket, options, head) {
|
|
proxyReq.setHeader('X-Special-Proxy-Header', 'foobar');
|
|
});
|
|
|
|
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.close();
|
|
destiny.close();
|
|
done();
|
|
});
|
|
});
|
|
|
|
destiny.on('connection', function (socket) {
|
|
expect(socket.upgradeReq.headers['x-special-proxy-header']).to.eql('foobar');
|
|
|
|
socket.on('message', function (msg) {
|
|
expect(msg).to.be('hello there');
|
|
socket.send('Hello over websockets');
|
|
});
|
|
});
|
|
});
|
|
|
|
it('should forward frames with single frame payload (including on node 4.x)', function (done) {
|
|
var payload = Array(65529).join('0');
|
|
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(payload);
|
|
});
|
|
|
|
client.on('message', function (msg) {
|
|
expect(msg).to.be('Hello over websockets');
|
|
client.close();
|
|
proxyServer.close();
|
|
destiny.close();
|
|
done();
|
|
});
|
|
});
|
|
|
|
destiny.on('connection', function (socket) {
|
|
socket.on('message', function (msg) {
|
|
expect(msg).to.be(payload);
|
|
socket.send('Hello over websockets');
|
|
});
|
|
});
|
|
});
|
|
|
|
it('should forward continuation frames with big payload (including on node 4.x)', function (done) {
|
|
var payload = Array(65530).join('0');
|
|
var ports = { source: gen.port, proxy: gen.port };
|
|
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(payload);
|
|
});
|
|
|
|
client.on('message', function (msg) {
|
|
expect(msg).to.be('Hello over websockets');
|
|
client.close();
|
|
proxyServer.close();
|
|
destiny.close();
|
|
done();
|
|
});
|
|
});
|
|
|
|
destiny.on('connection', function (socket) {
|
|
socket.on('message', function (msg) {
|
|
expect(msg).to.be(payload);
|
|
socket.send('Hello over websockets');
|
|
});
|
|
});
|
|
});
|
|
});
|
|
});
|