Skip to content

Commit

Permalink
Support subpaths in proxies for Testacular
Browse files Browse the repository at this point in the history
  • Loading branch information
shyamseshadri committed Aug 13, 2012
1 parent dc22e8e commit 8933381
Show file tree
Hide file tree
Showing 3 changed files with 64 additions and 13 deletions.
35 changes: 32 additions & 3 deletions lib/proxy.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,34 @@
var url = require('url');

var parseProxyConfig = function(proxies) {
var proxyConfig = {};
function endsWith(str, suffix) {
return str.indexOf(suffix, str.length - suffix.length) !== -1;
}
if (proxies) {
var proxiesList = Object.keys(proxies) || [];
for (var i = 0; i< proxiesList.length; i++) {
var proxyPath = proxiesList[i];
var proxyUrl = proxies[proxyPath];
if (!endsWith(proxyPath, '/')) {
proxyPath = proxyPath + '/';
}
var proxyDetails = url.parse(proxyUrl);
if (!endsWith(proxyDetails.path, '/')) {
proxyDetails.path = proxyDetails.path + '/';
}
proxyConfig[proxyPath] = {
host: proxyDetails.hostname,
port: proxyDetails.port || '80',
baseProxyUrl: proxyDetails.path
};
}
}
return proxyConfig;
};

exports.parseProxyConfig = parseProxyConfig;

/**
* Returns a handler which understands the proxies and its redirects, along with the proxy to use
* @param proxy A http-proxy.RoutingProxy object with the proxyRequest method
Expand All @@ -18,14 +47,14 @@ var createProxyHandler = function(proxy, proxies) {
if (proxies) {
for (var i = 0; i < proxiesList.length; i++) {
if (request.url.indexOf(proxiesList[i]) === 0) {
proxiedUrl = url.parse(proxies[proxiesList[i]]);
proxiedUrl = proxies[proxiesList[i]];
request.url = request.url.replace(proxiesList[i], proxiedUrl.baseProxyUrl);
break;
}
}
}
if (proxiedUrl) {
proxiedUrl.port = proxiedUrl.port || '80';
proxy.proxyRequest(request, response, {host: proxiedUrl.hostname, port: proxiedUrl.port});
proxy.proxyRequest(request, response, {host: proxiedUrl.host, port: proxiedUrl.port});
return true;
}
return false;
Expand Down
9 changes: 3 additions & 6 deletions lib/web-server.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,13 +26,13 @@ exports.createWebServer = function (fileList, baseFolder, proxies, urlRoot) {
var adapterFolder = path.normalize(__dirname + '/../adapter');

return http.createServer(createHandler(fileList, u.normalizeWinPath(staticFolder),
u.normalizeWinPath(adapterFolder), baseFolder,
new httpProxy.RoutingProxy(), proxies, urlRoot));
u.normalizeWinPath(adapterFolder), baseFolder,
new httpProxy.RoutingProxy(), proxies, urlRoot));
};

var createHandler = function(fileList, staticFolder, adapterFolder, baseFolder, proxyFn, proxies, urlRoot) {
var testacularSrcHandler = createTestacularSourceHandler(fileList, staticFolder, adapterFolder, baseFolder, urlRoot);
var proxiedPathsHandler = proxy.createProxyHandler(proxyFn, proxies);
var proxiedPathsHandler = proxy.createProxyHandler(proxyFn, proxy.parseProxyConfig(proxies));
var sourceFileHandler = createSourceFileHandler(fileList, adapterFolder, baseFolder);
return function(request, response) {
if (testacularSrcHandler(request, response)) {
Expand Down Expand Up @@ -150,6 +150,3 @@ var createSourceFileHandler = function(fileList, adapterFolder, baseFolder) {
}
}
};



33 changes: 29 additions & 4 deletions test/unit/proxy.spec.coffee
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ describe 'proxy unit tests', ->
fsMock = require('mocks').fs
httpMock = require('mocks').http
loadFile = require('mocks').loadFile
actualOptions = null
actualOptions = requestedUrl = null
# async helper
waitForFinishingResponse = ->
waitsFor (-> response._isFinished()), 'Finish response', 100
Expand All @@ -18,35 +18,60 @@ describe 'proxy unit tests', ->
mockProxy = {}
mockProxy.proxyRequest = (req, res, opt) ->
actualOptions = opt
requestedUrl = req.url
res.writeHead 200
res.end 'DONE'
response = null
getProxy = (mockProxy, proxy) ->
m.createProxyHandler mockProxy, m.parseProxyConfig(proxy)

beforeEach ->
actualOptions = {}
requestedUrl = ''
response = new httpMock.ServerResponse

it 'should proxy requests', ->
proxy = m.createProxyHandler(mockProxy, {'/proxy': 'http://localhost:9000'})
proxy = getProxy mockProxy, {'/proxy': 'http://localhost:9000'}

expect(proxy new httpMock.ServerRequest('/proxy/test.html'), response).toBeTruthy()
waitForFinishingResponse()

runs ->
expect(requestedUrl).toEqual '/test.html'
expect(actualOptions).toEqual {host: 'localhost', port: '9000'}

it 'should support multiple proxies', ->
proxy = m.createProxyHandler(mockProxy, {'/proxy': 'http://localhost:9000', '/static': 'http://gstatic.com'})
proxy = getProxy mockProxy, {'/proxy': 'http://localhost:9000', '/static': 'http://gstatic.com'}
expect(proxy new httpMock.ServerRequest('/static/test.html'), response).toBeTruthy()
waitForFinishingResponse()

runs ->
expect(requestedUrl).toEqual '/test.html'
expect(actualOptions).toEqual {host: 'gstatic.com', port: '80'}

it 'should handle nested proxies', ->
proxy = m.createProxyHandler(mockProxy, {'/sub': 'http://localhost:9000', '/sub/some': 'http://gstatic.com'})
proxy = getProxy mockProxy, {'/sub': 'http://localhost:9000', '/sub/some': 'http://gstatic.com/something'}
expect(proxy new httpMock.ServerRequest('/sub/some/Test.html'), response).toBeTruthy()
waitForFinishingResponse()

runs ->
expect(requestedUrl).toEqual '/something/Test.html'
expect(actualOptions).toEqual {host: 'gstatic.com', port: '80'}

it 'should parse a simple proxy config', ->
proxy = {'/base/': 'http://localhost:8000'}
parsedProxyConfig = m.parseProxyConfig proxy
expect(parsedProxyConfig).toEqual({'/base/': {host: 'localhost', port: '8000', baseProxyUrl: '/'}})

it 'should handle proxy configs without trailing slash', ->
proxy = {'/base': 'http://internationalhost:8000'}
parsedProxyConfig = m.parseProxyConfig proxy
expect(parsedProxyConfig).toEqual({'/base/': {host: 'internationalhost', port: '8000', baseProxyUrl: '/'}})

it 'should handle proxy configs with paths', ->
proxy = {'/base': 'http://localhost:8000/proxy'}
parsedProxyConfig = m.parseProxyConfig proxy
expect(parsedProxyConfig).toEqual({'/base/': {host: 'localhost', port: '8000', baseProxyUrl: '/proxy/'}})

it 'should handle empty proxy config', ->
expect(m.parseProxyConfig {}).toEqual({})

0 comments on commit 8933381

Please sign in to comment.