/** @jest-environment node */ import { getAllowedCorsOrigins, getRequestHostOrigin, isAllowedCorsOrigin, } from '@/lib/cors-origin' const originalAppPublicUrl = process.env.APP_PUBLIC_URL const originalNextAuthUrl = process.env.NEXTAUTH_URL const originalCorsAllowedOrigins = process.env.CORS_ALLOWED_ORIGINS const originalNextPublicAppUrl = process.env.NEXT_PUBLIC_APP_PUBLIC_URL function createRequest(headers: Record, nextUrlOrigin = 'http://127.0.0.1:3000') { return { headers: { get(name: string) { return headers[name.toLowerCase()] ?? null }, }, nextUrl: { origin: nextUrlOrigin, protocol: new URL(nextUrlOrigin).protocol, }, url: `${nextUrlOrigin}/api/work-review/projects`, } } describe('cors origin helpers', () => { beforeEach(() => { process.env.NEXT_PUBLIC_APP_PUBLIC_URL = 'https://sc.jiansun.vip' process.env.APP_PUBLIC_URL = 'https://sc.jiansun.vip' process.env.NEXTAUTH_URL = 'https://sc.jiansun.vip' process.env.CORS_ALLOWED_ORIGINS = '' }) afterAll(() => { if (originalNextPublicAppUrl === undefined) delete process.env.NEXT_PUBLIC_APP_PUBLIC_URL else process.env.NEXT_PUBLIC_APP_PUBLIC_URL = originalNextPublicAppUrl if (originalAppPublicUrl === undefined) delete process.env.APP_PUBLIC_URL else process.env.APP_PUBLIC_URL = originalAppPublicUrl if (originalNextAuthUrl === undefined) delete process.env.NEXTAUTH_URL else process.env.NEXTAUTH_URL = originalNextAuthUrl if (originalCorsAllowedOrigins === undefined) delete process.env.CORS_ALLOWED_ORIGINS else process.env.CORS_ALLOWED_ORIGINS = originalCorsAllowedOrigins }) test('prefers forwarded public host origin when nextUrl resolves to an internal address', () => { const request = createRequest({ host: 'sc.jiansun.vip', 'x-forwarded-proto': 'https', origin: 'https://sc.jiansun.vip', }) expect(getRequestHostOrigin(request)).toBe('https://sc.jiansun.vip') expect(Array.from(getAllowedCorsOrigins(request))).toContain('https://sc.jiansun.vip') expect(isAllowedCorsOrigin(request, 'https://sc.jiansun.vip')).toBe(true) }) test('allows trusted intranet entry origins when host headers point to the intranet domain', () => { const request = createRequest( { host: '192.168.58.20:4320', 'x-forwarded-proto': 'http', origin: 'http://192.168.58.20:4320', }, 'https://sc.jiansun.vip', ) expect(getRequestHostOrigin(request)).toBe('http://192.168.58.20:4320') expect(isAllowedCorsOrigin(request, 'http://192.168.58.20:4320')).toBe(true) }) test('keeps the public sc.jiansun.vip origin allowed when production only exposes an intranet NEXTAUTH_URL', () => { delete process.env.NEXT_PUBLIC_APP_PUBLIC_URL delete process.env.APP_PUBLIC_URL process.env.NEXTAUTH_URL = 'http://192.168.58.20:4320' process.env.CORS_ALLOWED_ORIGINS = '' const request = createRequest( { host: '192.168.58.20:4320', 'x-forwarded-proto': 'http', origin: 'https://sc.jiansun.vip', }, 'http://192.168.58.20:4320', ) expect(Array.from(getAllowedCorsOrigins(request))).toContain('https://sc.jiansun.vip') expect(isAllowedCorsOrigin(request, 'https://sc.jiansun.vip')).toBe(true) }) test('rejects foreign origins that do not match the request host or configured whitelist', () => { const request = createRequest({ host: 'sc.jiansun.vip', 'x-forwarded-proto': 'https', origin: 'https://evil.example.com', }) expect(isAllowedCorsOrigin(request, 'https://evil.example.com')).toBe(false) }) test('does not re-open the retired legacy public domain unless it is explicitly configured', () => { delete process.env.NEXT_PUBLIC_APP_PUBLIC_URL delete process.env.APP_PUBLIC_URL process.env.NEXTAUTH_URL = 'http://192.168.58.20:4320' process.env.CORS_ALLOWED_ORIGINS = '' const request = createRequest( { host: '192.168.58.20:4320', 'x-forwarded-proto': 'http', origin: 'https://3d.yydd.ai', }, 'http://192.168.58.20:4320', ) expect(isAllowedCorsOrigin(request, 'https://3d.yydd.ai')).toBe(false) }) })