mirror of
https://github.com/direct-img/direct-img.link.git
synced 2026-03-17 03:01:01 +00:00
Fix: Move body consumption inside fetchImage timeout scope
This commit is contained in:
@@ -72,18 +72,14 @@ export async function onRequest(context) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 4. Robust Fetch: Try results until one works
|
// 4. Robust Fetch: Try results until one works
|
||||||
let imgResponse = null;
|
let imgResult = null;
|
||||||
let finalContentType = "image/jpeg";
|
|
||||||
|
|
||||||
for (const imgUrl of imageUrls) {
|
for (const imgUrl of imageUrls) {
|
||||||
imgResponse = await fetchImage(imgUrl);
|
imgResult = await fetchImage(imgUrl);
|
||||||
if (imgResponse) {
|
if (imgResult) break;
|
||||||
finalContentType = imgResponse.headers.get("content-type") || "image/jpeg";
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!imgResponse) {
|
if (!imgResult) {
|
||||||
context.waitUntil(notify(env, {
|
context.waitUntil(notify(env, {
|
||||||
title: "Fetch Error (502)",
|
title: "Fetch Error (502)",
|
||||||
message: `All sources failed for: ${query}`,
|
message: `All sources failed for: ${query}`,
|
||||||
@@ -93,7 +89,7 @@ export async function onRequest(context) {
|
|||||||
return jsonResponse(502, { error: "Failed to fetch image from all available sources" });
|
return jsonResponse(502, { error: "Failed to fetch image from all available sources" });
|
||||||
}
|
}
|
||||||
|
|
||||||
const imgBuffer = await imgResponse.arrayBuffer();
|
const { buffer: imgBuffer, contentType: finalContentType } = imgResult;
|
||||||
|
|
||||||
// 5. Store in R2
|
// 5. Store in R2
|
||||||
await env.R2_IMAGES.put(r2Key, imgBuffer, {
|
await env.R2_IMAGES.put(r2Key, imgBuffer, {
|
||||||
@@ -180,7 +176,7 @@ async function braveImageSearch(query, apiKey) {
|
|||||||
async function fetchImage(imageUrl) {
|
async function fetchImage(imageUrl) {
|
||||||
try {
|
try {
|
||||||
const controller = new AbortController();
|
const controller = new AbortController();
|
||||||
const timeoutId = setTimeout(() => controller.abort(), 5000); // 5s timeout per image
|
const timeoutId = setTimeout(() => controller.abort(), 5000);
|
||||||
|
|
||||||
const res = await fetch(imageUrl, {
|
const res = await fetch(imageUrl, {
|
||||||
headers: {
|
headers: {
|
||||||
@@ -192,18 +188,32 @@ async function fetchImage(imageUrl) {
|
|||||||
cf: { cacheTtl: 0 },
|
cf: { cacheTtl: 0 },
|
||||||
});
|
});
|
||||||
|
|
||||||
|
if (!res.ok) {
|
||||||
clearTimeout(timeoutId);
|
clearTimeout(timeoutId);
|
||||||
|
return null;
|
||||||
if (!res.ok) return null;
|
}
|
||||||
|
|
||||||
const ct = res.headers.get("content-type") || "";
|
const ct = res.headers.get("content-type") || "";
|
||||||
if (!ct.startsWith("image/")) return null;
|
if (!ct.startsWith("image/")) {
|
||||||
|
clearTimeout(timeoutId);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
// Check for massive files that might crash the worker (> 10MB)
|
// Check for massive files that might crash the worker (> 10MB)
|
||||||
const size = res.headers.get("content-length");
|
const size = res.headers.get("content-length");
|
||||||
if (size && parseInt(size) > 10485760) return null;
|
if (size && parseInt(size) > 10485760) {
|
||||||
|
clearTimeout(timeoutId);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
return res;
|
// Consume body inside timeout scope so abort covers the full download
|
||||||
|
const buffer = await res.arrayBuffer();
|
||||||
|
clearTimeout(timeoutId);
|
||||||
|
|
||||||
|
// Final size check for chunked responses without content-length
|
||||||
|
if (buffer.byteLength > 10485760) return null;
|
||||||
|
|
||||||
|
return { buffer, contentType: ct };
|
||||||
} catch {
|
} catch {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user