From 2df8828742041fd09c0b45d6a62ebd7552116589 Mon Sep 17 00:00:00 2001 From: pavelgj Date: Mon, 18 Mar 2013 16:33:08 -0700 Subject: [PATCH] feat(web-server): allow custom file handlers and mime types --- lib/server.js | 2 ++ lib/web-server.js | 36 +++++++++++++++++++------- test/unit/web-server.spec.coffee | 44 +++++++++++++++++++++++++++++--- 3 files changed, 70 insertions(+), 12 deletions(-) diff --git a/lib/server.js b/lib/server.js index 76362d412..de92322cc 100644 --- a/lib/server.js +++ b/lib/server.js @@ -241,6 +241,8 @@ exports.start = function(cliOptions, done) { preprocess: ['factory', preprocessor.createPreprocessor], fileList: ['type', FileList], webServer: ['factory', ws.createWebServer], + customFileHandlers: ['value', []], + customScriptTypes: ['value', []], reporter: ['factory', reporter.createReporters], capturedBrowsers: ['type', browser.Collection] }]; diff --git a/lib/web-server.js b/lib/web-server.js index 3419b42b6..3a3a41887 100644 --- a/lib/web-server.js +++ b/lib/web-server.js @@ -12,7 +12,7 @@ var helper = require('./helper'); var proxy = require('./proxy'); var log = require('./logger').create('web server'); -var SCRIPT_TAG = ''; +var SCRIPT_TAG = ''; var setNoCacheHeaders = function(response) { @@ -44,10 +44,9 @@ var serveStaticFile = function(file, response, process) { var createKarmaSourceHandler = function(promiseContainer, staticFolder, adapterFolder, - baseFolder, urlRoot) { + baseFolder, urlRoot, customFileHandlers, customScriptTypes) { return function(request, response, next) { var requestUrl = request.url.replace(/\?.*/, ''); - if (requestUrl === urlRoot.substr(0, urlRoot.length - 1)) { response.setHeader('Location', urlRoot); response.writeHead(301); @@ -60,6 +59,15 @@ var createKarmaSourceHandler = function(promiseContainer, staticFolder, adapterF requestUrl = requestUrl.substring(urlRoot.length - 1); + // Check if any of the custom file handlers provided by plugins should be + // invoked first. + for (var i = 0; i < customFileHandlers.length; i++) { + if (customFileHandlers[i].urlRegex.test(requestUrl)) { + return customFileHandlers[i].handler(request, response, staticFolder, + adapterFolder, baseFolder, urlRoot); + } + } + if (requestUrl === '/') { return serveStaticFile(staticFolder + '/client.html', response); } @@ -82,6 +90,13 @@ var createKarmaSourceHandler = function(promiseContainer, staticFolder, adapterF var scriptTags = files.included.map(function(file) { var filePath = file.path; + var scriptType = 'text/javascript'; + customScriptTypes.forEach(function(type) { + var extension = '.' + type.extension; + if (filePath.indexOf(extension, filePath.length - extension.length) !== -1) { + scriptType = type.contentType; + } + }); if (!file.isUrl) { // TODO(vojta): serve these files from within urlRoot as well @@ -98,7 +113,7 @@ var createKarmaSourceHandler = function(promiseContainer, staticFolder, adapterF } } - return util.format(SCRIPT_TAG, filePath); + return util.format(SCRIPT_TAG, scriptType, filePath); }); var mappings = files.served.map(function(file) { @@ -175,9 +190,9 @@ var createSourceFileHandler = function(promiseContainer, adapterFolder, baseFold var createHandler = function(promiseContainer, staticFolder, adapterFolder, baseFolder, proxyFn, - proxies, urlRoot) { + proxies, urlRoot, customFileHandlers, customScriptTypes) { var karmaSrcHandler = createKarmaSourceHandler(promiseContainer, staticFolder, - adapterFolder, baseFolder, urlRoot); + adapterFolder, baseFolder, urlRoot, customFileHandlers, customScriptTypes); var proxiedPathsHandler = proxy.createProxyHandler(proxyFn, proxies); var sourceFileHandler = createSourceFileHandler(promiseContainer, adapterFolder, baseFolder); @@ -194,7 +209,8 @@ var createHandler = function(promiseContainer, staticFolder, adapterFolder, base }; -exports.createWebServer = function (baseFolder, proxies, urlRoot) { +exports.createWebServer = function (baseFolder, proxies, urlRoot, + customFileHandlers, customScriptTypes) { var staticFolder = path.normalize(__dirname + '/../static'); var adapterFolder = path.normalize(__dirname + '/../adapter'); @@ -204,7 +220,8 @@ exports.createWebServer = function (baseFolder, proxies, urlRoot) { var server = http.createServer(createHandler(promiseContainer, helper.normalizeWinPath(staticFolder), helper.normalizeWinPath(adapterFolder), baseFolder, - new httpProxy.RoutingProxy({changeOrigin: true}), proxies, urlRoot)); + new httpProxy.RoutingProxy({changeOrigin: true}), proxies, urlRoot, customFileHandlers, + customScriptTypes)); server.updateFilesPromise = function(promise) { promiseContainer.promise = promise; @@ -213,4 +230,5 @@ exports.createWebServer = function (baseFolder, proxies, urlRoot) { return server; }; -exports.createWebServer.$inject = ['config.basePath', 'config.proxies', 'config.urlRoot']; +exports.createWebServer.$inject = ['config.basePath', 'config.proxies', 'config.urlRoot', + 'customFileHandlers', 'customScriptTypes']; diff --git a/test/unit/web-server.spec.coffee b/test/unit/web-server.spec.coffee index 7dacba37c..63525fe76 100644 --- a/test/unit/web-server.spec.coffee +++ b/test/unit/web-server.spec.coffee @@ -71,7 +71,7 @@ describe 'web-server', -> beforeEach -> servedFiles defaultFiles handler = m.createHandler promiseContainer, staticFolderPath, adapterFolderPath, baseFolder, mockProxy, - {'/_karma_/': 'http://localhost:9000', '/base/': 'http://localhost:1000'}, '/_karma_/' + {'/_karma_/': 'http://localhost:9000', '/base/': 'http://localhost:1000'}, '/_karma_/', [], [] actualOptions = {} response = new responseMock() nextSpy = sinon.spy() @@ -142,7 +142,7 @@ describe 'web-server', -> includedFiles defaultFiles response = new responseMock globals.process.platform = 'darwin' - tcularSrcHandler = m.createKarmaSourceHandler promiseContainer, staticFolderPath, adapterFolderPath, baseFolder, '/_karma_/' + tcularSrcHandler = m.createKarmaSourceHandler promiseContainer, staticFolderPath, adapterFolderPath, baseFolder, '/_karma_/', [], [] it 'should serve client.html', (done) -> @@ -261,10 +261,48 @@ describe 'web-server', -> expect(response.statusCode).to.equal 301 expect(response.getHeader('Location')).to.equal '/_karma_/' done() - + tcularSrcHandler new httpMock.ServerRequest('/_karma_'), response, nextSpy + + it 'should invoke custom handler', (done) -> + response.once 'end', -> + expect(nextSpy).not.to.have.been.called + expect(response.statusCode).to.equal 200 + expect(response._content.toString()).to.equal 'Hello World' + done() + + customHandler = + urlRegex: /\/test/, + handler: (request, response, staticFolder, adapterFolder, baseFolder, urlRoot) -> + response.end 'Hello World' + + tcularSrcHandler = m.createKarmaSourceHandler promiseContainer, staticFolderPath, + adapterFolderPath, baseFolder, '/_karma_/', [customHandler], [] + tcularSrcHandler new httpMock.ServerRequest('/_karma_/test'), response, nextSpy + + + it 'should set custom script type', (done) -> + mocks.fs._touchFile '/tcular/static/context.html', 0, 'CONTEXT\n%SCRIPTS%' + includedFiles [{path: 'http://some.url.com/whatever.blah', isUrl: true}] + + response.once 'end', -> + expect(response._content.toString()).to.equal 'CONTEXT\n' + + '' + expect(response.statusCode).to.equal 200 + done() + + customScriptType = + extension: 'blah', + contentType: 'application/blah' + + tcularSrcHandler = m.createKarmaSourceHandler promiseContainer, staticFolderPath, + adapterFolderPath, baseFolder, '/_karma_/', [], [customScriptType] + + tcularSrcHandler new httpMock.ServerRequest('/_karma_/context.html'), response, nextSpy + + #============================================================================ # Source Files Handler #============================================================================