| 'use strict' |
| |
| const querystring = require('querystring') |
| const common = require('./common') |
| |
| const log = require('../logger').create('middleware:source-files') |
| |
| function findByPath (files, path) { |
| return Array.from(files).find((file) => file.path === path) |
| } |
| |
| function composeUrl (url, basePath, urlRoot) { |
| return url |
| .replace(urlRoot, '/') |
| .replace(/\?.*$/, '') |
| .replace(/^\/absolute/, '') |
| .replace(/^\/base/, basePath) |
| } |
| |
| // Source Files middleware is responsible for serving all the source files under the test. |
| function createSourceFilesMiddleware (filesPromise, serveFile, basePath, urlRoot) { |
| return function (request, response, next) { |
| const requestedFilePath = composeUrl(request.url, basePath, urlRoot) |
| // When a path contains HTML-encoded characters (e.g %2F used by Jenkins for branches with /) |
| const requestedFilePathUnescaped = composeUrl(querystring.unescape(request.url), basePath, urlRoot) |
| |
| request.pause() |
| |
| log.debug(`Requesting ${request.url}`) |
| log.debug(`Fetching ${requestedFilePath}`) |
| |
| return filesPromise.then(function (files) { |
| // TODO(vojta): change served to be a map rather then an array |
| const file = findByPath(files.served, requestedFilePath) || findByPath(files.served, requestedFilePathUnescaped) |
| const rangeHeader = request.headers['range'] |
| |
| if (file) { |
| const acceptEncodingHeader = request.headers['accept-encoding'] |
| const matchedEncoding = Object.keys(file.encodings).find( |
| (encoding) => new RegExp(`(^|.*, ?)${encoding}(,|$)`).test(acceptEncodingHeader) |
| ) |
| const content = file.encodings[matchedEncoding] || file.content |
| |
| serveFile(file.contentPath || file.path, rangeHeader, response, function () { |
| if (/\?\w+/.test(request.url)) { |
| common.setHeavyCacheHeaders(response) // files with timestamps - cache one year, rely on timestamps |
| } else { |
| common.setNoCacheHeaders(response) // without timestamps - no cache (debug) |
| } |
| if (matchedEncoding) { |
| response.setHeader('Content-Encoding', matchedEncoding) |
| } |
| }, content, file.doNotCache) |
| } else { |
| next() |
| } |
| |
| request.resume() |
| }) |
| } |
| } |
| |
| createSourceFilesMiddleware.$inject = [ |
| 'filesPromise', 'serveFile', 'config.basePath', 'config.urlRoot' |
| ] |
| |
| exports.create = createSourceFilesMiddleware |