hulai-website/server/api/image-proxy.get.js
刘涛 8832762e51 fix: 修复首页空白、小红书/游记封面图、定制页二维码
1. 首页大面积空白:useScrollReveal 添加 MutationObserver,
   确保异步子组件的 .reveal 元素也能触发入场动画

2. 小红书/游记封面图不显示:
   - 小红书 CDN 签名链接过期+防盗链,全部下载到本地
   - 新增 download-covers.mjs 脚本批量下载封面
   - 新增 useImageProxy composable 转换外部 URL
   - 页面 img 标签添加 referrerpolicy="no-referrer"
   - 管理端保存时自动下载外部封面图到本地
   - 种子数据更新为本地路径

3. 定制页微信号文字替换为二维码图片

4. prerender 路由添加 /xiaohongshu 和 /youji

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-25 15:37:58 +08:00

60 行
1.7 KiB
JavaScript

此文件含有模棱两可的 Unicode 字符

此文件含有可能会与其他字符混淆的 Unicode 字符。 如果您是想特意这样的,可以安全地忽略该警告。 使用 Escape 按钮显示他们。

/**
* 图片代理接口
* 用于加载有防盗链保护的外部图片(如小红书 CDN
*
* 用法: /api/image-proxy?url=https://sns-webpic-qc.xhscdn.com/...
*
* 安全限制:只允许代理白名单域名的图片
*/
export default defineEventHandler(async (event) => {
const { url } = getQuery(event)
if (!url) {
throw createError({ statusCode: 400, message: '缺少 url 参数' })
}
// 白名单:只允许代理指定域名的图片
const allowedHosts = [
'sns-webpic-qc.xhscdn.com',
'ci.xiaohongshu.com',
'image.xiaohongshu.com',
'picx.zhimg.com',
]
let parsedUrl
try {
parsedUrl = new URL(url)
} catch {
throw createError({ statusCode: 400, message: '无效的 URL' })
}
if (!allowedHosts.includes(parsedUrl.hostname)) {
throw createError({ statusCode: 403, message: '该域名不在白名单中' })
}
try {
const response = await fetch(url, {
headers: {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36',
'Accept': 'image/webp,image/apng,image/*,*/*;q=0.8',
},
})
if (!response.ok) {
throw createError({ statusCode: response.status, message: '图片获取失败' })
}
const contentType = response.headers.get('content-type') || 'image/jpeg'
const buffer = await response.arrayBuffer()
setHeader(event, 'Content-Type', contentType)
setHeader(event, 'Cache-Control', 'public, max-age=86400, s-maxage=604800')
setHeader(event, 'Access-Control-Allow-Origin', '*')
return Buffer.from(buffer)
} catch (err) {
if (err.statusCode) throw err
throw createError({ statusCode: 502, message: '图片代理请求失败' })
}
})