Files
roblox/lib/utils.ts
2025-08-14 22:46:42 +03:00

66 lines
1.5 KiB
TypeScript

"use client";
import { clsx, type ClassValue } from "clsx";
import { twMerge } from "tailwind-merge";
export function cn(...inputs: ClassValue[]) {
return twMerge(clsx(inputs));
}
export async function proxyFetchRaw(
input: RequestInfo | URL,
init?: RequestInit
): Promise<Response> {
const url =
typeof input === "string"
? input
: input instanceof Request
? input.url
: "";
const proxyUrl = `/api/proxy?url=${encodeURIComponent(url)}`;
// Fix headers
const headers = new Headers(init?.headers || {});
headers.delete("accept-encoding"); // prevent encoding issues
const fetchInit: RequestInit = {
...init,
method: init?.method || "GET",
headers,
body: init?.body
};
return window.fetch(proxyUrl, fetchInit);
}
// CSRF-aware proxy fetch
export async function proxyFetch(
input: RequestInfo | URL,
init?: RequestInit
): Promise<Response> {
const xsrfRequestMethods = ["POST", "PATCH", "DELETE"];
const csrfTokenHeader = "x-csrf-token";
const csrfInvalidResponseCode = 403;
const method = init?.method?.toUpperCase() || "GET";
let response = await proxyFetchRaw(input, init);
if (
xsrfRequestMethods.includes(method) &&
response.status === csrfInvalidResponseCode &&
response.headers.has(csrfTokenHeader)
) {
const newHeaders = new Headers(init?.headers || {});
newHeaders.set(csrfTokenHeader, response.headers.get(csrfTokenHeader)!);
response = await proxyFetchRaw(input, {
...init,
headers: newHeaders
});
}
return response;
}