将表单从客户端发布到 AWS API 网关功能时如何修复 CORS 错误?

Posted

技术标签:

【中文标题】将表单从客户端发布到 AWS API 网关功能时如何修复 CORS 错误?【英文标题】:How to fix CORS error when posting form from client to AWS API gateway function? 【发布时间】:2019-05-20 10:38:24 【问题描述】:

我的前端 React 应用程序上有一个联系表单,我想将其发布到 API 网关后面的 Lambda 函数,而 API 网关又在其顶部有一个自定义域。

我的前端在域 dev.example.com:3000 上运行 我的 API 网关在 contact.example.com

此外,我已经使用无服务器创建了我的 Lambda 函数,并在我的 YAML 文件中启用了 CORS:

# serverless.yml

service: contact-form-api

custom:
  secrets: $file(secrets.json)

provider:
  name: aws
  runtime: nodejs8.10
  stage: $self:custom.secrets.NODE_ENV
  region: us-east-1
  environment: 
    NODE_ENV: $self:custom.secrets.NODE_ENV
    EMAIL: $self:custom.secrets.EMAIL
    DOMAIN: $self:custom.secrets.DOMAIN
  iamRoleStatements:
    - Effect: "Allow"
      Action:
        - "ses:SendEmail"
      Resource: "*"

functions:
  send:
    handler: handler.send
    events:
      - http:
          path: email/send
          method: post
          cors: true

我正在使用 AXios 发出发生在客户端的发布请求:

const data = await axios.post(
    "https://contact.example.com/email/send",
    formData,
    
        "Content-Type": "application/json",
    
)

我得到的错误是:

从源“http://dev.example.com:3000”访问“https://contact.example.com/email/send”处的 XMLHttpRequest 已被 CORS 策略阻止:“Access-Control-Allow-Origin”标头包含无效值“example.com”。

我原以为将前端和 API 放在同一个域中可以在本地解决任何 cors 错误(尽管我在本地欺骗 dev.example.com)以便进行测试)。我还认为我的 YAML 文件中的 cors 设置会绕过它。

有人知道为什么我仍然会收到此 CORS 错误吗?

编辑:显示在 Lambda 函数中运行的处理程序代码 // handler.js

const aws = require('aws-sdk')
const ses = new aws.SES()
const myEmail = process.env.EMAIL
const myDomain = process.env.DOMAIN

function generateResponse (code, payload) 
  return 
    statusCode: code,
    headers: 
      'Access-Control-Allow-Origin': "*",
      'Access-Control-Allow-Headers': 'x-requested-with',
      'Access-Control-Allow-Credentials': true
    ,
    body: JSON.stringify(payload)
  


function generateError (code, err) 
  console.log(err)
  return 
    statusCode: code,
    headers: 
      'Access-Control-Allow-Origin': "*",
      'Access-Control-Allow-Headers': 'x-requested-with',
      'Access-Control-Allow-Credentials': true
    ,
    body: JSON.stringify(err.message)
  


function generateEmailParams (body) 
  const  email, name, content  = JSON.parse(body)
  console.log(email, name, content)
  if (!(email && name && content)) 
    throw new Error('Missing parameters! Make sure to add parameters \'email\', \'name\', \'content\'.')
  

  return 
    Source: myEmail,
    Destination:  ToAddresses: [myEmail] ,
    ReplyToAddresses: [email],
    Message: 
      Body: 
        Text: 
          Charset: 'UTF-8',
          Data: `Message sent from email $email by $name \nContent: $content`
        
      ,
      Subject: 
        Charset: 'UTF-8',
        Data: `You received a message from $myDomain!`
      
    
  


module.exports.send = async (event) => 
  try 
    const emailParams = generateEmailParams(event.body)
    const data = await ses.sendEmail(emailParams).promise()
    return generateResponse(200, data)
   catch (err) 
    return generateError(500, err)
  

【问题讨论】:

因为'Access-Control-Allow-Origin' 标头的值应该是*http://dev.example.com:3000 ...即协议和端口需要匹配源 你的意思是axios post请求中的header吗? 抱歉,我认为很明显我在谈论 'Access-Control-Allow-Origin' 标头 - 我只是想仔细检查一下,因为我确实尝试了您的建议,但无济于事。我尝试同时设置 "Access-Control-Allow-Origin": "dev.example.com:3000""Access-Control-Allow-Origin": "*" 但仍然遇到相同的 CORS 错误 a) 我说的是http://dev.example.com:3000 而不是dev.example.com:3000 并且b) 我看不到你在做任何事情,所以也许你做错了(在浏览器中查看您实际上是从服务器获取的标头) 【参考方案1】:

您应该将 HTTP 请求标头添加为“内容类型”:

现在,转到集成请求,并将映射模板更改如下:

希望,它会有所帮助。并且不要忘记在测试之前部署 API。

【讨论】:

以上是关于将表单从客户端发布到 AWS API 网关功能时如何修复 CORS 错误?的主要内容,如果未能解决你的问题,请参考以下文章

使用 REST 客户端 POSTMAN 使用 api 密钥调用 AWS api 网关端点

从帖子正文读取时,AWS API 网关 CORS 错误

Terraform 不会将 step 功能部署到 API 网关

AWS:使用 cloudformation 模板将 WAF 附加到 api 网关

AWS Cloudformation 将 API 密钥链接到 API 网关

AWS API 网关和 EC2 服务代理