worker.js
· 2.9 KiB · JavaScript
Raw
// 利用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
}
1 | // 利用api.nsmao.net实现的bing接口 |
2 | const API_KEY = "ajdlfklahweufbrffbhjefjfsmd,shj" // 自行申请API |
3 | const CACHE_TTL = 36000 // 10 小时 |
4 | |
5 | export 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 | |
47 | async 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 |