38 lines
1.0 KiB
TypeScript
38 lines
1.0 KiB
TypeScript
import { existsSync, readFileSync } from 'node:fs'
|
|||
|
|
import { join } from 'node:path'
|
||
|
|
import { defineEventHandler, getRequestURL, send, setResponseHeader } from 'h3'
|
||
|
|
|
||
|
|
const FAVICON_PATHS = [
|
||
|
|
'/favicon.ico',
|
||
|
|
'/favicon.png',
|
||
|
|
'/landing/favicon.ico',
|
||
|
|
'/landing/favicon.png',
|
||
|
|
]
|
||
|
|
|
||
|
|
function resolveFaviconFile() {
|
||
|
|
const candidates = [
|
||
|
|
join(process.cwd(), 'src', 'public', 'favicon.png'),
|
||
|
|
join(process.cwd(), 'public', 'favicon.png'),
|
||
|
|
]
|
||
|
|
for (const path of candidates) {
|
||
|
|
if (existsSync(path)) return path
|
||
|
|
}
|
||
|
|
return null
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* سرو مستقیم favicon تا درخواستهای روت و /landing
|
||
|
|
* وارد Vue Router نشوند و هشدار No match ندهند.
|
||
|
|
*/
|
||
|
|
export default defineEventHandler((event) => {
|
||
|
|
const { pathname } = getRequestURL(event)
|
||
|
|
if (!FAVICON_PATHS.includes(pathname)) return
|
||
|
|
|
||
|
|
const file = resolveFaviconFile()
|
||
|
|
if (!file) return
|
||
|
|
|
||
|
|
setResponseHeader(event, 'Content-Type', 'image/png')
|
||
|
|
setResponseHeader(event, 'Cache-Control', 'public, max-age=86400')
|
||
|
|
return send(event, readFileSync(file))
|
||
|
|
})
|