AWS API Gateway与Next.js交互时的CORS错误排查求助
错误信息
Access to fetch at 'https://xxxxxx.execute-api.us-east-1.amazonaws.com/items' from origin 'http://localhost:3000' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource. If an opaque response serves your needs, set the request's mode to 'no-cors' to fetch the resource with CORS disabled.
现有配置与代码
1. API Gateway配置

2. Lambda函数代码
import { DynamoDBClient } from "@aws-sdk/client-dynamodb"; import { S3Client, PutObjectCommand } from "@aws-sdk/client-s3"; import { DynamoDBDocumentClient, ScanCommand, PutCommand, GetCommand, DeleteCommand } from "@aws-sdk/lib-dynamodb"; const dynamoDBClient = new DynamoDBClient({}); const s3Client = new S3Client({}); const client = new DynamoDBClient({}); const dynamoDBDocumentClient = DynamoDBDocumentClient.from(dynamoDBClient); const dynamo = DynamoDBDocumentClient.from(client); const tableName = " "; const s3BucketName = ""; export const handler = async (event) => { const response = { statusCode: 200, headers: { "Access-Control-Allow-Headers": "rid,fdi-version,anti-csrf,st-auth-mode", "Access-Control-Allow-Origin" : "*", "Access-Control-Allow-Methods": "OPTIONS,POST,GET, PUT", "Cache-Control": "max-age=0, no-store, must-revalidate", "Access-Control-Allow-Credentials": "true", }, body: "", }; try { switch (event.routeKey) { case "POST /items": break; case "GET /items": break; case "GET /items/{id}": break; case "DELETE /items/{id}": break; default: throw new Error(`Unsupported route: "${event.routeKey}"`); } } catch (err) { response.statusCode = 400; response.body = err.message; } return response; }; // Function to generate a random alphanumeric string
3. Next.js handleSubmit代码
const handleSubmit = async (event) => { event.preventDefault(); var myHeaders = new Headers(); myHeaders.append("Content-Type", "application/json"); var raw = JSON.stringify({ "id": formData.projectId, "projectName": formData.projectName, "clientName": formData.clientName, }); var requestOptions = { method: 'POST', headers: myHeaders, body: raw, redirect: 'follow', // mode: 'no-cors', }; fetch("https://xxxxxxx.execute-api.us-east-1.amazonaws.com/items", requestOptions) .then(response => console.log(response.json())) .then(result => console.log(result, 'resulttttt')) .catch(error => console.log('error', error)) };
排查与解决方案
1. 处理OPTIONS预请求
浏览器发起跨域POST请求前会先发送OPTIONS预请求,需确保该请求能正确返回CORS头。在Lambda的switch语句中添加OPTIONS分支:
case "OPTIONS /items": // 直接返回配置好的CORS响应 break;
若API Gateway使用Lambda代理集成,需确认OPTIONS请求能触发Lambda并返回响应。
2. 修正允许的请求头
你的Next.js请求使用了Content-Type: application/json,但当前Lambda的Access-Control-Allow-Headers未包含该字段,会导致预请求失败。修改Lambda的响应头:
"Access-Control-Allow-Headers": "rid,fdi-version,anti-csrf,st-auth-mode,Content-Type",
同时在API Gateway的CORS配置中,将Content-Type添加到允许的头列表,修改后必须重新部署API Gateway才会生效。
3. 解决CORS配置冲突
你同时设置了Access-Control-Allow-Origin: *和Access-Control-Allow-Credentials: true,这两个配置冲突:当允许凭证(如Cookie)时,Origin不能使用通配符,必须指定具体域名。
二选一处理:
- 若不需要凭证:删除
Access-Control-Allow-Credentials: true - 若需要凭证:将
Access-Control-Allow-Origin改为具体域名,开发环境用http://localhost:3000,生产环境替换为实际域名
4. 验证API部署
每次修改API Gateway的CORS配置或Lambda代码后,都需要重新部署API,确保新配置生效。
内容的提问来源于stack exchange,提问作者Oluwafemi Akinyemi

