source_files.js 2.1 KB

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