【发布时间】:2018-08-27 08:50:17
【问题描述】:
已解决
以下问题只是由我的 Lambda 中构造的响应对象的 body 属性引起的。我忘记对数据进行字符串化,返回body: data 而不是body: JSON.stringify(data)。响应的这个问题似乎触发了 API Gateway 的错误,导致请求失败并带有一些相当混乱的错误消息。
问题
我正在使用 React、Serverless 和 Stripe API 开发一个电子商务网站。我的前端 React 应用程序正在使用 Axios 向我的 Lambda 函数发出 GET 请求,该函数已通过 API Gateway 公开。 Lambda 函数依次查询 Stripe API 并将 Stripe 响应数据返回到我的 React 应用程序。但是,当我的 React 应用程序尝试调用 Lambda 时,我遇到了 CORS 问题,它收到以下错误:
Failed to load: No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:3000' is therefore not allowed access. The response had HTTP status code 502.
在 Insomnia 中查询 Lambda 端点会返回一个带有 { "message": "internal server error" } 的 502 响应。但是从终端执行 Lambda 函数中的serverless invoke 命令成功返回了 Stripe 数据。
我正在为我的 serverless.yml 文件中的函数启用 cors,并按照this Serverless blog post 中的建议在我的 Lambda 代码响应中包含 'Access-Control-Allow-Origin': '*',我还尝试将以下标头的各种组合添加到我的 Lambda 响应和我的 Axios 请求基于在 this issue on Axios 和 this issue on Serverless 上找到的建议。我已多次删除并重新部署该服务并
Lambda 响应标头
headers: {
'Access-Control-Expose-Headers': 'Access-Control-Allow-Origin',
'Access-Control-Allow-Credentials': true,
'Content-Type': 'application/json',
'Access-Control-Allow-Origin': '*',
},
反应/Axios 配置
{
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json'
},
crossDomain: true
}
目前我的代码如下:
反应应用
import Axios from 'axios';
import { GET_PRODUCTS_URL } from '../config';
export default () => {
return Axios
.get(GET_PRODUCT_URL, {
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json'
},
crossDomain: true
})
.then(({ data }) => data)
.catch(console.log);
}
拉姆达
import Stripe from 'stripe';
const apiKey = process.env.STRIPE_SECRET_KEY;
const stripe = Stripe(apiKey);
module.exports.handler = (event, context, callback) => {
return stripe.products
.list()
.then(({ data }) => {
const response = {
statusCode: 200,
headers: {
'Access-Control-Expose-Headers': 'Access-Control-Allow-Origin',
'Access-Control-Allow-Credentials': true,
'Content-Type': 'application/json',
'Access-Control-Allow-Origin': '*',
},
body: data,
};
callback(null, response);
})
.catch(console.log);
}
无服务器.yml
service: srd
provider:
name: aws
runtime: nodejs6.10
stage: ${opt:stage, self:custom.defaultStage}
region: eu-west-1
memorySize: 256
timeout: 6
versionFunctions: true
plugins:
- serverless-plugin-optimize
- serverless-plugin-scripts
package:
individually: true
functions:
get-products:
handler: lambda/get-products.handler
name: srd-get-products-${self:provider.stage}
description: 'get srd products from stripe'
environment:
STRIPE_PUBLISHABLE_KEY: ${self:custom.stripe_publishable_key.${self:provider.stage}}
STRIPE_SECRET_KEY: ${self:custom.stripe_secret_key.${self:provider.stage}}
events:
- http:
path: products
method: get
cors: true
custom:
defaultStage: dev
stripe_publishable_key:
dev: ${file(env.yml):STRIPE_DEV_PUBLISHABLE_KEY}
live: ${file(env.yml):STRIPE_LIVE_PUBLISHABLE_KEY}
stripe_secret_key:
dev: ${file(env.yml):STRIPE_DEV_SECRET_KEY}
live: ${file(env.yml):STRIPE_LIVE_SECRET_KEY}
我已经为此工作了几个小时,非常感谢任何见解。
编辑/添加 从 CLI 发出选项请求会返回以下内容:
HTTP/1.1 200 OK
Content-Type: application/json
Content-Length: 0
Connection: keep-alive
Date: Mon, 19 Mar 2018 06:52:12 GMT
x-amzn-RequestId: 0d10c9d1-2b42-11e8-b270-a723e367048e
Access-Control-Allow-Origin: *
Access-Control-Allow-Headers: Content-Type,X-Amz-Date,Authorization,X-Api-Key,X-Amz-Security-Token,X-Amz-User-Agent
Access-Control-Allow-Methods: OPTIONS,GET
Access-Control-Allow-Credentials: false
X-Cache: Miss from cloudfront
Via: 1.1 e40b14deb4a844594f746b751f632677.cloudfront.net (CloudFront)
X-Amz-Cf-Id: eMvu3Ke7m7GNFCFgIOGVJmoObFwYMeEt4o8AByoipfMn1nXIi9Vo0g==
【问题讨论】:
-
根据日志,502 来自哪里(在 AWS 端)? Lambda 代码是否命中?
-
现在已经解决了,但要回答你的问题。是的,lambda 代码被命中了。似乎是因为我忘记对响应正文数据进行字符串化,这导致 API 网关出错并导致请求失败。
标签: aws-lambda axios aws-api-gateway serverless-framework http-status-code-502