/** * Caddy 등 리버스 프록시 뒤에서 request.url 이 * http://0.0.0.0:13000 처럼 잡히는 경우가 있어, 공개 Origin 을 따로 계산한다. */ export function getPublicOrigin(request: Request): string { const fromEnv = process.env.APP_ORIGIN?.trim() || process.env.NEXT_PUBLIC_APP_ORIGIN?.trim(); if (fromEnv) { try { return new URL(fromEnv).origin; } catch { // fall through } } const redirectUri = process.env.CHZZK_REDIRECT_URI?.trim(); if (redirectUri) { try { return new URL(redirectUri).origin; } catch { // fall through } } const xfHost = request.headers.get('x-forwarded-host')?.split(',')[0]?.trim(); const xfProto = request.headers.get('x-forwarded-proto')?.split(',')[0]?.trim() || 'https'; if (xfHost && !isBadHost(xfHost)) { return `${xfProto}://${xfHost}`; } const host = request.headers.get('host')?.trim(); if (host && !isBadHost(host)) { const proto = request.headers.get('x-forwarded-proto')?.split(',')[0]?.trim() || (host.includes('localhost') || host.startsWith('127.') ? 'http' : 'https'); return `${proto}://${host}`; } try { const origin = new URL(request.url).origin; if (!isBadHost(new URL(origin).host)) return origin; } catch { // fall through } return 'https://drink.kimyu.xyz'; } function isBadHost(host: string) { const h = host.toLowerCase().split(':')[0]; return ( h === '0.0.0.0' || h === '::' || h === '[::]' || h === 'host.docker.internal' ); }