Vue & Axios + AWS API Gateway & Lambda - CORS + POST 不起作用

Pat*_*man 1 amazon-web-services vue.js aws-lambda aws-api-gateway axios

我正在尝试通过 AWS API Gateway 创建一个 API 测试函数,以及一个通过 Axios 的 Vue 应用程序调用的 Lambda 函数。它应该从输入元素发送姓名和电子邮件。每次我收到此错误时:

Access to XMLHttpRequest at '[API Gateway URL]' from origin 'http://localhost:8080' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: It does not have HTTP ok status.
Run Code Online (Sandbox Code Playgroud)

我已在 API 网关设置中的每个步骤/资源上启用了 CORS(根据本文)。下面是 Vue 组件的代码:

<template>
<div data-app>
        <div class="cell" id="testForm">
    {{responseMsg}}

       <label>Name</label>
       <input v-model="name" type="text" placeholder="Name">
       <label>Email Address</label>
       <input v-model="email" type="email" placeholder="Email Address">
       <button v-on:click="formFunction">Submit</button>
   
   </div>
</div>
</template>

<script>
import axios from 'axios';

export default {
    name: "formtest",
    data: function () {
        return {name: '',
        email: '',
        responseMsg: 'No response yet!'}
    },
    methods: {
        formFunction: function () {
            const formObj = {
                name: this.name,
                email: this.email
            }
            const reqURL = [API gateway URL];
            axios.post(reqURL, formObj)
    .then(response => {
        console.log(response);
        });

        }
    }
}

</script>
Run Code Online (Sandbox Code Playgroud)

这是我的 Lambda 函数:

exports.handler = async (event) => {
    const resString = 'Hello ' + event.name + ", your email address is " + event.email

    const response = {
        statusCode: 200,
         headers: {
            "Access-Control-Allow-Headers" : "Content-Type",
            "Access-Control-Allow-Origin": "*",
            "Access-Control-Allow-Methods": "OPTIONS,POST,GET"
        },
        body: resString,
    };
    return response;
};
Run Code Online (Sandbox Code Playgroud)

我在这里可能做错了什么?

Rub*_*Rub 5

笔记:

  • 我下面的答案是针对像您这样的问题(我的)编写的,但其路线需要身份验证(例如 Cognito)。无论如何,该解决方案也适用于您的情况。
  • 如果我没记错的话,您的 axios 请求具有/请求 JSON 数据类型,这使其成为“非简单请求”(更多信息请参见下面的链接)。
  • 您的问题与 Vue 或 Axios 无关(我使用的是相同的)。 在此输入图像描述

回答

在某些条件下,POST/GET 请求会变成非简单请求。

该非简单请求将向同一目的地发出飞行前 OPTIONS 请求以验证某些内容,如果对响应感到满意,则执行您的原始请求。

为什么会发送 OPTIONS 请求?我可以禁用它吗?

如果路径 (API_url/private) 需要身份验证,则 OPTIONS 请求将失败,并且您将永远*无法设法让您的 POST/GET 请求通过。

如果路径不需要身份验证,但对 OPTIONS 的响应不提供 CORS 响应,则 OPTIONS 请求将失败,并且您将永远*无法设法让您的 POST/GET 请求通过。

*如果使用浏览器上运行的东西,因为浏览器确实非常关心CORS。如果您在浏览器外部(例如使用“curl”),您的请求将有效,因为它不关心 CORS 响应/参数。

解决方案很简单但并不明显:

如果你有一个

route       verb            Authentication      integration
/private    POST/GET        yes                 lambda-private
Run Code Online (Sandbox Code Playgroud)

然后你需要创建一个额外的

route       verb            Authentication      integration
/private    POST/GET        yes                 lambda-private
/private    OPTIONS         no                  lambda-CORS-response
Run Code Online (Sandbox Code Playgroud)

因此,您的飞行前请求将得到良好的响应,并且 POST/GET 请求将到达您想要的目的地。

这些是集成(使用不同的 lambda)

在此输入图像描述

这里是授权者(只有 POST 有授权者)

在此输入图像描述

如果您这样做,它将参加所有选项,无论路线如何(未验证)

route       verb            Authentication      integration
/{proxy+})  OPTIONS         no                  lambda-CORS-response
Run Code Online (Sandbox Code Playgroud)

这里以某种方式解释了这一点,但他们并没有说您需要创建“额外的 lambda 函数”来对该路由/动词做出响应。

https://docs.aws.amazon.com/apigateway/latest/developerguide/http-api-cors.html https://docs.aws.amazon.com/apigateway/latest/developerguide/how-to-cors.html

路线 https://docs.aws.amazon.com/apigateway/latest/developerguide/http-api-develop-routes.html#http-api-develop-routes.evaluation

在找到解决方案之前,我探索了其他选择。以下是我的发现。如果有人发现信息有误,我们非常乐意纠正该信息(声明需要以某种方式得到支持)。


问:我正在使用“HTTP API”(AWS)。我是否需要切换到“REST API”来解决此问题?

答:在某个阶段我是这么认为的。但不行,只需按照上面的说明操作即可。

但是,“REST API”有更多选项(它们的成本也更高),也许您不需要执行上述操作。如果有人对此有见解,我将很乐意更新这部分。然而,拥有更多选项也可能意味着“设置更复杂”。


问:那么如果我需要自己提供 CORS 响应,那么 API 上的 CORS 配置有何用途?

答:显然仅适用于“200 型”回复。-> https://enable-cors.org/server_awsapigateway.html

仅当我自己提供 CORS 响应时,我的功能才起作用。


问:我可以通过在 GET 而不是 POST 中提交数据来避免飞行前的 OPTIONS 请求吗

答:不,如果您的请求满足非简单请求的条件,无论如何都会发生。


问:为什么我的应用程序/网页中使用 Axios 的 POST/GET 请求失败并抱怨 CORS,但“curl”却可以正常运行。

A: 'curl' 不关心 CORS,浏览器非常关心。至少“curl”可以让您知道“有些东西正在工作”,但您需要做一些额外的工作才能使其完全正常。