chore: 初始化项目仓库
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,8 @@
|
||||
export default defineEventHandler(async () => {
|
||||
try {
|
||||
const raw = await $fetch<string>('https://keai.icu/apiwyy/api', { responseType: 'text' })
|
||||
return JSON.parse(raw as string)
|
||||
} catch {
|
||||
return null
|
||||
}
|
||||
})
|
||||
@@ -0,0 +1,39 @@
|
||||
import { readFile } from 'node:fs/promises'
|
||||
import { resolve, extname } from 'node:path'
|
||||
import { existsSync } from 'node:fs'
|
||||
|
||||
const MIME: Record<string, string> = {
|
||||
'.jpg': 'image/jpeg',
|
||||
'.jpeg': 'image/jpeg',
|
||||
'.png': 'image/png',
|
||||
'.gif': 'image/gif',
|
||||
'.webp': 'image/webp',
|
||||
'.avif': 'image/avif',
|
||||
'.svg': 'image/svg+xml',
|
||||
}
|
||||
|
||||
export default defineEventHandler(async (event) => {
|
||||
const url = getRequestURL(event)
|
||||
const pathMatch = url.pathname.match(/^\/posts\/([a-z0-9-]+)\/img\/(.+)$/)
|
||||
if (!pathMatch) return
|
||||
|
||||
const [, slug, filename] = pathMatch
|
||||
|
||||
// 防止路径遍历攻击
|
||||
if (filename.includes('..') || filename.includes('/') || filename.includes('\\')) {
|
||||
throw createError({ statusCode: 400 })
|
||||
}
|
||||
|
||||
const ext = extname(filename).toLowerCase()
|
||||
if (!MIME[ext]) return
|
||||
|
||||
const filePath = resolve('content/posts', slug, 'img', filename)
|
||||
if (!existsSync(filePath)) {
|
||||
throw createError({ statusCode: 404 })
|
||||
}
|
||||
|
||||
const data = await readFile(filePath)
|
||||
setResponseHeader(event, 'content-type', MIME[ext])
|
||||
setResponseHeader(event, 'cache-control', 'public, max-age=31536000')
|
||||
return data
|
||||
})
|
||||
Reference in New Issue
Block a user