koaproxy
v0.1.12
Published
koa proxy for the masses, reimplementation of node-http-proxy from the ground up for koa 2.
Downloads
7
Readme
proxy for the masses, reimplementation of node-http-proxy from the ground up for koa 2.
Install
npm i -S koaproxy
koaproxy
is an HTTP programmable proxying library that supports
websockets and is tailored for koa 2 (async / await). It is suitable for
implementing components such as reverse proxies and load balancers.
Roadmap
This library is currently in a state of rewrite. Some of the documentation has not yet been rewritten. Stay tuned.
- Rewrite with ES modules as es-http-proxy - Done
- Get all tests passing with ES6+ mocha - Done
- Write koaproxy
- async / await friendly promise based
- Rewrite docs
Table of Contents
- Core Concept
- Use Cases
- Options
- Listening for proxy events
- Shutdown
- Miscellaneous
- Contributing and Issues
- Tests
Core Concept
A new proxy is created by calling createProxyServer
and passing
an options
object as argument (valid properties are available here)
var httpProxy = require('reverse-proxy');
var proxy = httpProxy.createProxyServer(options); // See (†)
†Unless listen(..) is invoked on the object, this does not create a webserver. See below.
An object will be returned with four methods:
- 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) - close
[callback]
(a function that closes the inner webserver and stops listening on given port)
It is then possible to proxy requests by calling these functions
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
proxy.on('error', function(e) {
...
});
or using the callback API
proxy.web(req, res, { target: 'http://mytarget.com:8080' }, function(e) { ... });
When a request is proxied it follows two different pipelines (available here)
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.
Use Cases
Setup a basic stand-alone proxy server
var http = require('http'),
httpProxy = require('reverse-proxy');
//
// Create your proxy server and set the target in the options.
//
httpProxy.createProxyServer({target:'http://localhost:9000'}).listen(8000); // See (†)
//
// 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);
†Invoking listen(..) triggers the creation of a web server. Otherwise, just the proxy instance is created.
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.
var http = require('http'),
httpProxy = require('reverse-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 = 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 proxy request header re-writing
This example shows how you can proxy a request using your own HTTP server that modifies the outgoing proxy request by adding a special header.
var http = require('http'),
httpProxy = require('reverse-proxy');
//
// Create a proxy server with custom application logic
//
var proxy = httpProxy.createProxyServer({});
// To modify the proxy connection before data is sent, you can listen
// for the 'proxyReq' event. When the event is fired, you will receive
// the following arguments:
// (http.ClientRequest proxyReq, http.IncomingMessage req,
// http.ServerResponse res, Object options). This mechanism is useful when
// you need to modify the proxy request before the proxy connection
// is made to the target.
//
proxy.on('proxyReq', function(proxyReq, req, res, options) {
proxyReq.setHeader('X-Special-Proxy-Header', 'foobar');
});
var server = http.createServer(function(req, res) {
// You can define here your custom logic to handle the request
// and then proxy the request.
proxy.web(req, res, {
target: 'http://127.0.0.1:5060'
});
});
console.log("listening on port 5050")
server.listen(5050);
Modify a response from a proxied server
Sometimes when you have received a HTML/XML document from the server of origin you would like to modify it before forwarding it on.
Harmon allows you to do this in a streaming style so as to keep the pressure on the proxy to a minimum.
Setup a stand-alone proxy server with latency
var http = require('http'),
httpProxy = require('reverse-proxy');
//
// Create a proxy server with latency
//
var proxy = httpProxy.createProxyServer();
//
// Create your server that makes an operation that waits a while
// and then proxies the request
//
http.createServer(function (req, res) {
// This simulates an operation that takes 500ms to 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);
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
//
// 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
//
// 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.
//
// 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.
//
// 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);
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 and http agent objects)
- 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, if you want to verify the SSL Certs
- toProxy: true/false, passes the absolute URL as the
path
(useful for proxying to proxies) - prependPath: true/false, Default: true - specify whether you want to prepend the target's path to the proxy path
- ignorePath: true/false, Default: false - specify whether you want to ignore the proxy path of the incoming request (note: you will have to append / manually if required).
- localAddress: Local interface string to bind for outgoing connections
- changeOrigin: true/false, Default: false - changes the origin of the host header to the target URL
- auth: Basic authentication i.e. 'user:password' to compute an Authorization header.
- hostRewrite: rewrites the location hostname on (301/302/307/308) redirects.
- autoRewrite: rewrites the location host/port on (301/302/307/308) redirects based on requested host/port. Default: false.
- protocolRewrite: rewrites the location protocol on (301/302/307/308) redirects to 'http' or 'https'. Default: null.
- headers: object with extra headers to be added to target requests.
NOTE:
options.ws
and options.ssl
are optional.
options.target
and options.forward
cannot both be missing
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
Listening for proxy events
error
: The error event is emitted if the request to the target fail. We do not do any error handling of messages passed between client and proxy, and messages passed between proxy and target, so it is recommended that you listen on errors and handle them.proxyReq
: This event is emitted before the data is sent. It gives you a chance to alter the proxyReq request object. Applies to "web" connectionsproxyReqWs
: This event is emitted before the data is sent. It gives you a chance to alter the proxyReq request object. Applies to "websocket" connectionsproxyRes
: This event is emitted if the request to the target got a response.open
: This event is emitted once the proxy websocket was created and piped into the target websocket.close
: This event is emitted once the proxy websocket was closed.- (DEPRECATED)
proxySocket
: Deprecated in favor ofopen
.
var httpProxy = require('reverse-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 (proxyRes, req, res) {
console.log('RAW Response from the target', JSON.stringify(proxyRes.headers, true, 2));
});
//
// Listen for the `open` event on `proxy`.
//
proxy.on('open', function (proxySocket) {
// listen for messages coming FROM the target here
proxySocket.on('data', hybiParseAndLogMessage);
});
//
// Listen for the `close` event on `proxy`.
//
proxy.on('close', function (res, socket, head) {
// view disconnected websocket connections
console.log('Client disconnected');
});
Shutdown
- When testing or running server within another program it may be necessary to close the proxy.
- This will stop the proxy from accepting new connections.
var proxy = new httpProxy.createProxyServer({
target: {
host: 'localhost',
port: 1337
}
});
proxy.close();
Miscellaneous
ProxyTable API
A proxy table API is available through this add-on module, which lets you define a set of rules to translate matching routes to target routes that the reverse proxy will talk to.
Test
$ npm test
Logo
Logo created by Diego Pasquali
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)
TEST
Unit tests output for current release:
TOC
- lib/es-http-proxy/common.js
- lib/es-http-proxy/passes/web.js
- #createProxyServer.web() using own http server
- lib/es-http-proxy/passes/web-outgoing.js
- lib/es-http-proxy/passes/ws-incoming.js
- ProxyServer
- lib/es-http-proxy.js
- #createProxyServer
- #createProxyServer with forward options and using web-incoming passes
- #createProxyServer using the web-incoming passes
- #createProxyServer() method with error response
- #createProxyServer setting the correct timeout value
- #createProxyServer using the ws-incoming passes
- HTTPS #createProxyServer
- es-http-proxy examples
lib/es-http-proxy/common.js
#setupOutgoing
should exist.
return should.exist(setupOutgoing);
should be a function.
return setupOutgoing.should.be.a('function');
should not override agentless upgrade header.
var outgoing = {};
common.setupOutgoing(outgoing, { agent: undefined,
target: { host: 'hey',
hostname: 'how',
socketPath: 'are',
port: 'you' },
headers: { 'connection': 'upgrade' } }, { method: 'i',
url: 'am',
headers: { 'pro': 'xy', 'overwritten': false } });
(0, _chai.expect)(outgoing.headers.connection).to.eql('upgrade');
should not override agentless connection: contains upgrade.
var outgoing = {};
common.setupOutgoing(outgoing, { agent: undefined,
target: { host: 'hey',
hostname: 'how',
socketPath: 'are',
port: 'you' },
headers: { 'connection': 'keep-alive, upgrade' } }, { method: 'i',
url: 'am',
headers: { 'pro': 'xy', 'overwritten': false } });
(0, _chai.expect)(outgoing.headers.connection).to.eql('keep-alive, upgrade');
should override agentless connection: contains improper upgrade.
// sanity check on upgrade regex
var outgoing = {};
common.setupOutgoing(outgoing, { agent: undefined,
target: { host: 'hey',
hostname: 'how',
socketPath: 'are',
port: 'you' },
headers: { 'connection': 'keep-alive, not upgrade' } }, { method: 'i',
url: 'am',
headers: { 'pro': 'xy', 'overwritten': false } });
(0, _chai.expect)(outgoing.headers.connection).to.eql('close');
should override agentless non-upgrade header to close.
var outgoing = {};
common.setupOutgoing(outgoing, { agent: undefined,
target: { host: 'hey',
hostname: 'how',
socketPath: 'are',
port: 'you' },
headers: { 'connection': 'xyz' } }, { method: 'i',
url: 'am',
headers: { 'pro': 'xy', 'overwritten': false } });
(0, _chai.expect)(outgoing.headers.connection).to.eql('close');
should set the agent to false if none is given.
var outgoing = {};
common.setupOutgoing(outgoing, { target: 'http://localhost' }, { url: '/' });
(0, _chai.expect)(outgoing.agent).to.eql(false);
set the port according to the protocol.
var outgoing = {};
common.setupOutgoing(outgoing, { agent: '?',
target: { host: 'how',
hostname: 'are',
socketPath: 'you',
protocol: 'https:' } }, { method: 'i',
url: 'am',
headers: { pro: 'xy' } });
(0, _chai.expect)(outgoing.host).to.eql('how');
(0, _chai.expect)(outgoing.hostname).to.eql('are');
(0, _chai.expect)(outgoing.socketPath).to.eql('you');
(0, _chai.expect)(outgoing.agent).to.eql('?');
(0, _chai.expect)(outgoing.method).to.eql('i');
(0, _chai.expect)(outgoing.path).to.eql('am');
(0, _chai.expect)(outgoing.headers.pro).to.eql('xy');
(0, _chai.expect)(outgoing.port).to.eql(443);
should keep the original target path in the outgoing path.
var outgoing = {};
common.setupOutgoing(outgoing, { target: { path: 'some-path' } }, { url: 'am' });
(0, _chai.expect)(outgoing.path).to.eql('some-path/am');
should keep the original forward path in the outgoing path.
var outgoing = {};
common.setupOutgoing(outgoing, { target: {},
forward: { path: 'some-path' } }, { url: 'am' }, 'forward');
(0, _chai.expect)(outgoing.path).to.eql('some-path/am');
should properly detect https/wss protocol without the colon.
var outgoing = {};
common.setupOutgoing(outgoing, { target: { protocol: 'https',
host: 'whatever.com' } }, { url: '/' });
(0, _chai.expect)(outgoing.port).to.eql(443);
should not prepend the target path to the outgoing path with prependPath = false.
var outgoing = {};
common.setupOutgoing(outgoing, { target: { path: 'hellothere' },
prependPath: false }, { url: 'hi' });
(0, _chai.expect)(outgoing.path).to.eql('hi');
should properly join paths.
var outgoing = {};
common.setupOutgoing(outgoing, { target: { path: '/forward' } }, { url: '/static/path' });
(0, _chai.expect)(outgoing.path).to.eql('/forward/static/path');
should not modify the query string.
var outgoing = {};
common.setupOutgoing(outgoing, { target: { path: '/forward' } }, { url: '/?foo=bar//&target=http://foobar.com/?a=1%26b=2&other=2' });
(0, _chai.expect)(outgoing.path).to.eql('/forward/?foo=bar//&target=http://foobar.com/?a=1%26b=2&other=2');
should correctly format the toProxy URL.
var outgoing = {};
var google = 'https://google.com';
common.setupOutgoing(outgoing, { target: _url2.default.parse('http://sometarget.com:80'),
toProxy: true }, { url: google });
(0, _chai.expect)(outgoing.path).to.eql('/' + google);
should not replace : to :\ when no https word before.
var outgoing = {};
var google = 'https://google.com:/join/join.js';
common.setupOutgoing(outgoing, { target: _url2.default.parse('http://sometarget.com:80'),
toProxy: true }, { url: google });
(0, _chai.expect)(outgoing.path).to.eql('/' + google);
should not replace : to :\ when no http word before.
var outgoing = {};
var google = 'http://google.com:/join/join.js';
common.setupOutgoing(outgoing, { target: _url2.default.parse('http://sometarget.com:80'),
toProxy: true }, { url: google });
(0, _chai.expect)(outgoing.path).to.eql('/' + google);
should pass through https client parameters.
var outgoing = {};
common.setupOutgoing(outgoing, { agent: '?',
target: { host: 'how',
hostname: 'are',
socketPath: 'you',
protocol: 'https:',
pfx: 'my-pfx',
key: 'my-key',
passphrase: 'my-passphrase',
cert: 'my-cert',
ca: 'my-ca',
ciphers: 'my-ciphers',
secureProtocol: 'my-secure-protocol' } }, { method: 'i',
url: 'am' });
(0, _chai.expect)(outgoing.pfx).eql('my-pfx');
(0, _chai.expect)(outgoing.key).eql('my-key');
(0, _chai.expect)(outgoing.passphrase).eql('my-passphrase');
(0, _chai.expect)(outgoing.cert).eql('my-cert');
(0, _chai.expect)(outgoing.ca).eql('my-ca');
(0, _chai.expect)(outgoing.ciphers).eql('my-ciphers');
(0, _chai.expect)(outgoing.secureProtocol).eql('my-secure-protocol');
outgoing
should exist.
return should.exist(outgoing);
should be an object.
return outgoing.should.be.an('object');
#host
should exist.
return should.exist(prop);
should be a string.
return prop.should.be.a(propType);
should equal hey.
return prop.should.eql(propValue);
#hostname
should exist.
return should.exist(prop);
should be a string.
return prop.should.be.a(propType);
should equal how.
return prop.should.eql(propValue);
#socketPath
should exist.
return should.exist(prop);
should be a string.
return prop.should.be.a(propType);
should equal are.
return prop.should.eql(propValue);
#port
should exist.
return should.exist(prop);
should be a string.
return prop.should.be.a(propType);
should equal you.
return prop.should.eql(propValue);
#agent
should exist.
return should.exist(prop);
should be a string.
return prop.should.be.a(propType);
should equal ?.
return prop.should.eql(propValue);
#method
should exist.
return should.exist(prop);
should be a string.
return prop.should.be.a(propType);
should equal i.
return prop.should.eql(propValue);
#path
should exist.
return should.exist(prop);
should be a string.
return prop.should.be.a(propType);
should equal am.
return prop.should.eql(propValue);
#localAddress
should exist.
return should.exist(prop);
should be a string.
return prop.should.be.a(propType);
should equal local.address.
return prop.should.eql(propValue);
#auth
should exist.
return should.exist(prop);
should be a string.
return prop.should.be.a(propType);
should equal username:pass.
return prop.should.eql(propValue);
#pro
should exist.
return should.exist(prop);
should be a string.
return prop.should.be.a(propType);
should equal xy.
return prop.should.eql(propValue);
#fizz
should exist.
return should.exist(prop);
should be a string.
return prop.should.be.a(propType);
should equal bang.
return prop.should.eql(propValue);
#overwritten
should exist.
return should.exist(prop);
should be a boolean.
return prop.should.be.a(propType);
should equal true.
return prop.should.eql(propValue);
when using ignorePath
should ignore the path of the req.url
passed in but use the target path.
var outgoing = {};
var myEndpoint = 'https://whatever.com/some/crazy/path/whoooo';
common.setupOutgoing(outgoing, { target: _url2.default.parse(myEndpoint),
ignorePath: true }, { url: '/more/crazy/pathness' });
(0, _chai.expect)(outgoing.path).to.eql('/some/crazy/path/whoooo');
and prependPath: false, it should ignore path of target and incoming request.
var outgoing = {};
var myEndpoint = 'https://whatever.com/some/crazy/path/whoooo';
common.setupOutgoing(outgoing, { target: _url2.default.parse(myEndpoint),
ignorePath: true,
prependPath: false }, { url: '/more/crazy/pathness' });
(0, _chai.expect)(outgoing.path).to.eql('');
when using changeOrigin
should correctly set the port to the host when it is a non-standard port using url.parse.
var outgoing = {};
var myEndpoint = 'https://myCouch.com:6984';
common.setupOutgoing(outgoing, { target: _url2.default.parse(myEndpoint),
changeOrigin: true }, { url: '/' });
(0, _chai.expect)(outgoing.headers.host).to.eql('mycouch.com:6984');
should correctly set the port to the host when it is a non-standard port when setting host and port manually (which ignores port).
var outgoing = {};
common.setupOutgoing(outgoing, { target: { protocol: 'https:',
host: 'mycouch.com',
port: 6984 },
changeOrigin: true }, { url: '/' });
(0, _chai.expect)(outgoing.headers.host).to.eql('mycouch.com:6984');
should not pass null as last arg to #urlJoin
should exist.
return should.exist(outgoing);
should have path.
return outgoing.should.be.an('object').that.has.property('path').that.is.a('string');
should be empty.
return outgoing.path.should.eql('');
#setupSocket
should setup a socket
should still have socketConfig.
return should.exist(socketConfig);
should have timeout.
return socketConfig.should.be.an('object').that.has.property('timeout').that.is.a('number');
should have nodelay.
return socketConfig.should.be.an('object').that.has.property('nodelay').that.is.a('boolean');
should have keepalive.
return socketConfig.should.be.an('object').that.has.property('keepalive').that.is.a('boolean');
should have correct timeout value.
return socketConfig.timeout.should.eql(0);
should have correct nodelay value.
return socketConfig.nodelay.should.eql(true);
should have correct keepalive value.
return socketConfig.keepalive.should.eql(true);
lib/es-http-proxy/passes/web.js
#deleteLength
should change content-length
for DELETE requests.
var stubRequest = {
method: 'DELETE',
headers: {}
};
webPasses.deleteLength(stubRequest, {}, {});
(0, _chai.expect)(stubRequest.headers['content-length']).to.eql('0');
should change content-length
for OPTIONS requests.
var stubRequest = {
method: 'OPTIONS',
headers: {}
};
webPasses.deleteLength(stubRequest, {}, {});
(0, _chai.expect)(stubRequest.headers['content-length']).to.eql('0');
should remove transfer-encoding
from empty DELETE requests.
var stubRequest = {
method: 'DELETE',
headers: {
'transfer-encoding': 'chunked'
}
};
webPasses.deleteLength(stubRequest, {}, {});
(0, _chai.expect)(stubRequest.headers['content-length']).to.eql('0');
(0, _chai.expect)(stubRequest.headers).to.not.have.key('transfer-encoding');
#timeout
should set timeout on the socket.
var done = false,
stubRequest = {
socket: {
setTimeout: function setTimeout(value) {
done = value;
}
}
};
webPasses.timeout(stubRequest, {}, { timeout: 5000 });
(0, _chai.expect)(done).to.eql(5000);
#XHeaders
set the correct x-forwarded-* headers.
webPasses.XHeaders(stubRequest, {}, { xfwd: true });
(0, _chai.expect)(stubRequest.headers['x-forwarded-for']).to.eql('192.168.1.2');
(0, _chai.expect)(stubRequest.headers['x-forwarded-port']).to.eql('8080');
(0, _chai.expect)(stubRequest.headers['x-forwarded-proto']).to.eql('http');
#createProxyServer.web() using own http server
lib/es-http-proxy/passes/web-outgoing.js
#setRedirectHostRewrite
rewrites location host with hostRewrite
on 301.
this.proxyRes.statusCode = code;
httpProxy.setRedirectHostRewrite(this.req, {}, this.proxyRes, this.options);
(0, _chai.expect)(this.proxyRes.headers.location).to.eql('http://ext-manual.com/');
on 302.
this.proxyRes.statusCode = code;
httpProxy.setRedirectHostRewrite(this.req, {}, this.proxyRes, this.options);
(0, _chai.expect)(this.proxyRes.headers.location).to.eql('http://ext-manual.com/');
on 307.
this.proxyRes.statusCode = code;
httpProxy.setRedirectHostRewrite(this.req, {}, this.proxyRes, this.options);
(0, _chai.expect)(this.proxyRes.headers.location).to.eql('http://ext-manual.com/');
on 308.
this.proxyRes.statusCode = code;
httpProxy.setRedirectHostRewrite(this.req, {}, this.proxyRes, this.options);
(0, _chai.expect)(this.proxyRes.headers.location).to.eql('http://ext-manual.com/');
not on 200.
this.proxyRes.statusCode = 200;
httpProxy.setRedirectHostRewrite(this.req, {}, this.proxyRes, this.options);
(0, _chai.expect)(this.proxyRes.headers.location).to.eql('http://backend.com/');
not when hostRewrite is unset.
delete this.options.hostRewrite;
httpProxy.setRedirectHostRewrite(this.req, {}, this.proxyRes, this.options);
(0, _chai.expect)(this.proxyRes.headers.location).to.eql('http://backend.com/');
takes precedence over autoRewrite.
this.options.autoRewrite = true;
httpProxy.setRedirectHostRewrite(this.req, {}, this.proxyRes, this.options);
(0, _chai.expect)(this.proxyRes.headers.location).to.eql('http://ext-manual.com/');
not when the redirected location does not match target host.
this.proxyRes.statusCode = 302;
this.proxyRes.headers.location = 'http://some-other/';
httpProxy.setRedirectHostRewrite(this.req, {}, this.proxyRes, this.options);
(0, _chai.expect)(this.proxyRes.headers.location).to.eql('http://some-other/');
not when the redirected location does not match target port.
this.proxyRes.statusCode = 302;
this.proxyRes.headers.location = 'http://backend.com:8080/';
httpProxy.setRedirectHostRewrite(this.req, {}, this.proxyRes, this.options);
(0, _chai.expect)(this.proxyRes.headers.location).to.eql('http://backend.com:8080/');
rewrites location host with autoRewrite
on 301.
this.proxyRes.statusCode = code;
httpProxy.setRedirectHostRewrite(this.req, {}, this.proxyRes, this.options);
(0, _chai.expect)(this.proxyRes.headers.location).to.eql('http://ext-auto.com/');
on 302.
this.proxyRes.statusCode = code;
httpProxy.setRedirectHostRewrite(this.req, {}, this.proxyRes, this.options);
(0, _chai.expect)(this.proxyRes.headers.location).to.eql('http://ext-auto.com/');
on 307.
this.proxyRes.statusCode = code;
httpProxy.setRedirectHostRewrite(this.req, {}, this.proxyRes, this.options);
(0, _chai.expect)(this.proxyRes.headers.location).to.eql('http://ext-auto.com/');
on 308.
this.proxyRes.statusCode = code;
httpProxy.setRedirectHostRewrite(this.req, {}, this.proxyRes, this.options);
(0, _chai.expect)(this.proxyRes.headers.location).to.eql('http://ext-auto.com/');
not on 200.
this.proxyRes.statusCode = 200;
httpProxy.setRedirectHostRewrite(this.req, {}, this.proxyRes, this.options);
(0, _chai.expect)(this.proxyRes.headers.location).to.eql('http://backend.com/');
not when autoRewrite is unset.
delete this.options.autoRewrite;
httpProxy.setRedirectHostRewrite(this.req, {}, this.proxyRes, this.options);
(0, _chai.expect)(this.proxyRes.headers.location).to.eql('http://backend.com/');
not when the redirected location does not match target host.
this.proxyRes.statusCode = 302;
this.proxyRes.headers.location = 'http://some-other/';
httpProxy.setRedirectHostRewrite(this.req, {}, this.proxyRes, this.options);
(0, _chai.expect)(this.proxyRes.headers.location).to.eql('http://some-other/');
not when the redirected location does not match target port.
this.proxyRes.statusCode = 302;
this.proxyRes.headers.location = 'http://backend.com:8080/';
httpProxy.setRedirectHostRewrite(this.req, {}, this.proxyRes, this.options);
(0, _chai.expect)(this.proxyRes.headers.location).to.eql('http://backend.com:8080/');
rewrites location protocol with protocolRewrite
on 301.
this.proxyRes.statusCode = code;
httpProxy.setRedirectHostRewrite(this.req, {}, this.proxyRes, this.options);
(0, _chai.expect)(this.proxyRes.headers.location).to.eql('https://backend.com/');
on 302.
this.proxyRes.statusCode = code;
httpProxy.setRedirectHostRewrite(this.req, {}, this.proxyRes, this.options);
(0, _chai.expect)(this.proxyRes.headers.location).to.eql('https://backend.com/');
on 307.
this.proxyRes.statusCode = code;
httpProxy.setRedirectHostRewrite(this.req, {}, this.proxyRes, this.options);
(0, _chai.expect)(this.proxyRes.headers.location).to.eql('https://backend.com/');
on 308.
this.proxyRes.statusCode = code;
httpProxy.setRedirectHostRewrite(this.req, {}, this.proxyRes, this.options);
(0, _chai.expect)(this.proxyRes.headers.location).to.eql('https://backend.com/');
not on 200.
this.proxyRes.statusCode = 200;
httpProxy.setRedirectHostRewrite(this.req, {}, this.proxyRes, this.options);
(0, _chai.expect)(this.proxyRes.headers.location).to.eql('http://backend.com/');
not when protocolRewrite is unset.
delete this.options.protocolRewrite;
httpProxy.setRedirectHostRewrite(this.req, {}, this.proxyRes, this.options);
(0, _chai.expect)(this.proxyRes.headers.location).to.eql('http://backend.com/');
works together with hostRewrite.
this.options.hostRewrite = 'ext-manual.com';
httpProxy.setRedirectHostRewrite(this.req, {}, this.proxyRes, this.options);
(0, _chai.expect)(this.proxyRes.headers.location).to.eql('https://ext-manual.com/');
works together with autoRewrite.
this.options.autoRewrite = true;
httpProxy.setRedirectHostRewrite(this.req, {}, this.proxyRes, this.options);
(0, _chai.expect)(this.proxyRes.headers.location).to.eql('https://ext-auto.com/');
#setConnection
set the right connection with 1.0 - close
.
var proxyRes = { headers: {} };
httpProxy.setConnection({ httpVersion: '1.0', headers: { connection: null } }, {}, proxyRes);
(0, _chai.expect)(proxyRes.headers.connection).to.eql('close');
set the right connection with 1.0 - req.connection.
var proxyRes = { headers: {} };
httpProxy.setConnection({ httpVersion: '1.0', headers: { connection: 'hey' } }, {}, proxyRes);
(0, _chai.expect)(proxyRes.headers.connection).to.eql('hey');
set the right connection - req.connection.
var proxyRes = { headers: {} };
httpProxy.setConnection({ httpVersion: null, headers: { connection: 'hola' } }, {}, proxyRes);
(0, _chai.expect)(proxyRes.headers.connection).to.eql('hola');
set the right connection - keep-alive
.
var proxyRes = { headers: {} };
httpProxy.setConnection({ httpVersion: null, headers: { connection: null } }, {}, proxyRes);
(0, _chai.expect)(proxyRes.headers.connection).to.eql('keep-alive');
#writeStatusCode
should write status code.
var res = { writeHead: function writeHead(n) {
(0, _chai.expect)(n).to.eql(200);
} };
httpProxy.writeStatusCode({}, res, { statusCode: 200 });
lib/es-http-proxy/passes/ws-incoming.js
#checkMethodAndHeader
should drop non-GET connections.
var destroyCalled = false,
stubRequest = { method: 'DELETE', headers: {} },
stubSocket = { destroy: function destroy() {
// Simulate Socket.destroy() method when call
destroyCalled = true;
} };
var returnValue = httpProxy.checkMethodAndHeader(stubRequest, stubSocket);
(0, _chai.expect)(returnValue).to.eql(true);
(0, _chai.expect)(destroyCalled).to.eql(true);
should drop connections when no upgrade header.
var destroyCalled = false,
stubRequest = { method: 'GET',
headers: {} },
stubSocket = { destroy: function destroy() {
// Simulate Socket.destroy() method when call
destroyCalled = true;
} };
var returnValue = httpProxy.checkMethodAndHeader(stubRequest, stubSocket);
(0, _chai.expect)(returnValue).to.eql(true);
(0, _chai.expect)(destroyCalled).to.eql(true);
should drop connections when upgrade header is different of websocket
.
var destroyCalled = false,
stubRequest = { method: 'GET',
headers: { upgrade: 'anotherprotocol' } },
stubSocket = { destroy: function destroy() {
// Simulate Socket.destroy() method when call
destroyCalled = true;
} };
var returnValue = httpProxy.checkMethodAndHeader(stubRequest, stubSocket);
(0, _chai.expect)(returnValue).to.eql(true);
(0, _chai.expect)(destroyCalled).to.eql(true);
should return nothing when all is ok.
var destroyCalled = false,
stubRequest = { method: 'GET',
headers: { upgrade: 'websocket' } },
stubSocket = { destroy: function destroy() {
// Simulate Socket.destroy() method when call
destroyCalled = true;
} };
var returnValue = httpProxy.checkMethodAndHeader(stubRequest, stubSocket);
(0, _chai.expect)(returnValue).to.eql(undefined);
(0, _chai.expect)(destroyCalled).to.eql(false);
#XHeaders
return if no forward request.
var returnValue = httpProxy.XHeaders({}, {}, {});
(0, _chai.expect)(returnValue).to.be.undefined;
set the correct x-forwarded-* headers from req.connection.
var stubRequest = { connection: { remoteAddress: '192.168.1.2',
remotePort: '8080' },
headers: { host: '192.168.1.2:8080' } };
httpProxy.XHeaders(stubRequest, {}, { xfwd: true });
(0, _chai.expect)(stubRequest.headers['x-forwarded-for']).to.eql('192.168.1.2');
(0, _chai.expect)(stubRequest.headers['x-forwarded-port']).to.eql('8080');
(0, _chai.expect)(stubRequest.headers['x-forwarded-proto']).to.eql('ws');
set the correct x-forwarded-* headers from req.socket.
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 });
(0, _chai.expect)(stubRequest.headers['x-forwarded-for']).to.eql('192.168.1.3');
(0, _chai.expect)(stubRequest.headers['x-forwarded-port']).to.eql('8181');
(0, _chai.expect)(stubRequest.headers['x-forwarded-proto']).to.eql('wss');
ProxyServer
should exist.
return should.exist(_ProxyServer2.default);
should be a function.
return _ProxyServer2.default.should.be.a('function');
should create instanceof EE3.
return new _ProxyServer2.default().should.be.instanceof(_eventemitter2.default);
lib/es-http-proxy.js
#createProxyServer
should return an object otherwise
should exist.
return should.exist(obj);
should be an object.
return obj.should.be.an('object');
should have web function.
return obj.should.have.property('web').that.is.a('function');
should have ws function.
return obj.should.have.property('ws').that.is.a('function');
should have listen function.
return obj.should.have.property('listen').that.is.a('function');
#createProxyServer with forward options and using web-incoming passes
should pipe the request using web-incoming#stream method.
var ports = { source: gen.port, proxy: gen.port };
var proxy = (0, _esHttpProxy.createProxyServer)({
forward: 'http://127.0.0.1:' + ports.source
}).listen(ports.proxy);
var source = _http2.default.createServer(function (req, res) {
/*
should.exist(req)
should.exist(req.method)
*/
req.method.should.eql('GET');
/*
should.exist(req.headers)
should.exist(req.headers.host)
*/
req.headers.host.split(':')[1].should.eql(ports.proxy.toString());
source.close();
proxy.close();
done();
});
source.listen(ports.source);
_http2.default.request('http://127.0.0.1:' + ports.proxy, function () {}).end();
#createProxyServer using the web-incoming passes
should proxy sse.
var ports = { source: gen.port, proxy: gen.port },
proxy = (0, _esHttpProxy.createProxyServer)({
target: 'http://localhost:' + ports.source
}),
proxyServer = proxy.listen(ports.proxy),
source = _http2.default.createServer(),
sse = new _sse2.default(source, { path: '/' });
sse.on('connection', function (client) {
client.send('Hello over SSE');
client.close();
});
source.listen(ports.source);
var options = { hostname: 'localhost', port: ports.proxy };
var req = _http2.default.request(options, function (res) {
var streamData = '';
res.on('data', function (chunk) {
streamData += chunk.toString('utf8');
});
res.on('end', function (chunk) {
//should.exist(streamData)
streamData.should.eql(':ok\n\ndata: Hello over SSE\n\n');
source.close();
proxy.close();
done();
});
}).end();
should make the request on pipe and finish it.
var ports = { source: gen.port, proxy: gen.port };
var proxy = (0, _esHttpProxy.createProxyServer)({
target: 'http://127.0.0.1:' + ports.source
}).listen(ports.proxy);
var source = _http2.default.createServer(function (req, res) {
should.exist(req);
req.should.be.an('object').that.has.property('method');
req.method.should.eql('POST');
should.exist(req.headers);
should.exist(req.headers['x-forwarded-for']);
req.headers['x-forwarded-for'].should.eql('127.0.0.1');
should.exist(req.headers.host);
req.headers.host.split(':')[1].should.eql(ports.proxy.toString());
source.close();
proxy.close();
done();
});
source.listen(ports.source);
_http2.default.request({ hostname: '127.0.0.1',
port: ports.proxy,
method: 'POST',
headers: { 'x-forwarded-for': '127.0.0.1' }
}, function () {}).end();
#createProxyServer using the web-incoming passes
should make the request, handle response and finish it.
var ports = { source: gen.port, proxy: gen.port };
var proxy = (0, _esHttpProxy.createProxyServer)({
target: 'http://127.0.0.1:' + ports.source
}).listen(ports.proxy);
var source = _http2.default.createServer(function (req, res) {
req.method.should.eql('GET');
req.headers.host.split(':')[1].should.eql(ports.proxy.toString());
res.writeHead(200, { 'Content-Type': 'text/plain' });
res.end('Hello from ' + source.address().port);
});
source.listen(ports.source);
_http2.default.request({ hostname: '127.0.0.1',
port: ports.proxy,
method: 'GET'
}, function (res) {
res.statusCode.should.eql(200);
res.on('data', function (data) {
data.toString().should.eql('Hello from ' + ports.source);
});
res.on('end', function () {
source.close();
proxy.close();
done();
});
}).end();
#createProxyServer() method with error response
should make the request and emit the error event.
var ports = { source: gen.port, proxy: gen.port };
var proxy = (0, _esHttpProxy.createProxyServer)({
target: 'http://127.0.0.1:' + ports.source
});
proxy.on('error', function (err) {
(0, _chai.expect)(err).to.be.an.instanceof(Error);
(0, _chai.expect)(err.code).to.eql('ECONNREFUSED');
proxy.close();
done();
});
proxy.listen(ports.proxy);
_http2.default.request({ hostname: '127.0.0.1',
port: ports.proxy,
method: 'GET'
}, function () {}).end();
#createProxyServer setting the correct timeout value
should hang up the socket at the timeout.
this.timeout(30);
var ports = { source: gen.port, proxy: gen.port };
var proxy = (0, _esHttpProxy.createProxyServer)({ target: 'http://127.0.0.1:' + ports.source,
timeout: 3
}).listen(ports.proxy);
proxy.on('error', function (e) {
should.exist(e);
e.should.be.instanceof(Error);
should.exist(e.code);
e.code.should.eql('ECONNRESET');
});
var source = _http2.default.createServer(function (req, res) {
setTimeout(function () {
res.end('At this point the socket should be closed');
}, 5);
});
source.listen(ports.source);
var testReq = _http2.default.request({ hostname: '127.0.0.1',
port: ports.proxy,
method: 'GET'
}, function () {});
testReq.on('error', function (e) {
(0, _chai.expect)(e).to.be.instanceof(Error);
(0, _chai.expect)(e.code).to.eql('ECONNRESET');
proxy.close();
source.close();
done();
});
testReq.end();
#createProxyServer using the ws-incoming passes
should proxy the websockets stream.
var ports = { source: gen.port, proxy: gen.port };
var proxy = (0, _esHttpProxy.createProxyServer)({ target: 'ws://127.0.0.1:' + ports.source,
ws: true
});
var proxyServer = proxy.listen(ports.proxy);
var destiny = new _ws2.default.Server({ port: ports.source }, function () {
var client = new _ws2.default('ws://127.0.0.1:' + ports.proxy);
client.on('open', function () {
client.send('hello there');
});
client.on('message', function (msg) {
(0, _chai.expect)(msg).to.eql('Hello over websockets');
client.close();
proxyServer.close();
destiny.close();
done();
});
});
destiny.on('connection', function (socket) {
socket.on('message', function (msg) {
(0, _chai.expect)(msg).to.eql('hello there');
socket.send('Hello over websockets');
});
});
should emit error on proxy error.
var ports = { source: gen.port, proxy: gen.port };
var proxy = (0, _esHttpProxy.createProxyServer)({ target: 'ws://127.0.0.1:' + ports.source,
ws: true
});
var proxyServer = proxy.listen(ports.proxy);
var client = new _ws2.default('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) {
(0, _chai.expect)(err).to.be.instanceof(Error);
(0, _chai.expect)(err.code).to.eql('ECONNRESET');
maybe_done();
});
proxy.on('error', function (err) {
(0, _chai.expect)(err).to.be.instanceof(Error);
(0, _chai.expect)(err.code).to.eql('ECONNREFUSED');
proxyServer.close();
maybe_done();
});
should close client socket if upstream is closed before upgrade.
var ports = { source: gen.port, proxy: gen.port };
var server = _http2.default.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 = (0, _esHttpProxy.createProxyServer)({ target: 'ws://127.0.0.1:' + ports.source,
ws: true
});
var proxyServer = proxy.listen(ports.proxy);
var client = new _ws2.default('ws://127.0.0.1:' + ports.proxy);
client.on('open', function () {
client.send('hello there');
});
client.on('error', function (err) {
(0, _chai.expect)(err).to.be.instanceof(Error);
(0, _chai.expect)(err.code).to.eql('ECONNRESET');
proxyServer.close();
done();
});
should proxy a socket.io stream.
var ports = { source: gen.port, proxy: gen.port };
var proxy = (0, _esHttpProxy.createProxyServer)({ target: 'ws://127.0.0.1:' + ports.source,
ws: true
});
var proxyServer = proxy.listen(ports.proxy);
var server = _http2.default.createServer();
var destiny = _socket2.default.listen(server);
function startSocketIo() {
var client = _socket4.default.connect('ws://127.0.0.1:' + ports.proxy);
client.on('connect', function () {
client.emit('incoming', 'hello there');
});
client.on('outgoing', function (data) {
(0, _chai.expect)(data).to.eql('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) {
(0, _chai.expect)(msg).to.eql('hello there');
socket.emit('outgoing', 'Hello over websockets');
});
});
should emit open and close events when socket.io client connects and disconnects.
var ports = { source: gen.port, proxy: gen.port };
var proxy = (0, _esHttpProxy.createProxyServer)({ target: 'ws://127.0.0.1:' + ports.source,
ws: true
});
var proxyServer = proxy.listen(ports.proxy);
var server = _http2.default.createServer();
var destiny = _socket2.default.listen(server);
function startSocketIo() {
var client = _socket4.default.connect('ws://127.0.0.1:' + ports.proxy, { rejectUnauthorized: null });
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);
should pass all set-cookie headers to client.
var ports = { source: gen.port, proxy: gen.port };
var proxy = (0, _esHttpProxy.createProxyServer)({
target: 'ws://127.0.0.1:' + ports.source,
ws: true
}),
proxyServer = proxy.listen(ports.proxy),
destiny = new _ws2.default.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 = _http2.default.request(requestOptions);
req.on('upgrade', function (res, socket, upgradeHead) {
(0, _chai.expect)(res.headers['set-cookie'].length).to.eql(2);
done();
});
req.end();
});
destiny.on('headers', function (headers) {
headers.push('Set-Cookie: test1=test1');
headers.push('Set-Cookie: test2=test2');
});
should detect a proxyReq event and modify headers.
var ports = { source: gen.port, proxy: gen.port },
proxy,
proxyServer,
destiny;
proxy = (0, _esHttpProxy.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 _ws2.default.Server({ port: ports.source }, function () {
var client = new _ws2.default('ws://127.0.0.1:' + ports.proxy);
client.on('open', function () {
client.send('hello there');
});
client.on('message', function (msg) {
(0, _chai.expect)(msg).to.eql('Hello over websockets');
client.close();
proxyServer.close();
destiny.close();
done();
});
});
destiny.on('connection', function (socket) {
(0, _chai.expect)(socket.upgradeReq.headers['x-special-proxy-header']).to.eql('foobar');
socket.on('message', function (msg) {
(0, _chai.expect)(msg).to.eql('hello there');
socket.send('Hello over websockets');
});
});
should forward frames with single frame payload (including on node 4.x).
var payload = Array(65529).join('0');
var ports = { source: gen.port, proxy: gen.port };
var proxy = (0, _esHttpProxy.createProxyServer)({
target: 'ws://127.0.0.1:' + ports.source,
ws: true
}),
proxyServer = proxy.listen(ports.proxy),
destiny = new _ws2.default.Server({ port: ports.source }, function () {
var client = new _ws2.default('ws://127.0.0.1:' + ports.proxy);
client.on('open', function () {
client.send(payload);
});
client.on('message', function (msg) {
(0, _chai.expect)(msg).to.eql('Hello over websockets');
client.close();
proxyServer.close();
destiny.close();
done();
});
});
destiny.on('connection', function (socket) {
socket.on('message', function (msg) {
(0, _chai.expect)(msg).to.eql(payload);
socket.send('Hello over websockets');
});
});
should forward continuation frames with big payload (including on node 4.x).
var payload = Array(65530).join('0');
var ports = { source: gen.port, proxy: gen.port };
var proxy = (0, _esHttpProxy.createProxyServer)({
target: 'ws://127.0.0.1:' + ports.source,
ws: true
}),
proxyServer = proxy.listen(ports.proxy),
destiny = new _ws2.default.Server({ port: ports.source }, function () {
var client = new _ws2.default('ws://127.0.0.1:' + ports.proxy);
client.on('open', function () {
client.send(payload);
});
client.on('message', function (msg) {
(0, _chai.expect)(msg).to.eql('Hello over websockets');
client.close();
proxyServer.close();
destiny.close();
done();
});
});
destiny.on('connection', function (socket) {
socket.on('message', function (msg) {
(0, _chai.expect)(msg).to.eql(payload);
socket.send('Hello over websockets');
});
});
lib/es-http-proxy.js
HTTPS #createProxyServer
HTTPS to HTTP
should proxy the request en send back the response.
var ports = { source: gen.port, proxy: gen.port };
var source = _http2.default.createServer(function (req, res) {
(0, _chai.expect)(req.method).to.eql('GET');
(0, _chai.expect)(req.headers.host.split(':')[1]).to.eql(ports.proxy.toString());
res.writeHead(200, { 'Content-Type': 'text/plain' });
res.end('Hello from ' + ports.source);
});
source.listen(ports.source);
var proxy = (0, _esHttpProxy.createProxyServer)({
target: 'http://127.0.0.1:' + ports.source,
ssl: {
key: _fs2.default.readFileSync(_path2.default.join(__dirname, 'fixtures', 'agent2-key.pem')),
cert: _fs2.default.readFileSync(_path2.default.join(__dirname, 'fixtures', 'agent2-cert.pem')),
ciphers: 'AES128-GCM-SHA256'
}
}).listen(ports.proxy);
_https2.default.request({
host: 'localhost',
port: ports.proxy,
path: '/',
method: 'GET',
rejectUnauthorized: false
}, function (res) {
(0, _chai.expect)(res.statusCode).to.eql(200);
res.on('data', function (data) {
(0, _chai.expect)(data.toString()).to.eql('Hello from ' + ports.source);
});
res.on('end', function () {
source.close();
proxy.close();
done();
});
}).end();
HTTP to HTTPS
should proxy the request and send back the response.
var ports = { source: gen.port, proxy: gen.port };
var source = _https2.default.createServer({
key: _fs2.default.readFileSync(_path2.default.join(__dirname, 'fixtures', 'agent2-key.pem')),
cert: _fs2.default.readFileSync(_path2.default.join(__dirname, 'fixtures', 'agent2-cert.pem')),
ciphers: 'AES128-GCM-SHA256'
}, function (req, res) {
(0, _chai.expect)(req.method).to.eql('GET');
(0, _chai.expect)(req.headers.host.split(':')[1]).to.eql(ports.proxy.toString());
res.writeHead(200, { 'Content-Type': 'text/plain' });
res.end('Hello from ' + ports.source);
});
source.listen(ports.source);
var proxy = (0, _esHttpProxy.createProxyServer)({
target: 'https://127.0.0.1:' + ports.source,
// Allow to use SSL self signed
secure: false
}).listen(ports.proxy);
_http2.default.request({
hostname: '127.0.0.1',
port: ports.proxy,
method: 'GET'
}, function (res) {
(0, _chai.expect)(res.statusCode).to.eql(200);
res.on('data', function (data) {
(0, _chai.expect)(data.toString()).to.eql('Hello from ' + ports.source);
});
res.on('end', function () {
source.close();
proxy.close();
done();
});
}).end();
HTTPS to HTTPS
should proxy the request en send back the response.
var ports = { source: gen.port, proxy: gen.port };
var source = _https2.default.createServer({
key: _fs2.default.readFileSync(_path2.default.join(__dirname, 'fixtures', 'agent2-key.pem')),
cert: _fs2.default.readFileSync(_path2.default.join(__dirname, 'fixtures', 'agent2-cert.pem')),
ciphers: 'AES128-GCM-SHA256'
}, function (req, res) {
(0, _chai.expect)(req.method).to.eql('GET');
(0, _chai.expect)(req.headers.host.split(':')[1]).to.eql(ports.proxy.toString());
res.writeHead(200, { 'Content-Type': 'text/plain' });
res.end('Hello from ' + ports.source);
});
source.listen(ports.source);
var proxy = (0, _esHttpProxy.createProxyServer)({
target: 'https://127.0.0.1:' + ports.source,
ssl: {
key: _fs2.default.readFileSync(_path2.default.join(__dirname, 'fixtures', 'agent2-key.pem')),
cert: _fs2.default.readFileSync(_path2.default.join(__dirname, 'fixtures', 'agent2-cert.pem')),
ciphers: 'AES128-GCM-SHA256'
},
secure: false
}).listen(ports.proxy);
_https2.default.request({
host: 'localhost',
port: ports.proxy,
path: '/',
method: 'GET',
rejectUnauthorized: false
}, function (res) {
(0, _chai.expect)(res.statusCode).to.eql(200);
res.on('data', function (data) {
(0, _chai.expect)(data.toString()).to.eql('Hello from ' + ports.source);
});
res.on('end', function () {
source.close();
proxy.close();
done();
});
}).end();
HTTPS not allow SSL self signed
should fail with error.
var ports = { source: gen.port, proxy: gen.port };
var source = _https2.default.createServer({
key: _fs2.default.readFileSync(_path2.default.join(__dirname, 'fixtures'