| 'use strict' |
| |
| const fs = require('graceful-fs') |
| const http = require('http') |
| const https = require('https') |
| const path = require('path') |
| const connect = require('connect') |
| const Promise = require('bluebird') |
| |
| const common = require('./middleware/common') |
| const runnerMiddleware = require('./middleware/runner') |
| const stopperMiddleware = require('./middleware/stopper') |
| const karmaMiddleware = require('./middleware/karma') |
| const sourceFilesMiddleware = require('./middleware/source_files') |
| const proxyMiddleware = require('./middleware/proxy') |
| |
| const log = require('./logger').create('web-server') |
| |
| function createCustomHandler (customFileHandlers, config) { |
| return function (request, response, next) { |
| const handler = customFileHandlers.find((handler) => handler.urlRegex.test(request.url)) |
| return handler |
| ? handler.handler(request, response, 'fake/static', 'fake/adapter', config.basePath, 'fake/root') |
| : next() |
| } |
| } |
| |
| createCustomHandler.$inject = ['customFileHandlers', 'config'] |
| |
| function createFilesPromise (emitter, fileList) { |
| const filesPromise = new common.PromiseContainer() |
| |
| // Set an empty list of files to avoid race issues with |
| // file_list_modified not having been emitted yet |
| filesPromise.set(Promise.resolve(fileList.files)) |
| |
| emitter.on('file_list_modified', (files) => filesPromise.set(Promise.resolve(files))) |
| |
| return filesPromise |
| } |
| |
| // Bind the filesystem into the injectable file reader function |
| function createReadFilePromise () { |
| return (filepath) => { |
| return new Promise((resolve, reject) => { |
| fs.readFile(filepath, 'utf8', function (error, data) { |
| if (error) { |
| reject(new Error(`Cannot read ${filepath}, got: ${error}`)) |
| } else if (!data) { |
| reject(new Error(`No content at ${filepath}`)) |
| } else { |
| resolve(data.split('\n')) |
| } |
| }) |
| }) |
| } |
| } |
| |
| createReadFilePromise.$inject = [] |
| |
| function createServeStaticFile (config) { |
| return common.createServeFile(fs, path.normalize(path.join(__dirname, '/../static')), config) |
| } |
| createServeStaticFile.$inject = ['config'] |
| |
| function createServeFile (config) { |
| return common.createServeFile(fs, null, config) |
| } |
| createServeFile.$inject = ['config'] |
| |
| function createWebServer (injector, config) { |
| common.initializeMimeTypes(config) |
| |
| const proxyMiddlewareInstance = injector.invoke(proxyMiddleware.create) |
| |
| log.debug('Instantiating middleware') |
| const handler = connect() |
| |
| if (config.beforeMiddleware) { |
| config.beforeMiddleware.forEach((middleware) => handler.use(injector.get('middleware:' + middleware))) |
| } |
| |
| handler.use(injector.invoke(runnerMiddleware.create)) |
| handler.use(injector.invoke(stopperMiddleware.create)) |
| handler.use(injector.invoke(karmaMiddleware.create)) |
| handler.use(injector.invoke(sourceFilesMiddleware.create)) |
| // TODO(vojta): extract the proxy into a plugin |
| handler.use(proxyMiddlewareInstance) |
| // TODO(vojta): remove, this is only here because of karma-dart |
| // we need a better way of custom handlers |
| handler.use(injector.invoke(createCustomHandler)) |
| |
| if (config.middleware) { |
| config.middleware.forEach((middleware) => handler.use(injector.get('middleware:' + middleware))) |
| } |
| |
| handler.use((request, response) => common.serve404(response, request.url)) |
| |
| let serverClass = http |
| const serverArguments = [handler] |
| |
| if (config.protocol === 'https:') { |
| serverClass = https |
| serverArguments.unshift(config.httpsServerOptions || {}) |
| } |
| |
| if (config.httpModule) { |
| serverClass = config.httpModule |
| } |
| |
| const server = serverClass.createServer.apply(null, serverArguments) |
| |
| server.on('upgrade', function (req, socket, head) { |
| log.debug(`upgrade ${req.url}`) |
| proxyMiddlewareInstance.upgrade(req, socket, head) |
| }) |
| |
| return server |
| } |
| |
| createWebServer.$inject = ['injector', 'config'] |
| |
| module.exports = { |
| createWebServer, |
| createServeFile, |
| createServeStaticFile, |
| createFilesPromise, |
| createReadFilePromise |
| } |