[6a3a178] | 1 | 'use strict'
|
---|
| 2 |
|
---|
| 3 | const querystring = require('querystring')
|
---|
| 4 | const common = require('./common')
|
---|
| 5 |
|
---|
| 6 | const log = require('../logger').create('middleware:source-files')
|
---|
| 7 |
|
---|
| 8 | function findByPath (files, path) {
|
---|
| 9 | return Array.from(files).find((file) => file.path === path)
|
---|
| 10 | }
|
---|
| 11 |
|
---|
| 12 | function composeUrl (url, basePath, urlRoot) {
|
---|
| 13 | return url
|
---|
| 14 | .replace(urlRoot, '/')
|
---|
| 15 | .replace(/\?.*$/, '')
|
---|
| 16 | .replace(/^\/absolute/, '')
|
---|
| 17 | .replace(/^\/base/, basePath)
|
---|
| 18 | }
|
---|
| 19 |
|
---|
| 20 | // Source Files middleware is responsible for serving all the source files under the test.
|
---|
| 21 | function createSourceFilesMiddleware (filesPromise, serveFile, basePath, urlRoot) {
|
---|
| 22 | return function (request, response, next) {
|
---|
| 23 | const requestedFilePath = composeUrl(request.url, basePath, urlRoot)
|
---|
| 24 | // When a path contains HTML-encoded characters (e.g %2F used by Jenkins for branches with /)
|
---|
| 25 | const requestedFilePathUnescaped = composeUrl(querystring.unescape(request.url), basePath, urlRoot)
|
---|
| 26 |
|
---|
| 27 | request.pause()
|
---|
| 28 |
|
---|
| 29 | log.debug(`Requesting ${request.url}`)
|
---|
| 30 | log.debug(`Fetching ${requestedFilePath}`)
|
---|
| 31 |
|
---|
| 32 | return filesPromise.then(function (files) {
|
---|
| 33 | // TODO(vojta): change served to be a map rather then an array
|
---|
| 34 | const file = findByPath(files.served, requestedFilePath) || findByPath(files.served, requestedFilePathUnescaped)
|
---|
| 35 | const rangeHeader = request.headers.range
|
---|
| 36 |
|
---|
| 37 | if (file) {
|
---|
| 38 | const acceptEncodingHeader = request.headers['accept-encoding']
|
---|
| 39 | const matchedEncoding = Object.keys(file.encodings).find(
|
---|
| 40 | (encoding) => new RegExp(`(^|.*, ?)${encoding}(,|$)`).test(acceptEncodingHeader)
|
---|
| 41 | )
|
---|
| 42 | const content = file.encodings[matchedEncoding] || file.content
|
---|
| 43 |
|
---|
| 44 | serveFile(file.contentPath || file.path, rangeHeader, response, function () {
|
---|
| 45 | if (/\?\w+/.test(request.url)) {
|
---|
| 46 | common.setHeavyCacheHeaders(response) // files with timestamps - cache one year, rely on timestamps
|
---|
| 47 | } else {
|
---|
| 48 | common.setNoCacheHeaders(response) // without timestamps - no cache (debug)
|
---|
| 49 | }
|
---|
| 50 | if (matchedEncoding) {
|
---|
| 51 | response.setHeader('Content-Encoding', matchedEncoding)
|
---|
| 52 | }
|
---|
| 53 | }, content, file.doNotCache)
|
---|
| 54 | } else {
|
---|
| 55 | next()
|
---|
| 56 | }
|
---|
| 57 |
|
---|
| 58 | request.resume()
|
---|
| 59 | })
|
---|
| 60 | }
|
---|
| 61 | }
|
---|
| 62 |
|
---|
| 63 | createSourceFilesMiddleware.$inject = [
|
---|
| 64 | 'filesPromise', 'serveFile', 'config.basePath', 'config.urlRoot'
|
---|
| 65 | ]
|
---|
| 66 |
|
---|
| 67 | exports.create = createSourceFilesMiddleware
|
---|