blob: 91da2a0a7b93faf279ca151390b2e683154a103e [file] [edit]
/// <reference path="../../../typings/node/node.d.ts" />
/// <reference path="../../../typings/mocha/mocha.d.ts" />
/// <reference path="../../../typings/chai/chai.d.ts" />
'use strict';
var helper = require('../../test-helper');
var config = helper.config();
var chai = require('chai');
var should = chai.should();
var request = require('supertest');
var async = require('async');
var url = require('url');
var path = require('path');
var https = require('https');
describe('passthrough', function() {
var servers, proxy;
before(function(done) {
config.edgemicro.plugins.sequence = []; // no plugins needed for this test
helper.startServers(config, function(err, s) {
if (err) { return done(err); }
servers = s;
proxy = servers.proxy;
done();
});
});
after(function() {
servers.close();
});
describe('path', function() {
it('root should invoke default target', function(done) {
request(proxy)
.get('/')
.expect(200)
.end(function(err, res) {
if (err) { return done(err); }
res.body.fromTarget.should.be.true;
res.body.proxyName.should.eql('microgateway_test');
done();
});
});
it('path match should invoke correct target', function(done) {
request(proxy)
.get('/microgateway_test2')
.expect(200)
.end(function(err, res) {
if (err) { return done(err); }
res.body.fromTarget.should.be.true;
res.body.proxyName.should.eql('microgateway_test2');
done();
});
});
it('path submatch should invoke correct target', function(done) {
request(proxy)
.get('/something/else')
.expect(200)
.end(function(err, res) {
if (err) { return done(err); }
res.body.fromTarget.should.be.true;
res.body.proxyName.should.eql('microgateway_test');
done();
});
});
it('most specific match should invoke correct target', function(done) {
request(proxy)
.get('/microgateway_test2/something/else')
.expect(200)
.end(function(err, res) {
if (err) { return done(err); }
res.body.fromTarget.should.be.true;
res.body.proxyName.should.eql('microgateway_test2');
done();
});
});
it('/boo should match proxy boo', function(done) {
request(proxy)
.get('/boo')
.expect(200)
.end(function(err, res) {
if (err) { return done(err); }
res.body.fromTarget.should.be.true;
res.body.proxyName.should.eql('boo');
done();
});
});
it('/boo1 should match proxy boo', function(done) {
request(proxy)
.get('/boo1')
.expect(200)
.end(function(err, res) {
if (err) { return done(err); }
res.body.fromTarget.should.be.true;
res.body.proxyName.should.eql('boo');
done();
});
});
it('/boo/bar should match proxy boo', function(done) {
request(proxy)
.get('/boo/bar')
.expect(200)
.end(function(err, res) {
if (err) { return done(err); }
res.body.fromTarget.should.be.true;
res.body.proxyName.should.eql('boo');
done();
});
});
it('/b should match proxy b', function(done) {
request(proxy)
.get('/b')
.expect(200)
.end(function(err, res) {
if (err) { return done(err); }
res.body.fromTarget.should.be.true;
res.body.proxyName.should.eql('b');
done();
});
});
it('/b2 should match proxy b', function(done) {
request(proxy)
.get('/b2')
.expect(200)
.end(function(err, res) {
if (err) { return done(err); }
res.body.fromTarget.should.be.true;
res.body.proxyName.should.eql('b');
done();
});
});
it('/b/bar/foo should match proxy b', function(done) {
request(proxy)
.get('/b/bar/foo')
.expect(200)
.end(function(err, res) {
if (err) { return done(err); }
res.body.fromTarget.should.be.true;
res.body.proxyName.should.eql('b');
done();
});
});
});
describe('query params', function() {
it('should pass through', function(done) {
var pathname = '/foo';
var search = '?id=42';
var path = pathname + search;
request(proxy)
.get(path)
.expect(200)
.end(function(err, res) {
if (err) { return done(err); }
res.body.fromTarget.should.be.true;
res.body.should.have.property('url').that.is.a.String;
var reqUrl = url.parse(res.body.url);
reqUrl.pathname.should.equal(pathname);
reqUrl.path.should.equal(path);
reqUrl.search.should.equal(search);
done();
});
});
it('missing should pass through', function(done) {
var pathname = '/foo';
request(proxy)
.get(pathname)
.expect(200)
.end(function(err, res) {
if (err) { return done(err); }
res.body.fromTarget.should.be.true;
res.body.should.have.property('url').that.is.a.String;
var reqUrl = url.parse(res.body.url);
reqUrl.pathname.should.equal(pathname);
done();
});
});
it('missing in sub path should pass through', function(done) {
var pathname = '/foo/bar/42';
request(proxy)
.get(pathname)
.expect(200)
.end(function(err, res) {
if (err) { return done(err); }
res.body.fromTarget.should.be.true;
res.body.should.have.property('url').that.is.a.String;
var reqUrl = url.parse(res.body.url);
reqUrl.pathname.should.equal(pathname);
done();
});
});
it('in sub path should pass through', function(done) {
var pathname = '/foo/bar/42';
var search = '?uid=MTQzNjIyMjgxOTUxNQ&pid=1234';
var path = pathname + search;
request(proxy)
.get(path)
.expect(200)
.end(function(err, res) {
if (err) { return done(err); }
res.body.fromTarget.should.be.true;
res.body.should.have.property('url').that.is.a.String;
var reqUrl = url.parse(res.body.url);
reqUrl.pathname.should.equal(pathname);
reqUrl.path.should.equal(path);
reqUrl.search.should.equal(search);
done();
});
});
});
describe('body', function() {
it('should pass through', function(done) {
var data = JSON.stringify({ gotIt: true });
request(proxy)
.post('/foo')
.send(data)
.expect(200)
.end(function(err, res) {
if (err) { return done(err); }
res.body.fromTarget.should.be.true;
res.body.should.have.property('body').that.is.a.String;
res.body.body.should.equal(data);
done();
});
});
it('should pass through if large', function(done) {
var data = new Buffer(1024 * 65);
data.fill('x');
data = data.toString();
request(proxy)
.post('/foo')
.send(data)
.expect(200)
.end(function(err, res) {
if (err) { return done(err); }
res.body.fromTarget.should.be.true;
res.body.should.have.property('body').that.is.a.String;
res.body.body.length.should.equal(data.length);
res.body.body.should.equal(data);
done();
});
});
});
describe('response headers', function() {
var headers = ['x-response-time'];
headers.forEach(function(header) {
describe (header, function() {
it('should exist when not configured', function(done) {
config.headers = {};
request(proxy)
.get('/')
.expect(200)
.end(function(err, res) {
if (err) { return done(err); }
res.body.fromTarget.should.be.true;
should.exist(res.headers['x-response-time']);
done();
});
});
it('should exist when true', function(done) {
config.headers[header] = true;
request(proxy)
.get('/')
.expect(200)
.end(function(err, res) {
if (err) { return done(err); }
res.body.fromTarget.should.be.true;
should.exist(res.headers['x-response-time']);
done();
});
});
it('should not exist when false', function(done) {
config.headers = {};
config.headers[header] = false;
request(proxy)
.get('/')
.expect(200)
.end(function(err, res) {
if (err) { return done(err); }
res.body.fromTarget.should.be.true;
should.not.exist(res.headers['x-response-time']);
done();
});
});
});
});
});
describe('target header', function() {
var headers = ['x-forwarded-for', 'x-forwarded-host', 'x-request-id', 'via'];
headers.forEach(function(header) {
describe(header, function() {
it('should exist when not configured', function(done) {
config.headers = {};
request(proxy)
.get('/')
.expect(200)
.end(function(err, res) {
if (err) { return done(err); }
res.body.fromTarget.should.be.true;
should.exist(res.body.headers[header]);
done();
});
});
it('should exist when true', function(done) {
config.headers[header] = true;
request(proxy)
.get('/')
.expect(200)
.end(function(err, res) {
if (err) { return done(err); }
res.body.fromTarget.should.be.true;
should.exist(res.body.headers[header]);
done();
});
});
it('should not exist when false', function(done) {
config.headers = {};
config.headers[header] = false;
request(proxy)
.get('/')
.expect(200)
.end(function(err, res) {
if (err) { return done(err); }
res.body.fromTarget.should.be.true;
should.not.exist(res.body.headers[header]);
done();
});
});
});
});
});
describe('existing target header', function() {
var headers = ['x-forwarded-for', 'x-forwarded-host', 'via'];
var headerValue = 'my header';
headers.forEach(function(header) {
describe(header, function() {
config.headers = {};
config.headers[header] = true;
it('should include both headers', function(done) {
config.headers[header] = true;
request(proxy)
.get('/')
.set(header, headerValue)
.expect(200)
.end(function(err, res) {
if (err) { return done(err); }
res.body.fromTarget.should.be.true;
should.exist(res.body.headers[header]);
res.body.headers[header].should.match(new RegExp(headerValue + ',.+'));
done();
});
});
});
});
});
describe('target down', function() {
var proxy;
before(function(done) {
helper.startServers(config, function(err, servers) {
if (err) { return done(err); }
servers.targets.forEach(function(target) {
target.close();
});
proxy = servers.proxy;
done();
});
});
after(function() {
proxy.close();
});
it('should fail with 502 gateway error', function(done) {
request(proxy)
.get('/')
.expect(502, done);
});
});
describe('too many connections', function() {
var servers, proxy;
before(function(done) {
config.edgemicro.max_connections = 1;
helper.startServers(config, function(err, s) {
if (err) { return done(err); }
servers = s;
proxy = servers.proxy;
done();
});
});
after(function() {
servers.close();
});
it('should fail with 429 error', function(done) {
async.parallel([
function(next) { request(proxy).get('/100').end(function(err, res) { next(err, res) }) },
function(next) { request(proxy).get('/100').end(function(err, res) { next(err, res) }) }
], function(err, res) {
res[0].error.should.be.false;
res[0].statusCode.should.equal(200);
should.exist(res[1].error);
res[1].statusCode.should.equal(429);
done(err);
});
});
});
describe('SSL-termination verification', function() {
var servers, proxy;
/**
* To generate certificates, make sure you have openssl installed
* run the following:
* openssl genrsa -out key.pem 2048
* openssl req -new -key key.pem -out csr.pem
* openssl req -x509 -days 365 -key key.pem -in csr.pem -out certificate.pem
*
* To view the certificate information, run this command:
* openssl x509 -in certificate.pem -noout -text
*/
before(function(done) {
config.edgemicro['ssl'] = {
cert: path.join(__dirname, 'certificate.pem'),
key: path.join(__dirname, 'key.pem')
}
helper.startServers(config, function(err, s) {
if (err) { return done(err); }
servers = s;
proxy = servers.proxy;
done();
});
});
it('proxy should be SSL-terminated', function(done) {
https.request({
port: config.edgemicro.port,
ca: proxy.cert
}, function(res) {
res.statusCode.should.equal(200);
done();
}).end();
});
after(function() {
servers.close();
});
});
});