From 2e963c32cf90bb9abe1e84098aad2deccaf41c59 Mon Sep 17 00:00:00 2001 From: Shane Russell Date: Mon, 12 Oct 2015 10:54:38 -0700 Subject: [PATCH] feat(web-server): allow injection of custom middleware. Closes #1612 --- docs/config/01-configuration-file.md | 29 ++++++++++++++++++++ lib/web-server.js | 11 ++++++-- test/unit/web-server.spec.js | 40 +++++++++++++++++++++++++--- 3 files changed, 75 insertions(+), 5 deletions(-) diff --git a/docs/config/01-configuration-file.md b/docs/config/01-configuration-file.md index ecf5abf05..410ef4a28 100644 --- a/docs/config/01-configuration-file.md +++ b/docs/config/01-configuration-file.md @@ -280,6 +280,35 @@ httpsServerOptions: { **Description:** A list of log appenders to be used. See the documentation for [log4js] for more information. +## middleware +**Type:** Array + +**Default:** `[]` + +**Description:** List of names of additional middleware you want the karma server to use. Middleware will be used in the order listed. + +You must have installed the middleware via a plugin/framework (either inline or via NPM). Additional information can be found in [plugins]. + +The plugin must provide an express/connect middleware function (details about this can be found in [the Express docs](http://expressjs.com/guide/using-middleware.html). An example of custom inline middleware is shown below. + +**Example:** +```javascript +var CustomMiddlewareFactory = function (config) { + return function (request, response, /* next */) { + response.writeHead(200) + return response.end("content!") + } +} +``` + +```javascript +middleware: ['custom'] +plugins: [ + {'middleware:custom': ['factory', CustomMiddlewareFactory]} + ... +] +``` + ## plugins **Type:** Array diff --git a/lib/web-server.js b/lib/web-server.js index 244e48f59..fbb9c6eb4 100644 --- a/lib/web-server.js +++ b/lib/web-server.js @@ -63,9 +63,16 @@ var createWebServer = function (injector, emitter, fileList) { // TODO(vojta): remove, this is only here because of karma-dart // we need a better way of custom handlers .use(injector.invoke(createCustomHandler)) - .use(function (request, response) { - common.serve404(response, request.url) + + if (config.middleware) { + config.middleware.forEach(function (middleware) { + handler.use(injector.get('middleware:' + middleware)) }) + } + + handler.use(function (request, response) { + common.serve404(response, request.url) + }) var serverClass = http var serverArguments = [handler] diff --git a/test/unit/web-server.spec.js b/test/unit/web-server.spec.js index a51c7a1e7..4592f5b1e 100644 --- a/test/unit/web-server.spec.js +++ b/test/unit/web-server.spec.js @@ -32,7 +32,7 @@ describe('web-server', () => { var m = mocks.loadFile(__dirname + '/../../lib/web-server.js', _mocks, _globals) var customFileHandlers = server = emitter = null - + var middlewareActive = false var servedFiles = (files) => { emitter.emit('file_list_modified', {included: [], served: files}) } @@ -41,16 +41,31 @@ describe('web-server', () => { beforeEach(() => { customFileHandlers = [] emitter = new EventEmitter() + var config = { + basePath: '/base/path', + urlRoot: '/', + middleware: ['custom'], + middlewareResponse: 'hello middleware!' + } var injector = new di.Injector([{ - config: ['value', {basePath: '/base/path', urlRoot: '/'}], + config: ['value', config], customFileHandlers: ['value', customFileHandlers], emitter: ['value', emitter], fileList: ['value', {files: {served: [], included: []}}], capturedBrowsers: ['value', null], reporter: ['value', null], executor: ['value', null], - proxies: ['value', null] + proxies: ['value', null], + 'middleware:custom': ['factory', function (config) { + return function (request, response, next) { + if (middlewareActive) { + response.writeHead(222) + return response.end(config.middlewareResponse) + } + next() + } + }] }]) server = injector.invoke(m.createWebServer) @@ -81,6 +96,25 @@ describe('web-server', () => { .expect(200, 'new-js-source') }) + describe('middleware', () => { + beforeEach(() => { + servedFiles(new Set([new File('/base/path/one.js')])) + middlewareActive = true + }) + + it('should use injected middleware', () => { + return request(server) + .get('/base/other.js') + .expect(222, 'hello middleware!') + }) + + it('should inject middleware behind served files', () => { + return request(server) + .get('/base/one.js') + .expect(200, 'js-source') + }) + }) + it('should serve no files when they are not available yet', () => { return request(server) .get('/base/new.js')