feat: improve admin experience and ignore local data
This commit is contained in:
+89
-11
@@ -2,23 +2,101 @@ import { headers } from "next/headers";
|
||||
|
||||
import { getEnv } from "@/lib/env";
|
||||
|
||||
export async function getRequestOrigin() {
|
||||
const headerList = await headers();
|
||||
const forwardedProto = headerList.get("x-forwarded-proto");
|
||||
const forwardedHost = headerList.get("x-forwarded-host");
|
||||
const host = forwardedHost || headerList.get("host");
|
||||
function getFirstHeaderValue(value: string | null) {
|
||||
return value?.split(",")[0]?.trim() || null;
|
||||
}
|
||||
|
||||
if (!host) {
|
||||
return getEnv().APP_URL;
|
||||
function sanitizeProto(value: string | null) {
|
||||
const candidate = getFirstHeaderValue(value)?.toLowerCase();
|
||||
if (candidate === "http" || candidate === "https") {
|
||||
return candidate;
|
||||
}
|
||||
|
||||
const proto =
|
||||
forwardedProto || (host.startsWith("localhost") || host.startsWith("127.0.0.1") ? "http" : "http");
|
||||
return null;
|
||||
}
|
||||
|
||||
return `${proto}://${host}`;
|
||||
function sanitizeHost(value: string | null) {
|
||||
const candidate = getFirstHeaderValue(value)?.replace(/^"|"$/g, "");
|
||||
if (!candidate) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (candidate.includes("/") || /\s/.test(candidate)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return candidate;
|
||||
}
|
||||
|
||||
function parseForwardedHeader(value: string | null) {
|
||||
const firstEntry = getFirstHeaderValue(value);
|
||||
if (!firstEntry) {
|
||||
return {
|
||||
host: null,
|
||||
proto: null,
|
||||
};
|
||||
}
|
||||
|
||||
let host: string | null = null;
|
||||
let proto: "http" | "https" | null = null;
|
||||
|
||||
for (const segment of firstEntry.split(";")) {
|
||||
const [rawKey, ...rest] = segment.split("=");
|
||||
const key = rawKey?.trim().toLowerCase();
|
||||
const rawValue = rest.join("=").trim();
|
||||
|
||||
if (!key || !rawValue) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (key === "host") {
|
||||
host = sanitizeHost(rawValue) || host;
|
||||
} else if (key === "proto") {
|
||||
proto = sanitizeProto(rawValue) || proto;
|
||||
}
|
||||
}
|
||||
|
||||
return { host, proto };
|
||||
}
|
||||
|
||||
function buildOriginFromParts(
|
||||
host: string | null,
|
||||
proto: "http" | "https" | null,
|
||||
fallback: string,
|
||||
) {
|
||||
if (!host) {
|
||||
return fallback;
|
||||
}
|
||||
|
||||
return `${proto || "http"}://${host}`;
|
||||
}
|
||||
|
||||
export async function getRequestOrigin() {
|
||||
const headerList = await headers();
|
||||
const envOrigin = getEnv().APP_URL;
|
||||
const forwarded = parseForwardedHeader(headerList.get("forwarded"));
|
||||
const host =
|
||||
sanitizeHost(headerList.get("x-forwarded-host")) ||
|
||||
forwarded.host ||
|
||||
sanitizeHost(headerList.get("host"));
|
||||
const proto =
|
||||
sanitizeProto(headerList.get("x-forwarded-proto")) || forwarded.proto;
|
||||
|
||||
return buildOriginFromParts(host, proto, envOrigin);
|
||||
}
|
||||
|
||||
export function getOriginFromRequest(request: Request) {
|
||||
const url = new URL(request.url);
|
||||
return `${url.protocol}//${url.host}`;
|
||||
const forwarded = parseForwardedHeader(request.headers.get("forwarded"));
|
||||
const host =
|
||||
sanitizeHost(request.headers.get("x-forwarded-host")) ||
|
||||
forwarded.host ||
|
||||
sanitizeHost(request.headers.get("host")) ||
|
||||
url.host;
|
||||
const proto =
|
||||
sanitizeProto(request.headers.get("x-forwarded-proto")) ||
|
||||
forwarded.proto ||
|
||||
sanitizeProto(url.protocol.replace(/:$/, ""));
|
||||
|
||||
return buildOriginFromParts(host, proto, getEnv().APP_URL);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user