// var define_IMAGES_DEVICE_SIZES_default = [640, 750, 828, 1080, 1200, 1920, 2048, 3840]; // var define_IMAGES_FORMATS_default = ["image/webp"]; // var define_IMAGES_IMAGE_SIZES_default = [16, 32, 48, 64, 96, 128, 256, 384]; // var define_IMAGES_LOCAL_PATTERNS_default = [{ pathname: "^(?:\\/(?!\\.{1,2}(?:\\/|$))(?:(?:(?!(?:^|\\/)\\.{1,2}(?:\\/|$)).)*?))$" }]; // var define_IMAGES_QUALITIES_default = [75]; // var define_IMAGES_REMOTE_PATTERNS_default = []; // node_modules/@opennextjs/aws/dist/utils/error.js function isOpenNextError(e) { try { return "__openNextInternal" in e; } catch { return false; } } // node_modules/@opennextjs/aws/dist/adapters/logger.js function debug(...args) { if (globalThis.openNextDebug) { console.log(...args); } } function warn(...args) { console.warn(...args); } var DOWNPLAYED_ERROR_LOGS = [ { clientName: "S3Client", commandName: "GetObjectCommand", errorName: "NoSuchKey" } ]; var isDownplayedErrorLog = (errorLog) => DOWNPLAYED_ERROR_LOGS.some((downplayedInput) => downplayedInput.clientName === errorLog?.clientName && downplayedInput.commandName === errorLog?.commandName && (downplayedInput.errorName === errorLog?.error?.name || downplayedInput.errorName === errorLog?.error?.Code)); function error(...args) { if (args.some((arg) => isDownplayedErrorLog(arg))) { return debug(...args); } if (args.some((arg) => isOpenNextError(arg))) { const error2 = args.find((arg) => isOpenNextError(arg)); if (error2.logLevel < getOpenNextErrorLogLevel()) { return; } if (error2.logLevel === 0) { return console.log(...args.map((arg) => isOpenNextError(arg) ? `${arg.name}: ${arg.message}` : arg)); } if (error2.logLevel === 1) { return warn(...args.map((arg) => isOpenNextError(arg) ? `${arg.name}: ${arg.message}` : arg)); } return console.error(...args); } console.error(...args); } function getOpenNextErrorLogLevel() { const strLevel = process.env.OPEN_NEXT_ERROR_LOG_LEVEL ?? "1"; switch (strLevel.toLowerCase()) { case "debug": case "0": return 0; case "error": case "2": return 2; default: return 1; } } // node_modules/@opennextjs/cloudflare/dist/cli/templates/images.js async function handleImageRequest(requestURL, requestHeaders, env) { const parseResult = parseImageRequest(requestURL, requestHeaders); if (!parseResult.ok) { return new Response(parseResult.message, { status: 400 }); } let imageResponse; if (parseResult.url.startsWith("/")) { if (env.ASSETS === void 0) { error("env.ASSETS binding is not defined"); return new Response('"url" parameter is valid but upstream response is invalid', { status: 404 }); } const absoluteURL = new URL(parseResult.url, requestURL); imageResponse = await env.ASSETS.fetch(absoluteURL); } else { let fetchImageResult; try { fetchImageResult = await fetchWithRedirects(parseResult.url, 7e3, 3); } catch (e) { throw new Error("Failed to fetch image", { cause: e }); } if (!fetchImageResult.ok) { if (fetchImageResult.error === "timed_out") { return new Response('"url" parameter is valid but upstream response timed out', { status: 504 }); } if (fetchImageResult.error === "too_many_redirects") { return new Response('"url" parameter is valid but upstream response is invalid', { status: 508 }); } throw new Error("Failed to fetch image"); } imageResponse = fetchImageResult.response; } if (!imageResponse.ok || imageResponse.body === null) { return new Response('"url" parameter is valid but upstream response is invalid', { status: imageResponse.status }); } let immutable = false; if (parseResult.static) { immutable = true; } else { const cacheControlHeader = imageResponse.headers.get("Cache-Control"); if (cacheControlHeader !== null) { immutable = cacheControlHeader.includes("immutable"); } } const readHeaderResult = await readImageHeader(imageResponse); if (readHeaderResult instanceof Response) { return readHeaderResult; } const { contentType, imageStream } = readHeaderResult; if (contentType === null) { warn(`Failed to detect content type of "${parseResult.url}"`); return new Response('"url" parameter is valid but image type is not allowed', { status: 400 }); } if (contentType === SVG) { if (true) { return new Response('"url" parameter is valid but image type is not allowed', { status: 400 }); } const response2 = createImageResponse(imageStream, contentType, { immutable }); return response2; } if (contentType === GIF) { if (env.IMAGES === void 0) { warn("env.IMAGES binding is not defined"); const response3 = createImageResponse(imageStream, contentType, { immutable }); return response3; } const imageSource = env.IMAGES.input(imageStream); const imageTransformationResult = await imageSource.transform({ width: parseResult.width, fit: "scale-down" }).output({ quality: parseResult.quality, format: GIF }); const outputImageStream = imageTransformationResult.image(); const response2 = createImageResponse(outputImageStream, GIF, { immutable }); return response2; } if (contentType === AVIF || contentType === WEBP || contentType === JPEG || contentType === PNG) { if (env.IMAGES === void 0) { warn("env.IMAGES binding is not defined"); const response3 = createImageResponse(imageStream, contentType, { immutable }); return response3; } const outputFormat = parseResult.format ?? contentType; const imageSource = env.IMAGES.input(imageStream); const imageTransformationResult = await imageSource.transform({ width: parseResult.width, fit: "scale-down" }).output({ quality: parseResult.quality, format: outputFormat }); const outputImageStream = imageTransformationResult.image(); const response2 = createImageResponse(outputImageStream, outputFormat, { immutable }); return response2; } warn(`Image content type ${contentType} not supported`); const response = createImageResponse(imageStream, contentType, { immutable }); return response; } async function handleCdnCgiImageRequest(requestURL, env) { const parseResult = parseCdnCgiImageRequest(requestURL.pathname); if (!parseResult.ok) { return new Response(parseResult.message, { status: 400 }); } let imageResponse; if (parseResult.url.startsWith("/")) { if (env.ASSETS === void 0) { return new Response("env.ASSETS binding is not defined", { status: 404 }); } const absoluteURL = new URL(parseResult.url, requestURL); imageResponse = await env.ASSETS.fetch(absoluteURL); } else { imageResponse = await fetch(parseResult.url); } if (!imageResponse.ok || imageResponse.body === null) { return new Response('"url" parameter is valid but upstream response is invalid', { status: imageResponse.status }); } const readHeaderResult = await readImageHeader(imageResponse); if (readHeaderResult instanceof Response) { return readHeaderResult; } const { contentType, imageStream } = readHeaderResult; if (contentType === null || !SUPPORTED_CDN_CGI_INPUT_TYPES.has(contentType)) { return new Response('"url" parameter is valid but image type is not allowed', { status: 400 }); } if (contentType === SVG && true) { return new Response('"url" parameter is valid but image type is not allowed', { status: 400 }); } return new Response(imageStream, { headers: { "Content-Type": contentType } }); } function parseCdnCgiImageRequest(pathname) { const match = pathname.match(/^\/cdn-cgi\/image\/(?[^/]+)\/(?.+)$/); if (match === null || // Valid URLs have at least one option !match.groups?.options || !match.groups?.url) { return { ok: false, message: "Invalid /cdn-cgi/image/ URL format" }; } const imageUrl = match.groups.url; if (imageUrl.startsWith("/")) { return { ok: false, message: '"url" parameter cannot be a protocol-relative URL (//)' }; } let resolvedUrl; if (imageUrl.match(/^https?:\/\//)) { resolvedUrl = imageUrl; } else { resolvedUrl = `/${imageUrl}`; } return { ok: true, url: resolvedUrl, static: false }; } async function readImageHeader(imageResponse) { const [contentTypeStream, imageStream] = imageResponse.body.tee(); const headerBytes = new Uint8Array(32); const reader = contentTypeStream.getReader({ mode: "byob" }); const readResult = await reader.readAtLeast(32, headerBytes); if (readResult.value === void 0) { await imageResponse.body.cancel(); return new Response('"url" parameter is valid but upstream response is invalid', { status: 400 }); } const contentType = detectImageContentType(readResult.value); return { contentType, imageStream }; } async function fetchWithRedirects(url, timeoutMS, maxRedirectCount) { let response; try { response = await fetch(url, { signal: AbortSignal.timeout(timeoutMS), redirect: "manual" }); } catch (e) { if (e instanceof Error && e.name === "TimeoutError") { const result2 = { ok: false, error: "timed_out" }; return result2; } throw e; } if (redirectResponseStatuses.includes(response.status)) { const locationHeader = response.headers.get("Location"); if (locationHeader !== null) { if (maxRedirectCount < 1) { const result3 = { ok: false, error: "too_many_redirects" }; return result3; } let redirectTarget; if (locationHeader.startsWith("/")) { redirectTarget = new URL(locationHeader, url).href; } else { redirectTarget = locationHeader; } const result2 = await fetchWithRedirects(redirectTarget, timeoutMS, maxRedirectCount - 1); return result2; } } const result = { ok: true, response }; return result; } var redirectResponseStatuses = [301, 302, 303, 307, 308]; function createImageResponse(image, contentType, imageResponseFlags) { const response = new Response(image, { headers: { Vary: "Accept", "Content-Type": contentType, "Content-Disposition": "attachment", "Content-Security-Policy": "script-src 'none'; frame-src 'none'; sandbox;" } }); if (imageResponseFlags.immutable) { response.headers.set("Cache-Control", "public, max-age=315360000, immutable"); } return response; } function parseImageRequest(requestURL, requestHeaders) { const formats = define_IMAGES_FORMATS_default; const parsedUrlOrError = validateUrlQueryParameter(requestURL); if (!("url" in parsedUrlOrError)) { return parsedUrlOrError; } const widthOrError = validateWidthQueryParameter(requestURL); if (typeof widthOrError !== "number") { return widthOrError; } const qualityOrError = validateQualityQueryParameter(requestURL); if (typeof qualityOrError !== "number") { return qualityOrError; } const acceptHeader = requestHeaders.get("Accept") ?? ""; let format = null; for (const allowedFormat of formats) { if (acceptHeader.includes(allowedFormat)) { format = allowedFormat; break; } } const result = { ok: true, url: parsedUrlOrError.url, width: widthOrError, quality: qualityOrError, format, static: parsedUrlOrError.static }; return result; } function validateUrlQueryParameter(requestURL) { const urls = requestURL.searchParams.getAll("url"); if (urls.length < 1) { const result = { ok: false, message: '"url" parameter is required' }; return result; } if (urls.length > 1) { const result = { ok: false, message: '"url" parameter cannot be an array' }; return result; } const url = urls[0]; if (url.length > 3072) { const result = { ok: false, message: '"url" parameter is too long' }; return result; } if (url.startsWith("//")) { const result = { ok: false, message: '"url" parameter cannot be a protocol-relative URL (//)' }; return result; } if (url.startsWith("/")) { const staticAsset = url.startsWith(`${__NEXT_BASE_PATH__ || ""}/_next/static/media`); const pathname = getPathnameFromRelativeURL(url); if (/\/_next\/image($|\/)/.test(decodeURIComponent(pathname))) { const result = { ok: false, message: '"url" parameter cannot be recursive' }; return result; } if (!staticAsset) { if (!hasLocalMatch(define_IMAGES_LOCAL_PATTERNS_default, url)) { const result = { ok: false, message: '"url" parameter is not allowed' }; return result; } } return { url, static: staticAsset }; } let parsedURL; try { parsedURL = new URL(url); } catch { const result = { ok: false, message: '"url" parameter is invalid' }; return result; } const validProtocols = ["http:", "https:"]; if (!validProtocols.includes(parsedURL.protocol)) { const result = { ok: false, message: '"url" parameter is invalid' }; return result; } if (!hasRemoteMatch(define_IMAGES_REMOTE_PATTERNS_default, parsedURL)) { const result = { ok: false, message: '"url" parameter is not allowed' }; return result; } return { url: parsedURL.href, static: false }; } function validateWidthQueryParameter(requestURL) { const widthQueryValues = requestURL.searchParams.getAll("w"); if (widthQueryValues.length < 1) { const result = { ok: false, message: '"w" parameter (width) is required' }; return result; } if (widthQueryValues.length > 1) { const result = { ok: false, message: '"w" parameter (width) cannot be an array' }; return result; } const widthQueryValue = widthQueryValues[0]; if (!/^[0-9]+$/.test(widthQueryValue)) { const result = { ok: false, message: '"w" parameter (width) must be an integer greater than 0' }; return result; } const width = parseInt(widthQueryValue, 10); if (width <= 0 || isNaN(width)) { const result = { ok: false, message: '"w" parameter (width) must be an integer greater than 0' }; return result; } const sizeValid = define_IMAGES_DEVICE_SIZES_default.includes(width) || define_IMAGES_IMAGE_SIZES_default.includes(width); if (!sizeValid) { const result = { ok: false, message: `"w" parameter (width) of ${width} is not allowed` }; return result; } return width; } function validateQualityQueryParameter(requestURL) { const qualityQueryValues = requestURL.searchParams.getAll("q"); if (qualityQueryValues.length < 1) { const result = { ok: false, message: '"q" parameter (quality) is required' }; return result; } if (qualityQueryValues.length > 1) { const result = { ok: false, message: '"q" parameter (quality) cannot be an array' }; return result; } const qualityQueryValue = qualityQueryValues[0]; if (!/^[0-9]+$/.test(qualityQueryValue)) { const result = { ok: false, message: '"q" parameter (quality) must be an integer between 1 and 100' }; return result; } const quality = parseInt(qualityQueryValue, 10); if (isNaN(quality) || quality < 1 || quality > 100) { const result = { ok: false, message: '"q" parameter (quality) must be an integer between 1 and 100' }; return result; } if (!define_IMAGES_QUALITIES_default.includes(quality)) { const result = { ok: false, message: `"q" parameter (quality) of ${quality} is not allowed` }; return result; } return quality; } function getPathnameFromRelativeURL(relativeURL) { return relativeURL.split("?")[0]; } function hasLocalMatch(localPatterns, relativeURL) { const parseRelativeURLResult = parseRelativeURL(relativeURL); for (const localPattern of localPatterns) { const matched = matchLocalPattern(localPattern, parseRelativeURLResult); if (matched) { return true; } } return false; } function parseRelativeURL(relativeURL) { if (!relativeURL.includes("?")) { const result2 = { pathname: relativeURL, search: "" }; return result2; } const parts = relativeURL.split("?"); const pathname = parts[0]; const search = "?" + parts.slice(1).join("?"); const result = { pathname, search }; return result; } function matchLocalPattern(pattern, url) { if (pattern.search !== void 0 && pattern.search !== url.search) { return false; } return new RegExp(pattern.pathname).test(url.pathname); } function hasRemoteMatch(remotePatterns, url) { for (const remotePattern of remotePatterns) { const matched = matchRemotePattern(remotePattern, url); if (matched) { return true; } } return false; } function matchRemotePattern(pattern, url) { if (pattern.protocol !== void 0 && pattern.protocol.replace(/:$/, "") !== url.protocol.replace(/:$/, "")) { return false; } if (pattern.port !== void 0 && pattern.port !== url.port) { return false; } if (pattern.hostname === void 0 || !new RegExp(pattern.hostname).test(url.hostname)) { return false; } if (pattern.search !== void 0 && pattern.search !== url.search) { return false; } return new RegExp(pattern.pathname).test(url.pathname); } var AVIF = "image/avif"; var WEBP = "image/webp"; var PNG = "image/png"; var JPEG = "image/jpeg"; var JXL = "image/jxl"; var JP2 = "image/jp2"; var HEIC = "image/heic"; var GIF = "image/gif"; var SVG = "image/svg+xml"; var ICO = "image/x-icon"; var ICNS = "image/x-icns"; var TIFF = "image/tiff"; var BMP = "image/bmp"; var SUPPORTED_CDN_CGI_INPUT_TYPES = /* @__PURE__ */ new Set([JPEG, PNG, GIF, WEBP, SVG, HEIC]); function detectImageContentType(buffer) { if ([255, 216, 255].every((b, i) => buffer[i] === b)) { return JPEG; } if ([137, 80, 78, 71, 13, 10, 26, 10].every((b, i) => buffer[i] === b)) { return PNG; } if ([71, 73, 70, 56].every((b, i) => buffer[i] === b)) { return GIF; } if ([82, 73, 70, 70, 0, 0, 0, 0, 87, 69, 66, 80].every((b, i) => !b || buffer[i] === b)) { return WEBP; } if ([60, 63, 120, 109, 108].every((b, i) => buffer[i] === b)) { return SVG; } if ([60, 115, 118, 103].every((b, i) => buffer[i] === b)) { return SVG; } if ([0, 0, 0, 0, 102, 116, 121, 112, 97, 118, 105, 102].every((b, i) => !b || buffer[i] === b)) { return AVIF; } if ([0, 0, 1, 0].every((b, i) => buffer[i] === b)) { return ICO; } if ([105, 99, 110, 115].every((b, i) => buffer[i] === b)) { return ICNS; } if ([73, 73, 42, 0].every((b, i) => buffer[i] === b)) { return TIFF; } if ([66, 77].every((b, i) => buffer[i] === b)) { return BMP; } if ([255, 10].every((b, i) => buffer[i] === b)) { return JXL; } if ([0, 0, 0, 12, 74, 88, 76, 32, 13, 10, 135, 10].every((b, i) => buffer[i] === b)) { return JXL; } if ([0, 0, 0, 0, 102, 116, 121, 112, 104, 101, 105, 99].every((b, i) => !b || buffer[i] === b)) { return HEIC; } if ([0, 0, 0, 12, 106, 80, 32, 32, 13, 10, 135, 10].every((b, i) => buffer[i] === b)) { return JP2; } return null; } export { detectImageContentType, handleCdnCgiImageRequest, handleImageRequest, matchLocalPattern, matchRemotePattern, parseCdnCgiImageRequest };