// 利用api.nsmao.net实现的bing接口 const API_KEY = "ajdlfklahweufbrffbhjefjfsmd,shj" // 自行申请API const CACHE_TTL = 36000 // 10 小时 export default { async fetch(request, env, ctx) { const { pathname } = new URL(request.url) // 首页说明 if (pathname === "/") { return new Response( "🚀 本服务用于代理并缓存 https://api.nsmao.net 的图片接口,保护密钥不泄露。\n" + "当前支持:/api/360bz 与 /api/bing 接口,图片将自动缓存10小时以减少请求压力。", { status: 200, headers: { "Content-Type": "text/plain; charset=utf-8" } } ) } // 360bz 图片接口 if (pathname === "/api/360bz") { return await cachedProxyImage( "360bz", "https://api.nsmao.net/api/360bz/query", { key: API_KEY }, "url", ctx ) } // bing 图片接口 if (pathname === "/api/bing") { return await cachedProxyImage( "bing", "https://api.nsmao.net/api/bing/query", { key: API_KEY, type: "json" }, "image_url", ctx ) } return new Response("Not found", { status: 404 }) } } async function cachedProxyImage( cacheKey, apiUrl, queryParams, imageField, ctx ) { const cache = caches.default const cacheRequest = new Request(`https://cache.nsmao/${cacheKey}`) const cached = await cache.match(cacheRequest) if (cached) { const cachedWithHeader = new Response(cached.body, cached) cachedWithHeader.headers.set("X-Cache-Status", "HIT") return cachedWithHeader } // 构造真实请求 URL const url = new URL(apiUrl) Object.entries(queryParams).forEach(([k, v]) => url.searchParams.set(k, v)) const headers = { "Accept": "application/json", "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/123.0.0.0 Safari/537.36", "Referer": "https://www.google.com/", "Accept-Language": "zh-CN,zh;q=0.9,en;q=0.8" } // 请求 nsmao 接口 const apiResp = await fetch(url.toString(), { method: "GET", headers }) if (!apiResp.ok) { return new Response("Failed to fetch API", { status: 502 }) } const json = await apiResp.json() const imageUrl = json?.data?.[imageField] if (!imageUrl) { return new Response("Image URL not found in API response", { status: 500 }) } // 请求图片 const imageResp = await fetch(imageUrl, { headers: { ...headers, "Accept": "image/*" } }) const contentType = imageResp.headers.get("content-type") || "image/jpeg" const response = new Response(imageResp.body, { headers: { "Content-Type": contentType, "Cache-Control": `public, max-age=${CACHE_TTL}`, "X-Cache-Status": "MISS" } }) // 后台写入缓存 ctx.waitUntil(cache.put(cacheRequest, response.clone())) return response }