avoid cache problems with favicon

Massimo Melina committed Mar 3, 2024 at 12:36 UTC ae7c7d90a61bda4a0414fbd2a42f0a533fcddaf5
3 files changed +10 -4
src/adminApis.ts
+1 -1
@@ -10,7 +10,7 @@ import {
10 HFS_STARTED,
11 IS_WINDOWS,
12 VERSION,
13 - HTTP_UNAUTHORIZED, HTTP_NOT_FOUND, HTTP_BAD_REQUEST, HTTP_SERVER_ERROR, HTTP_FORBIDDEN
13 + HTTP_UNAUTHORIZED, HTTP_BAD_REQUEST, HTTP_SERVER_ERROR, HTTP_FORBIDDEN
14 } from './const'
15 import vfsApis from './api.vfs'
16 import accountsApis from './api.accounts'
src/serveGuiAndSharedFiles.ts
+1 -1
@@ -52,7 +52,7 @@ export const serveGuiAndSharedFiles: Koa.Middleware = async (ctx, next) => {
52 }
53 return
54 }
55 - if (ctx.originalUrl === '/favicon.ico' && favicon.get()) // originalUrl to not be subject to changes (vhosting plugin)
55 + if (/^\/favicon.ico(\??.*)/.test(ctx.originalUrl) && favicon.get()) // originalUrl to not be subject to changes (vhosting plugin)
56 return serveFile(ctx, favicon.get())
57 let node = await urlToNode(path, ctx)
58 if (!node)
src/serveGuiFiles.ts
+8 -2
@@ -9,7 +9,7 @@ import { getPluginConfigFields, getPluginInfo, mapPlugins, pluginsConfig } from
9 import { refresh_session } from './api.auth'
10 import { ApiError } from './apiMiddleware'
11 import { join, extname } from 'path'
12 -import { CFG, FRONTEND_OPTIONS, getOrSet, newObj, onlyTruthy } from './misc'
12 +import { CFG, debounceAsync, FRONTEND_OPTIONS, getOrSet, newObj, onlyTruthy, repeat } from './misc'
13 import { favicon, title } from './adminApis'
14 import { subscribe } from 'valtio/vanilla'
15 import { customHtmlState, getSection } from './customHtml'
@@ -64,6 +64,11 @@ function adjustBundlerLinks(ctx: Koa.Context, uri: string, data: string | Buffer
64 : String(data).replace(/((?:import[ (]| from )['"])\//g, `$1${ctx.state.revProxyPath}${uri}`)
65 }
66
67 +const getFaviconTimestamp = debounceAsync(async () => {
68 + const f = favicon.get()
69 + return !f ? 0 : fs.stat(f).then(x => x?.mtimeMs || 0, () => 0)
70 +}, 0, { retain: 5_000 })
71 +
72 async function treatIndex(ctx: Koa.Context, filesUri: string, body: string) {
73 const session = await refresh_session({}, ctx)
74 ctx.set('etag', '')
@@ -83,13 +88,14 @@ async function treatIndex(ctx: Koa.Context, filesUri: string, body: string) {
88 configs = getPluginInfo(name).onFrontendConfig?.(configs) || configs
89 return !_.isEmpty(configs) && [name, configs]
90 })))
91 + const timestamp = await getFaviconTimestamp()
92 const lang = await getLangData(ctx)
93 let ret = body
94 .replace(/((?:src|href) *= *['"])\/?(?!([a-z]+:\/)?\/)/g, '$1' + ctx.state.revProxyPath + filesUri)
95 .replace('<head>', () => `<head>
96 ${!isFrontend ? '' : `
97 <title>${title.get()}</title>
92 - <link rel="shortcut icon" href="${favicon.get() ? '/favicon.ico' : '#'}" />
98 + <link rel="shortcut icon" href="/favicon.ico?${timestamp}" />
99 `}
100 <script>
101 HFS = ${JSON.stringify({