Add unit tests

This commit is contained in:
Rob Wu
2015-05-05 22:36:44 +02:00
parent f0bdb5ffd1
commit 1ee157fc0f
4 changed files with 469 additions and 0 deletions

View File

@@ -24,6 +24,12 @@
"http-proxy": "1.3.0"
},
"devDependencies": {
"mocha": "~2.2.4",
"nock": "~1.9.0",
"supertest": "~0.15.0"
},
"scripts": {
"test": "./node_modules/.bin/mocha ./test/test.js --reporter spec"
},
"engines": {
"node": ">=0.6.6",

1
test/dummy.txt Normal file
View File

@@ -0,0 +1 @@
dummy content

95
test/setup.js Normal file
View File

@@ -0,0 +1,95 @@
var nock = require('nock');
nock.enableNetConnect('127.0.0.1');
function echoheaders(origin) {
nock(origin)
.persist()
.get('/echoheaders')
.reply(function(uri) {
var headers = this.req.headers;
var excluded_headers = [
'accept-encoding',
'user-agent',
'connection',
// Remove this header since its value is platform-specific.
'x-forwarded-for',
'test-include-xfwd',
];
if (!('test-include-xfwd' in headers)) {
excluded_headers.push('x-forwarded-port');
excluded_headers.push('x-forwarded-proto');
}
var response = {};
Object.keys(headers).forEach(function(name) {
if (excluded_headers.indexOf(name) === -1) {
response[name] = headers[name];
}
});
return response;
});
}
nock('http://example.com')
.persist()
.get('/')
.reply(200, 'Response from example.com')
.post('/echopost')
.reply(200, function(uri, requestBody) {
return requestBody;
})
.get('/setcookie')
.reply(200, '', {
'Set-Cookie': 'x',
'Set-Cookie2': 'y',
'Set-Cookie3': 'z', // This is not a special cookie setting header.
})
.get('/redirecttarget')
.reply(200, 'redirect target', {
'Some header': 'value'
})
.head('/redirect')
.reply(302, '', {
'Location': '/redirecttarget'
})
.get('/redirect')
.reply(302, 'redirecting...', {
'Location': '/redirecttarget'
})
.get('/redirectposttarget')
.reply(200, 'post target')
.post('/redirectposttarget')
.reply(200, 'post target (POST)')
.post('/redirectpost')
.reply(302, 'redirecting...', {
'Location': '/redirectposttarget'
})
.post('/redirect307')
.reply(307, 'redirecting...', {
'Location': '/redirectposttarget'
})
.get('/redirect2redirect')
.reply(302, 'redirecting to redirect...', {
'Location': '/redirect'
})
.get('/redirectloop')
.reply(302, 'redirecting ad infinitum...', {
'Location': '/redirectloop'
})
;
echoheaders('http://example.com');
echoheaders('http://example.com:1337');
echoheaders('https://example.com');
echoheaders('https://example.com:1337');

367
test/test.js Normal file
View File

@@ -0,0 +1,367 @@
require('./setup');
var createServer = require('../').createServer;
var request = require('supertest');
var path = require('path');
var fs = require('fs');
var helpTextPath = path.join(__dirname, '../lib/help.txt');
var helpText = fs.readFileSync(helpTextPath, { encoding: 'utf8' });
request.Test.prototype.expectJSON = function(json, done) {
return this.expect(200, JSON.stringify(json), done);
};
var cors_anywhere;
function stopServer(done) {
cors_anywhere.close(function() {
done();
});
cors_anywhere = null;
}
describe('Basic functionality', function() {
before(function() {
// Mostly the default settings from server.js
cors_anywhere = createServer();
});
after(stopServer);
it('GET /', function(done) {
request(cors_anywhere)
.get('/')
.type('text/plain')
.expect('Access-Control-Allow-Origin', '*')
.expect(200, helpText, done);
});
it('GET /iscorsneeded', function(done) {
request(cors_anywhere)
.get('/iscorsneeded')
.expect(function(res) {
if ('access-control-allow-origin' in res.headers) {
return 'access-control-allow-origin header should not be set';
}
})
.end(done);
});
it('GET /example.com:65536', function(done) {
request(cors_anywhere)
.get('/example.com:65536')
.expect('Access-Control-Allow-Origin', '*')
.expect(400, 'Port number too large: 65536', done);
});
it('GET /favicon.ico', function(done) {
request(cors_anywhere)
.get('/favicon.ico')
.expect('Access-Control-Allow-Origin', '*')
.expect(404, 'Invalid host: favicon.ico', done);
});
it('GET /robots.txt', function(done) {
request(cors_anywhere)
.get('/robots.txt')
.expect('Access-Control-Allow-Origin', '*')
.expect(404, 'Invalid host: robots.txt', done);
});
it('GET /example.com', function(done) {
request(cors_anywhere)
.get('/example.com')
.expect('Access-Control-Allow-Origin', '*')
.expect('x-request-url', 'http://example.com/')
.expect(200, 'Response from example.com', done);
});
it('GET //example.com', function(done) {
// '/example.com' is an invalid URL.
request(cors_anywhere)
.get('//example.com')
.expect('Access-Control-Allow-Origin', '*')
.expect(200, helpText, done);
});
it('GET ///example.com', function(done) {
// API base URL (with trailing slash) + '//example.com'
request(cors_anywhere)
.get('///example.com')
.expect('Access-Control-Allow-Origin', '*')
.expect('x-request-url', 'http://example.com/')
.expect(200, 'Response from example.com', done);
});
it('GET /http://example.com', function(done) {
request(cors_anywhere)
.get('/http://example.com')
.expect('Access-Control-Allow-Origin', '*')
.expect('x-request-url', 'http://example.com/')
.expect(200, 'Response from example.com', done);
});
it('POST plain text', function(done) {
request(cors_anywhere)
.post('/example.com/echopost')
.send('{"this is a request body & should not be mangled":1.00}')
.expect('Access-Control-Allow-Origin', '*')
.expect('{"this is a request body & should not be mangled":1.00}', done);
});
it('POST file', function(done) {
request(cors_anywhere)
.post('/example.com/echopost')
.attach('file', path.join(__dirname, 'dummy.txt'))
.expect('Access-Control-Allow-Origin', '*')
.expect(/\r\nContent-Disposition: form-data; name="file"; filename="dummy.txt"\r\nContent-Type: text\/plain\r\n\r\ndummy content\n\r\n/, done);
});
it('HEAD with redirect should be followed', function(done) {
// Redirects are automatically followed, because redirects are to be
// followed automatically per specification regardless of the HTTP verb.
request(cors_anywhere)
.head('/example.com/redirect')
.redirects(0)
.expect('Access-Control-Allow-Origin', '*')
.expect('some header', 'value')
.expect('x-request-url', 'http://example.com/redirect')
.expect('x-cors-redirect-1', '302 http://example.com/redirecttarget')
.expect('x-final-url', 'http://example.com/redirecttarget')
.expect('access-control-expose-headers', /some header,x-final-url/)
.expect(200, '', done);
});
it('GET with redirect should be followed', function(done) {
request(cors_anywhere)
.get('/example.com/redirect')
.redirects(0)
.expect('Access-Control-Allow-Origin', '*')
.expect('some header', 'value')
.expect('x-request-url', 'http://example.com/redirect')
.expect('x-cors-redirect-1', '302 http://example.com/redirecttarget')
.expect('x-final-url', 'http://example.com/redirecttarget')
.expect('access-control-expose-headers', /some header,x-final-url/)
.expect(200, 'redirect target', done);
});
it('GET with redirect loop should interrupt', function(done) {
request(cors_anywhere)
.get('/example.com/redirectloop')
.redirects(0)
.expect('Access-Control-Allow-Origin', '*')
.expect('x-request-url', 'http://example.com/redirectloop')
.expect('x-cors-redirect-1', '302 http://example.com/redirectloop')
.expect('x-cors-redirect-2', '302 http://example.com/redirectloop')
.expect('x-cors-redirect-3', '302 http://example.com/redirectloop')
.expect('x-cors-redirect-4', '302 http://example.com/redirectloop')
.expect('x-cors-redirect-5', '302 http://example.com/redirectloop')
.expect('Location', /^http:\/\/127.0.0.1:\d+\/http:\/\/example.com\/redirectloop$/)
.expect(302, 'redirecting ad infinitum...', done);
});
it('POST with 302 redirect should be followed', function(done) {
request(cors_anywhere)
.post('/example.com/redirectpost')
.redirects(0)
.expect('Access-Control-Allow-Origin', '*')
.expect('x-request-url', 'http://example.com/redirectpost')
.expect('x-cors-redirect-1', '302 http://example.com/redirectposttarget')
.expect('x-final-url', 'http://example.com/redirectposttarget')
.expect('access-control-expose-headers', /x-final-url/)
.expect(200, 'post target', done);
});
it('POST with 307 redirect should not be handled', function(done) {
// Because of implementation difficulties (having to keep the request body
// in memory), handling HTTP 307/308 redirects is deferred to the requestor.
request(cors_anywhere)
.post('/example.com/redirect307')
.redirects(0)
.expect('Access-Control-Allow-Origin', '*')
.expect('x-request-url', 'http://example.com/redirect307')
.expect('Location', /^http:\/\/127.0.0.1:\d+\/http:\/\/example.com\/redirectposttarget$/)
.expect('x-final-url', 'http://example.com/redirect307')
.expect('access-control-expose-headers', /x-final-url/)
.expect(307, 'redirecting...', done);
});
it('OPTIONS /', function(done) {
request(cors_anywhere)
.options('/')
.expect('Access-Control-Allow-Origin', '*')
.expect(200, '', done);
});
it('OPTIONS / with Access-Control-Request-Method / -Headers', function(done) {
request(cors_anywhere)
.options('/')
.set('Access-Control-Request-Method', 'DELETE')
.set('Access-Control-Request-Headers', 'X-Tralala')
.expect('Access-Control-Allow-Origin', '*')
.expect('Access-Control-Allow-Methods', 'DELETE')
.expect('Access-Control-Allow-Headers', 'X-Tralala')
.expect(200, '', done);
});
it('OPTIONS //bogus', function(done) {
// The preflight request always succeeds, regardless of whether the request
// is valid.
request(cors_anywhere)
.options('//bogus')
.expect('Access-Control-Allow-Origin', '*')
.expect(200, '', done);
});
it('X-Forwarded-* headers', function(done) {
request(cors_anywhere)
.get('/example.com/echoheaders')
.set('test-include-xfwd', '')
.expect('Access-Control-Allow-Origin', '*')
.expectJSON({
host: 'example.com',
'x-forwarded-port': '80',
'x-forwarded-proto': 'http',
}, done);
});
it('X-Forwarded-* headers (non-standard port)', function(done) {
request(cors_anywhere)
.get('/example.com:1337/echoheaders')
.set('test-include-xfwd', '')
.expect('Access-Control-Allow-Origin', '*')
.expectJSON({
host: 'example.com:1337',
'x-forwarded-port': '1337',
'x-forwarded-proto': 'http',
}, done);
});
// Skipped because x-forwarded-proto == http and port == 80
it.skip('X-Forwarded-* headers (https)', function(done) {
request(cors_anywhere)
.get('/https://example.com/echoheaders')
.set('test-include-xfwd', '')
.expect('Access-Control-Allow-Origin', '*')
.expectJSON({
host: 'example.com',
'x-forwarded-port': '443',
'x-forwarded-proto': 'https',
}, done);
});
// Skipped because x-forwarded-proto == http
it.skip('X-Forwarded-* headers (https, non-standard port)', function(done) {
request(cors_anywhere)
.get('/https://example.com:1337/echoheaders')
.set('test-include-xfwd', '')
.expect('Access-Control-Allow-Origin', '*')
.expectJSON({
host: 'example.com:1337',
'x-forwarded-port': '1337',
'x-forwarded-proto': 'https',
}, done);
});
it('Ignore cookies', function(done) {
request(cors_anywhere)
.get('/example.com/setcookie')
.expect('Access-Control-Allow-Origin', '*')
.expect('Set-Cookie3', 'z')
.expect(function(res) {
if (res.headers['set-cookie']) {
return 'set-cookie header was set';
}
if (res.headers['set-cookie2']) {
return 'set-cookie2 header was set';
}
})
.end(done);
});
});
describe('requireHeader', function() {
before(function() {
cors_anywhere = createServer({
requireHeader: ['origin', 'x-requested-with'],
});
});
after(stopServer);
it('GET /example.com without header', function(done) {
request(cors_anywhere)
.get('/example.com/')
.expect('Access-Control-Allow-Origin', '*')
.expect(400, 'Missing required request header. Must specify one of: origin,x-requested-with', done);
});
it('GET /example.com with X-Requested-With header', function(done) {
request(cors_anywhere)
.get('/example.com/')
.set('X-Requested-With', '')
.expect('Access-Control-Allow-Origin', '*')
.expect(200, done);
});
it('GET /example.com with Origin header', function(done) {
request(cors_anywhere)
.get('/example.com/')
.set('Origin', 'null')
.expect('Access-Control-Allow-Origin', '*')
.expect(200, done);
});
});
describe('removeHeaders', function() {
before(function() {
cors_anywhere = createServer({
removeHeaders: ['cookie', 'cookie2'],
});
});
after(stopServer);
it('GET /example.com with request cookie', function(done) {
request(cors_anywhere)
.get('/example.com/echoheaders')
.set('cookie', 'a')
.set('cookie2', 'b')
.expect('Access-Control-Allow-Origin', '*')
.expectJSON({
host: 'example.com',
}, done);
});
it('GET /example.com with unknown header', function(done) {
request(cors_anywhere)
.get('/example.com/echoheaders')
.set('cookie', 'a')
.set('cookie2', 'b')
.set('cookie3', 'c')
.expect('Access-Control-Allow-Origin', '*')
.expectJSON({
host: 'example.com',
cookie3: 'c',
}, done);
});
});
describe('httpProxyOptions.xfwd=false', function() {
before(function() {
cors_anywhere = createServer({
httpProxyOptions: {
xfwd: false
}
});
});
after(stopServer);
it('X-Forwarded-* headers should not be set', function(done) {
request(cors_anywhere)
.get('/example.com/echoheaders')
.set('test-include-xfwd', '')
.expect('Access-Control-Allow-Origin', '*')
.expectJSON({
host: 'example.com',
}, done);
});
});