fix: bypass image proxy for browser image loads
This commit is contained in:
parent
166cc184d1
commit
e1e4c205e1
@ -90,6 +90,80 @@ function buildEtag(input: string): string {
|
||||
return `"${crypto.createHash("sha1").update(input).digest("hex")}"`;
|
||||
}
|
||||
|
||||
function isBrowserImageRequest(request: NextRequest): boolean {
|
||||
return request.headers.get("sec-fetch-dest") === "image";
|
||||
}
|
||||
|
||||
function isAliyunOssHost(hostname: string): boolean {
|
||||
const normalized = hostname.toLowerCase();
|
||||
return normalized.endsWith(".aliyuncs.com") && normalized.includes(".oss-");
|
||||
}
|
||||
|
||||
function appendAliyunImageProcess(
|
||||
target: URL,
|
||||
width: number | null,
|
||||
quality: number | null,
|
||||
requestedFormat: string | null
|
||||
): URL | null {
|
||||
if (target.searchParams.has("x-oss-process")) {
|
||||
return width || quality || requestedFormat ? null : target;
|
||||
}
|
||||
|
||||
const processSteps: string[] = ["image"];
|
||||
if (width) {
|
||||
processSteps.push(`resize,w_${width}`);
|
||||
}
|
||||
|
||||
if (quality) {
|
||||
processSteps.push(`quality,q_${quality}`);
|
||||
}
|
||||
|
||||
if (requestedFormat) {
|
||||
const format = requestedFormat === "jpeg" ? "jpg" : requestedFormat;
|
||||
if (format !== "webp" && format !== "jpg" && format !== "png") {
|
||||
return null;
|
||||
}
|
||||
processSteps.push(`format,${format}`);
|
||||
}
|
||||
|
||||
const redirected = new URL(target.toString());
|
||||
redirected.searchParams.set("x-oss-process", processSteps.join("/"));
|
||||
return redirected;
|
||||
}
|
||||
|
||||
function resolveDirectImageTarget(
|
||||
request: NextRequest,
|
||||
target: URL,
|
||||
width: number | null,
|
||||
requestedQuality: number | null,
|
||||
requestedFormat: string | null
|
||||
): URL | null {
|
||||
if (!isBrowserImageRequest(request)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const hasTransformRequest = Boolean(width || requestedQuality || requestedFormat);
|
||||
if (!hasTransformRequest) {
|
||||
return target;
|
||||
}
|
||||
|
||||
if (isAliyunOssHost(target.hostname)) {
|
||||
return appendAliyunImageProcess(target, width, requestedQuality, requestedFormat);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
function redirectToDirectImage(target: URL): NextResponse {
|
||||
const response = NextResponse.redirect(target, 307);
|
||||
response.headers.set(
|
||||
"Cache-Control",
|
||||
"public, max-age=31536000, immutable, stale-while-revalidate=86400"
|
||||
);
|
||||
response.headers.set("X-Image-Proxy-Bypass", "direct-image-request");
|
||||
return response;
|
||||
}
|
||||
|
||||
export async function GET(request: NextRequest) {
|
||||
const { searchParams } = request.nextUrl;
|
||||
const rawUrl = (searchParams.get("url") || "").trim();
|
||||
@ -116,8 +190,20 @@ export async function GET(request: NextRequest) {
|
||||
const requestedQuality = parsePositiveInt(searchParams.get("q"));
|
||||
const width = requestedWidth ? clamp(requestedWidth, MIN_WIDTH, MAX_WIDTH) : null;
|
||||
const quality = requestedQuality ? clamp(requestedQuality, MIN_QUALITY, MAX_QUALITY) : DEFAULT_QUALITY;
|
||||
const directQuality = requestedQuality ? clamp(requestedQuality, MIN_QUALITY, MAX_QUALITY) : null;
|
||||
const requestedFormat = searchParams.get("f");
|
||||
|
||||
const directImageTarget = resolveDirectImageTarget(
|
||||
request,
|
||||
target,
|
||||
width,
|
||||
directQuality,
|
||||
requestedFormat
|
||||
);
|
||||
if (directImageTarget) {
|
||||
return redirectToDirectImage(directImageTarget);
|
||||
}
|
||||
|
||||
const cacheKey = `${target.toString()}|${width || "auto"}|${quality}|${requestedFormat || "auto"}`;
|
||||
const etag = buildEtag(cacheKey);
|
||||
const ifNoneMatch = request.headers.get("if-none-match");
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user