Last active 1744868788

利用CF Worker实现一个每日bing一图接口API,可以直接用作图片数据。

worker.js Raw
1// 利用api.nsmao.net实现的bing接口
2const API_KEY = "ajdlfklahweufbrffbhjefjfsmd,shj" // 自行申请API
3const CACHE_TTL = 36000 // 10 小时
4
5export default {
6 async fetch(request, env, ctx) {
7 const { pathname } = new URL(request.url)
8
9 // 首页说明
10 if (pathname === "/") {
11 return new Response(
12 "🚀 本服务用于代理并缓存 https://api.nsmao.net 的图片接口,保护密钥不泄露。\n" +
13 "当前支持:/api/360bz 与 /api/bing 接口,图片将自动缓存10小时以减少请求压力。",
14 {
15 status: 200,
16 headers: { "Content-Type": "text/plain; charset=utf-8" }
17 }
18 )
19 }
20
21 // 360bz 图片接口
22 if (pathname === "/api/360bz") {
23 return await cachedProxyImage(
24 "360bz",
25 "https://api.nsmao.net/api/360bz/query",
26 { key: API_KEY },
27 "url",
28 ctx
29 )
30 }
31
32 // bing 图片接口
33 if (pathname === "/api/bing") {
34 return await cachedProxyImage(
35 "bing",
36 "https://api.nsmao.net/api/bing/query",
37 { key: API_KEY, type: "json" },
38 "image_url",
39 ctx
40 )
41 }
42
43 return new Response("Not found", { status: 404 })
44 }
45}
46
47async function cachedProxyImage(
48 cacheKey,
49 apiUrl,
50 queryParams,
51 imageField,
52 ctx
53) {
54 const cache = caches.default
55 const cacheRequest = new Request(`https://cache.nsmao/${cacheKey}`)
56 const cached = await cache.match(cacheRequest)
57
58 if (cached) {
59 const cachedWithHeader = new Response(cached.body, cached)
60 cachedWithHeader.headers.set("X-Cache-Status", "HIT")
61 return cachedWithHeader
62 }
63
64 // 构造真实请求 URL
65 const url = new URL(apiUrl)
66 Object.entries(queryParams).forEach(([k, v]) => url.searchParams.set(k, v))
67
68 const headers = {
69 "Accept": "application/json",
70 "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",
71 "Referer": "https://www.google.com/",
72 "Accept-Language": "zh-CN,zh;q=0.9,en;q=0.8"
73 }
74
75 // 请求 nsmao 接口
76 const apiResp = await fetch(url.toString(), { method: "GET", headers })
77 if (!apiResp.ok) {
78 return new Response("Failed to fetch API", { status: 502 })
79 }
80
81 const json = await apiResp.json()
82 const imageUrl = json?.data?.[imageField]
83
84 if (!imageUrl) {
85 return new Response("Image URL not found in API response", { status: 500 })
86 }
87
88 // 请求图片
89 const imageResp = await fetch(imageUrl, {
90 headers: {
91 ...headers,
92 "Accept": "image/*"
93 }
94 })
95
96 const contentType = imageResp.headers.get("content-type") || "image/jpeg"
97 const response = new Response(imageResp.body, {
98 headers: {
99 "Content-Type": contentType,
100 "Cache-Control": `public, max-age=${CACHE_TTL}`,
101 "X-Cache-Status": "MISS"
102 }
103 })
104
105 // 后台写入缓存
106 ctx.waitUntil(cache.put(cacheRequest, response.clone()))
107 return response
108}
109