(app, supportedAppExtensions)
| 122 | } |
| 123 | |
| 124 | async function configureApp (app, supportedAppExtensions) { |
| 125 | if (!_.isString(app)) { |
| 126 | // immediately shortcircuit if not given an app |
| 127 | return; |
| 128 | } |
| 129 | if (!_.isArray(supportedAppExtensions)) { |
| 130 | supportedAppExtensions = [supportedAppExtensions]; |
| 131 | } |
| 132 | |
| 133 | let newApp = app; |
| 134 | let shouldUnzipApp = false; |
| 135 | let archiveHash = null; |
| 136 | const remoteAppProps = { |
| 137 | lastModified: null, |
| 138 | immutable: false, |
| 139 | maxAge: null, |
| 140 | }; |
| 141 | const {protocol, pathname} = url.parse(newApp); |
| 142 | const isUrl = ['http:', 'https:'].includes(protocol); |
| 143 | |
| 144 | return await APPLICATIONS_CACHE_GUARD.acquire(app, async () => { |
| 145 | if (isUrl) { |
| 146 | // Use the app from remote URL |
| 147 | logger.info(`Using downloadable app '${newApp}'`); |
| 148 | const headers = await retrieveHeaders(newApp); |
| 149 | if (!_.isEmpty(headers)) { |
| 150 | if (headers['last-modified']) { |
| 151 | remoteAppProps.lastModified = new Date(headers['last-modified']); |
| 152 | } |
| 153 | logger.debug(`Last-Modified: ${headers['last-modified']}`); |
| 154 | if (headers['cache-control']) { |
| 155 | remoteAppProps.immutable = /\bimmutable\b/i.test(headers['cache-control']); |
| 156 | const maxAgeMatch = /\bmax-age=(\d+)\b/i.exec(headers['cache-control']); |
| 157 | if (maxAgeMatch) { |
| 158 | remoteAppProps.maxAge = parseInt(maxAgeMatch[1], 10); |
| 159 | } |
| 160 | } |
| 161 | logger.debug(`Cache-Control: ${headers['cache-control']}`); |
| 162 | } |
| 163 | const cachedPath = getCachedApplicationPath(app, remoteAppProps); |
| 164 | if (cachedPath) { |
| 165 | if (await fs.exists(cachedPath)) { |
| 166 | logger.info(`Reusing previously downloaded application at '${cachedPath}'`); |
| 167 | return verifyAppExtension(cachedPath, supportedAppExtensions); |
| 168 | } |
| 169 | logger.info(`The application at '${cachedPath}' does not exist anymore. Deleting it from the cache`); |
| 170 | APPLICATIONS_CACHE.del(app); |
| 171 | } |
| 172 | |
| 173 | let fileName = null; |
| 174 | const basename = fs.sanitizeName(path.basename(decodeURIComponent(pathname)), { |
| 175 | replacement: SANITIZE_REPLACEMENT |
| 176 | }); |
| 177 | const extname = path.extname(basename); |
| 178 | // to determine if we need to unzip the app, we have a number of places |
| 179 | // to look: content type, content disposition, or the file extension |
| 180 | if (ZIP_EXTS.includes(extname)) { |
| 181 | fileName = basename; |
no test coverage detected
searching dependent graphs…