1 | 'use strict'
|
2 |
|
3 | const { dirname, join } = require('path')
|
4 | const { createWriteStream } = require('fs')
|
5 | const { mkdir, unlink } = require('fs').promises
|
6 | const { capture } = require('reserve')
|
7 | const { getOutput } = require('./output')
|
8 |
|
9 | module.exports = job => {
|
10 | if (job.disableUi5) {
|
11 | return []
|
12 | }
|
13 |
|
14 | const [, hostName] = /https?:\/\/([^/]*)/.exec(job.ui5)
|
15 | const [, version] = /(\d+\.\d+\.\d+)?$/.exec(job.ui5)
|
16 | const cacheBase = join(job.cache || '', hostName.replace(':', '_'), version || '')
|
17 | const match = /\/((?:test-)?resources\/.*)/
|
18 | const ifCacheEnabled = (request, url, match) => job.cache ? match : false
|
19 | const uncachable = {}
|
20 | const cachingInProgress = {}
|
21 |
|
22 | const mappings = [{
|
23 | |
24 |
|
25 |
|
26 |
|
27 | match,
|
28 | 'if-match': ifCacheEnabled,
|
29 | custom: async (request, response, path) => {
|
30 | if (uncachable[path]) {
|
31 | response.writeHead(404)
|
32 | response.end()
|
33 | return
|
34 | }
|
35 | const cachingPromise = cachingInProgress[path]
|
36 |
|
37 | if (cachingPromise) {
|
38 | await cachingPromise
|
39 | }
|
40 | }
|
41 | }, {
|
42 |
|
43 | match,
|
44 | 'if-match': ifCacheEnabled,
|
45 | file: join(cacheBase, '$1'),
|
46 | 'ignore-if-not-found': true
|
47 | }, {
|
48 |
|
49 | method: 'GET',
|
50 | match,
|
51 | 'if-match': ifCacheEnabled,
|
52 | custom: async (request, response, path) => {
|
53 | const filePath = /([^?#]+)/.exec(unescape(path))[1]
|
54 | const cachePath = join(cacheBase, filePath)
|
55 | const cacheFolder = dirname(cachePath)
|
56 | await mkdir(cacheFolder, { recursive: true })
|
57 | if (cachingInProgress[path]) {
|
58 | return request.url
|
59 | }
|
60 | const file = createWriteStream(cachePath)
|
61 | cachingInProgress[path] = capture(response, file)
|
62 | .catch(reason => {
|
63 | file.end()
|
64 | uncachable[path] = true
|
65 | if (response.statusCode !== 404) {
|
66 | getOutput(job).failedToCacheUI5resource(path, response.statusCode)
|
67 | }
|
68 | return unlink(cachePath)
|
69 | })
|
70 | .then(() => {
|
71 | delete cachingInProgress[path]
|
72 | })
|
73 | }
|
74 | }, {
|
75 |
|
76 | method: ['GET', 'HEAD'],
|
77 | match,
|
78 | url: `${job.ui5}/$1`,
|
79 | 'ignore-unverifiable-certificate': true
|
80 | }]
|
81 |
|
82 | job.libs.forEach(({ relative, source }) => {
|
83 | mappings.unshift({
|
84 | match: new RegExp(`\\/resources\\/${relative.replace(/\//g, '\\/')}(.*)`),
|
85 | file: join(source, '$1'),
|
86 | 'ignore-if-not-found': true
|
87 | })
|
88 | })
|
89 |
|
90 | return mappings
|
91 | }
|