NextJS 14部署AWS Amplify后Origin显示localhost:3000的CORS问题
问题:AWS Amplify部署NextJS 14.2.20后,Middleware获取的Origin异常为localhost:3000
现象
将NextJS 14.2.20应用通过GitHub部署至AWS Amplify后,服务器端CORS白名单校验时,req.nextUrl.origin获取到的值是https://localhost:3000,而非Amplify分配的应用域名(如https://main.xxxxxx.amplifyapp.com),导致校验失败返回405错误。
该问题仅在AWS Amplify部署时出现:
- 本地运行(端口88888)时,Origin正常获取为本地地址
- 部署至Vercel时,Origin正常获取为Vercel分配的域名
错误返回结果:
{"error":"Access denied. Environment: production. Your Origin: https://localhost:3000 | Whitelist: https://main.xxxxxx.amplifyapp.com"}
相关代码与配置
Middleware校验代码(middleware.ts)
export const middleware = async (req: NextRequest) => { const origin = req.nextUrl.origin; if (!publicEnv.CORS_WHITELIST?.includes(origin)) { return NextResponse.json({ error: `Access denied. Environment: ${process.env.NODE_ENV}. Your Origin: ${origin} | Whitelist: ${publicEnv.CORS_WHITELIST}` }, { status: 405 }) } // ...其他逻辑 }
Amplify配置(amplify.yml)
version: 1 frontend: phases: preBuild: commands: - npm ci --cache .npm --prefer-offline build: commands: - npm run build artifacts: baseDirectory: .next files: - '**/*' cache: paths: - .npm/**/* - node_modules/**/*
尝试过的配置调整
- customHttp.yml:无论是空文件还是添加CORS头配置,问题未解决
customHeaders: - pattern: "**/*" headers: - key: Access-Control-Allow-Origin value: https://main.xxxxxx.amplifyapp.com - key: Access-Control-Allow-Headers value: Origin, X-Requested-With, Content-Type, Accept, Authorization - key: Access-Control-Allow-Methods value: GET, POST, PUT, PATCH, DELETE, OPTIONS - package.json scripts:尝试两种配置,均无效
第一种:
第二种:"scripts": { "dev": "next dev -p 88888", "build": "next build", "start": "next start -p 88888", "lint": "next lint" }"scripts": { "dev": "next dev -p 88888", "build": "NODE_ENV=production next build", "start": "NODE_ENV=production next start", "lint": "next lint" }
原因分析
AWS Amplify部署NextJS时,默认通过内部反向代理转发请求,req.nextUrl.origin读取的是代理内部的容器端口地址(localhost:3000,对应NextJS在Amplify容器内的运行端口),而非客户端实际请求的外部域名。这是Amplify部署环境与Vercel/本地环境的核心差异点。
解决方案
方案1:从请求头获取真实Origin
放弃使用req.nextUrl.origin,改为读取请求头中的Origin字段(客户端发送的真实来源),同时兼容本地开发场景:
export const middleware = async (req: NextRequest) => { // 优先取请求头的真实Origin,本地开发时fallback到nextUrl.origin const origin = req.headers.get('origin') || req.nextUrl.origin; if (!publicEnv.CORS_WHITELIST?.includes(origin)) { return NextResponse.json({ error: `Access denied. Environment: ${process.env.NODE_ENV}. Your Origin: ${origin} | Whitelist: ${publicEnv.CORS_WHITELIST}` }, { status: 405 }) } // ...其他逻辑 }
方案2:通过环境变量强制指定允许的Origin
在AWS Amplify控制台添加环境变量NEXT_PUBLIC_APP_URL,值为你的Amplify应用域名(如https://main.xxxxxx.amplifyapp.com),然后在middleware中直接用该变量作为校验基准:
export const middleware = async (req: NextRequest) => { const allowedOrigin = process.env.NODE_ENV === 'production' ? process.env.NEXT_PUBLIC_APP_URL : req.nextUrl.origin; const clientOrigin = req.headers.get('origin') || req.nextUrl.origin; if (clientOrigin !== allowedOrigin) { return NextResponse.json({ error: `Access denied. Environment: ${process.env.NODE_ENV}. Your Origin: ${clientOrigin} | Whitelist: ${allowedOrigin}` }, { status: 405 }) } // ...其他逻辑 }
方案3:调整Amplify代理与NextJS信任配置(进阶)
通过customHttp.yml配置转发真实域名头,同时让NextJS信任Amplify代理:
- 修改
customHttp.yml:
customHeaders: - pattern: "**/*" headers: - key: X-Forwarded-Proto value: https - key: X-Forwarded-Host value: main.xxxxxx.amplifyapp.com
- 修改
next.config.js:
/** @type {import('next').NextConfig} */ const nextConfig = { async headers() { return [ { source: '/api/:path*', headers: [ { key: 'Access-Control-Allow-Credentials', value: 'true' }, { key: 'Access-Control-Allow-Origin', value: process.env.NEXT_PUBLIC_APP_URL }, { key: 'Access-Control-Allow-Methods', value: 'GET,OPTIONS,PATCH,DELETE,POST,PUT' }, { key: 'Access-Control-Allow-Headers', value: 'X-CSRF-Token, X-Requested-With, Accept, Accept-Version, Content-Length, Content-MD5, Content-Type, Date, X-Api-Version' }, ], }, ] }, // 信任Amplify代理传递的Host头 trustHostHeader: true, } module.exports = nextConfig
内容的提问来源于stack exchange,提问作者Viserion Wick
相关产品推荐
相关产品推荐

