如何在Serverless TypeScript Lambda函数中启用CORS以解决跨域请求错误?
你遇到的这个CORS错误很常见,尤其是在本地测试Serverless服务的时候。咱们一步步来排查你可能遗漏的点:
1. 本地测试时,Serverless Offline插件需要单独配置CORS
你用了serverless-offline插件,这个插件默认的CORS配置可能和你预期的不一样,哪怕你在函数的http事件里设了cors: true。你需要在serverless.ts的custom字段里添加专门的离线插件配置:
custom: { esbuild: { // 你原有的esbuild配置... bundle: true, minify: false, sourcemap: true, exclude: ['aws-sdk'], target: 'node14', define: { 'require.resolve': undefined }, platform: 'node', concurrency: 10, }, // 新增serverless-offline的CORS配置 'serverless-offline': { corsAllowOrigin: 'http://localhost:3001', // 你的前端地址 corsAllowHeaders: '*', corsEnableCredentials: true } },
这个配置会确保本地运行的API网关正确返回CORS头部,解决本地请求的跨域问题。
2. 明确配置Middy的CORS中间件参数
你已经用了@middy/http-cors,但默认的配置可能不够明确。建议你在中间件里指定具体的允许来源和头部,避免和其他配置冲突:
修改你的middyfy函数:
import middy from "@middy/core" import middyJsonBodyParser from "@middy/http-json-body-parser" import cors from "@middy/http-cors" export const middyfy = (handler) => { return middy(handler) .use(middyJsonBodyParser()) .use(cors({ origin: 'http://localhost:3001', // 匹配你的前端域名 credentials: true, allowedHeaders: '*', exposedHeaders: '*' })) }
这里明确指定origin为你的前端地址,比用通配符*更严谨(尤其是如果你的请求带Credentials的话,*是不允许的)。
3. 确保重新部署了函数(针对线上环境)
如果你是在测试AWS上的线上函数,修改配置后需要重新运行serverless deploy来更新API Gateway的CORS设置。API Gateway不会自动同步你的Serverless配置,必须重新部署才能生效。
4. 清空浏览器缓存或用无痕模式测试
浏览器有时候会缓存CORS相关的响应头,导致新的配置不生效。你可以尝试清空浏览器缓存,或者直接用无痕窗口测试,排除缓存的影响。
额外检查:避免重复设置CORS头部
你之前在formatJSONResponse里手动添加了CORS头部,同时又用了Middy的CORS中间件,这可能导致头部重复或者冲突。建议你保留其中一种方式即可——更推荐用Middy的中间件,因为它会自动处理OPTIONS预请求等细节。
你可以先注释掉formatJSONResponse里的自定义headers,让Middy的中间件来处理:
export const formatJSONResponse = (response: Record<string, unknown>) => { return { statusCode: 200, // 暂时注释掉手动添加的headers // headers: { // 'Access-Control-Allow-Origin': '*', // 'Access-Control-Allow-Credentials': true, // }, body: JSON.stringify(response) } }
按照上面的步骤调整后,再测试你的POST请求,应该就能解决CORS问题了。
内容的提问来源于stack exchange,提问作者nyphur

