import { client } from "$lib/server/nextcloud"; import { error } from "@sveltejs/kit"; import type { RequestHandler } from "./$types"; import mime from "mime-types"; import { env } from "$env/dynamic/private"; export const GET: RequestHandler = async ({ params, url }) => { const { path } = params; const width = url.searchParams.get("w"); const height = url.searchParams.get("h"); if (!path) { throw error(400, "Path is required"); } try { let buffer: ArrayBuffer; let contentType: string; // Try both original path and hidden variant if applicable const pathsToTry = [path]; if (!path.startsWith('_')) { pathsToTry.push(`_${path}`); } let response: Response | null = null; let lastError: any = null; for (const currentPath of pathsToTry) { try { if (width || height) { // Use Nextcloud Preview API const baseUrl = env.NEXTCLOUD_URL?.endsWith("/") ? env.NEXTCLOUD_URL : `${env.NEXTCLOUD_URL}/`; let fullPath = currentPath; if (env.NEXTCLOUD_BASE_DIR) { const baseDir = env.NEXTCLOUD_BASE_DIR.replace(/^\/+|\/+$/g, ""); fullPath = baseDir ? `${baseDir}/${currentPath}` : currentPath; } const isJpg = fullPath.match(/\.(jpg|jpeg)$/i); const previewExtension = isJpg ? 'jpg' : 'png'; const previewUrl = new URL(`${baseUrl}index.php/core/preview.${previewExtension}`); // Ensure leading slash for the file parameter const fileParam = fullPath.startsWith('/') ? fullPath : `/${fullPath}`; previewUrl.searchParams.set("file", fileParam); if (width) previewUrl.searchParams.set("x", width); if (height) previewUrl.searchParams.set("y", height); previewUrl.searchParams.set("forceIcon", "0"); const auth = Buffer.from(`${env.NEXTCLOUD_USER}:${env.NEXTCLOUD_PASSWORD}`).toString("base64"); console.log(`Fetching preview: ${previewUrl.toString()} for file: ${fullPath}`); const ncResponse = await fetch(previewUrl.toString(), { headers: { "Authorization": `Basic ${auth}` } }); if (ncResponse.ok) { buffer = await ncResponse.arrayBuffer(); contentType = ncResponse.headers.get("Content-Type") || "image/png"; return new Response(buffer, { headers: { "Content-Type": contentType, "Cache-Control": "public, max-age=86400", "Vary": "Accept-Encoding" } }); } else { console.warn(`Nextcloud preview failed (${ncResponse.status}) for ${fullPath}.`); } } // Fetch original via WebDAV (Fallback or no resize requested) console.log(`Fetching original file via WebDAV: /${currentPath}`); const data = await client.getFileContents("/" + currentPath); buffer = data as ArrayBuffer; contentType = mime.lookup(currentPath) || "application/octet-stream"; return new Response(buffer, { headers: { "Content-Type": contentType, "Cache-Control": "public, max-age=86400", "Vary": "Accept-Encoding" } }); } catch (e) { lastError = e; continue; // Try next path variant } } throw lastError || new Error("Asset not found"); } catch (e) { console.error(`Error fetching asset from Nextcloud: ${path}`, e); throw error(404, "Asset not found"); } };