admin/lib/security/requestHost.ts
alisaza e1eaf5eff5 feat: initial ghabilee-admin backoffice app
Extract admin dashboard from ghabilee-frontend2 into a dedicated Next.js
app for backoffice.ghabilee.ir (no SEO indexing / Clarity).
2026-09-05 13:12:59 +03:30

33 lines
1.2 KiB
TypeScript

/** Production hostname served by the admin app. */
const PRODUCTION_HOSTS = new Set(['backoffice.ghabilee.ir'])
const normalizeHostHeader = (hostHeader: string | null): string | null => {
if (!hostHeader) return null
const value = hostHeader.trim().toLowerCase()
// Production hostnames are DNS names, optionally followed by a numeric port.
// Reject userinfo, paths, comma-separated proxy values and other ambiguities.
if (!/^[a-z0-9.-]+(?::[0-9]{1,5})?$/.test(value)) return null
const [hostname, port] = value.split(':')
if (port && Number(port) > 65535) return null
return hostname.endsWith('.') ? hostname.slice(0, -1) : hostname
}
export const isRequestHostAllowed = (hostHeader: string | null, environment = process.env.NODE_ENV): boolean => {
if (environment !== 'production') return true
const hostname = normalizeHostHeader(hostHeader)
// Local Playwright / standalone e2e still runs with NODE_ENV=production
// (Next.js standalone forces it). Opt in via ALLOW_LOCAL_REQUEST_HOSTS=1.
if (process.env.ALLOW_LOCAL_REQUEST_HOSTS === '1' && (hostname === '127.0.0.1' || hostname === 'localhost')) {
return true
}
return hostname !== null && PRODUCTION_HOSTS.has(hostname)
}