UNPKG

astro

Version:

Astro is a modern site builder with web best practices, performance, and DX front-of-mind.

77 lines (76 loc) • 2.33 kB
// @ts-expect-error import { fsDenyGlob, safeModulePaths, viteFSConfig } from "astro:assets"; import { readFile } from "node:fs/promises"; import os from "node:os"; import { isFileLoadingAllowed } from "vite"; import { handleImageRequest, loadRemoteImage } from "./shared.js"; function replaceFileSystemReferences(src) { return os.platform().includes("win32") ? src.replace(/^\/@fs\//, "") : src.replace(/^\/@fs/, ""); } async function loadLocalImage(src, url) { let returnValue; let fsPath; // Vite uses /@fs/ to denote filesystem access, but we need to convert that to a real path to load it if (src.startsWith("/@fs/")) { fsPath = replaceFileSystemReferences(src); } // Vite only uses the fs config, but the types ask for the full config if (fsPath && isFileLoadingAllowed({ fsDenyGlob, server: { fs: viteFSConfig }, safeModulePaths }, fsPath)) { try { returnValue = await readFile(fsPath); } catch { returnValue = undefined; } // If we couldn't load it directly, try loading it through Vite as a fallback, which will also respect Vite's fs rules if (!returnValue) { try { const res = await fetch(new URL(src, url)); if (res.ok) { returnValue = Buffer.from(await res.arrayBuffer()); } } catch { returnValue = undefined; } } } else { // Otherwise, we'll assume it's a local URL and try to load it via fetch const sourceUrl = new URL(src, url.origin); // This is only allowed if this is the same origin if (sourceUrl.origin !== url.origin) { return { kind: "invalid-path" }; } const buffer = await loadRemoteImage(sourceUrl); return buffer ? { kind: "loaded", buffer } : { kind: "failed" }; } return returnValue ? { kind: "loaded", buffer: returnValue } : { kind: "failed" }; } /** * Endpoint used in dev and SSR to serve optimized images by the base image services */ export const GET = async ({ request, logger }) => { if (!import.meta.env.DEV) { logger.error("The dev image endpoint can only be used in dev mode."); return new Response("Invalid endpoint", { status: 500 }); } try { return await handleImageRequest({ request, loadLocalImage, logger }); } catch (err) { const message = `Could not process image request: ${err}`; logger.error(message); return new Response(message, { status: 500 }); } };