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
|
---|