| import { NextRequest, NextResponse } from "next/server";
|
| import { STORAGE_KEY, internalAllowedWebDavEndpoints } from "../../../constant";
|
| import { getServerSideConfig } from "@/app/config/server";
|
|
|
| const config = getServerSideConfig();
|
|
|
| const mergedAllowedWebDavEndpoints = [
|
| ...internalAllowedWebDavEndpoints,
|
| ...config.allowedWebDavEndpoints,
|
| ].filter((domain) => Boolean(domain.trim()));
|
|
|
| const normalizeUrl = (url: string) => {
|
| try {
|
| return new URL(url);
|
| } catch (err) {
|
| return null;
|
| }
|
| };
|
|
|
| async function handle(
|
| req: NextRequest,
|
| { params }: { params: Promise<{ path: string[] }> },
|
| ) {
|
| const { path } = await params;
|
| if (req.method === "OPTIONS") {
|
| return NextResponse.json({ body: "OK" }, { status: 200 });
|
| }
|
| const folder = STORAGE_KEY;
|
| const fileName = `${folder}/backup.json`;
|
|
|
| const requestUrl = new URL(req.url);
|
| let endpoint = requestUrl.searchParams.get("endpoint");
|
| let proxy_method = requestUrl.searchParams.get("proxy_method") || req.method;
|
|
|
|
|
| if (
|
| !endpoint ||
|
| !mergedAllowedWebDavEndpoints.some((allowedEndpoint) => {
|
| const normalizedAllowedEndpoint = normalizeUrl(allowedEndpoint);
|
| const normalizedEndpoint = normalizeUrl(endpoint as string);
|
|
|
| return (
|
| normalizedEndpoint &&
|
| normalizedEndpoint.hostname === normalizedAllowedEndpoint?.hostname &&
|
| normalizedEndpoint.pathname.startsWith(
|
| normalizedAllowedEndpoint.pathname,
|
| )
|
| );
|
| })
|
| ) {
|
| return NextResponse.json(
|
| {
|
| error: true,
|
| msg: "Invalid endpoint",
|
| },
|
| {
|
| status: 400,
|
| },
|
| );
|
| }
|
|
|
| if (!endpoint?.endsWith("/")) {
|
| endpoint += "/";
|
| }
|
|
|
| const endpointPath = path.join("/");
|
| const targetPath = `${endpoint}${endpointPath}`;
|
|
|
|
|
| if (
|
| proxy_method !== "MKCOL" &&
|
| proxy_method !== "GET" &&
|
| proxy_method !== "PUT"
|
| ) {
|
| return NextResponse.json(
|
| {
|
| error: true,
|
| msg: "you are not allowed to request " + targetPath,
|
| },
|
| {
|
| status: 403,
|
| },
|
| );
|
| }
|
|
|
|
|
| if (proxy_method === "MKCOL" && !targetPath.endsWith(folder)) {
|
| return NextResponse.json(
|
| {
|
| error: true,
|
| msg: "you are not allowed to request " + targetPath,
|
| },
|
| {
|
| status: 403,
|
| },
|
| );
|
| }
|
|
|
|
|
| if (proxy_method === "GET" && !targetPath.endsWith(fileName)) {
|
| return NextResponse.json(
|
| {
|
| error: true,
|
| msg: "you are not allowed to request " + targetPath,
|
| },
|
| {
|
| status: 403,
|
| },
|
| );
|
| }
|
|
|
|
|
| if (proxy_method === "PUT" && !targetPath.endsWith(fileName)) {
|
| return NextResponse.json(
|
| {
|
| error: true,
|
| msg: "you are not allowed to request " + targetPath,
|
| },
|
| {
|
| status: 403,
|
| },
|
| );
|
| }
|
|
|
| const targetUrl = targetPath;
|
|
|
| const method = proxy_method || req.method;
|
| const shouldNotHaveBody = ["get", "head"].includes(
|
| method?.toLowerCase() ?? "",
|
| );
|
|
|
| const fetchOptions: RequestInit = {
|
| headers: {
|
| authorization: req.headers.get("authorization") ?? "",
|
| },
|
| body: shouldNotHaveBody ? null : req.body,
|
| redirect: "manual",
|
| method,
|
|
|
| duplex: "half",
|
| };
|
|
|
| let fetchResult;
|
|
|
| try {
|
| fetchResult = await fetch(targetUrl, fetchOptions);
|
| } finally {
|
| console.log(
|
| "[Any Proxy]",
|
| targetUrl,
|
| {
|
| method: method,
|
| },
|
| {
|
| status: fetchResult?.status,
|
| statusText: fetchResult?.statusText,
|
| },
|
| );
|
| }
|
|
|
| return fetchResult;
|
| }
|
|
|
| export const PUT = handle;
|
| export const GET = handle;
|
| export const OPTIONS = handle;
|
|
|
| export const runtime = "edge";
|
|
|