在 Angular 11 中,如何通过 API Gateway 将应用程序/json HTTP POST 到 AWS Lambda?
Posted
技术标签:
【中文标题】在 Angular 11 中,如何通过 API Gateway 将应用程序/json HTTP POST 到 AWS Lambda?【英文标题】:In Angular 11, how to HTTP POST application/json to AWS Lambda via API Gateway? 【发布时间】:2021-07-30 16:55:00 【问题描述】:我计划在 AWS Amplify 中托管一个 Angular 应用程序。它为其 REST API 调用 Lambda 函数。我有一个大部分成功的测试应用程序,但它不能做这件事:将 JSON 数据发布到托管 URI。
在浏览器中,我有一个 Angular 客户端,它有一个按钮,单击时会调用 HttpClient.post
或 HttpClient.request
。我有多个我测试过的后端服务器:(1) NestJs/Express,(2) sam local start-api
和 (3) AWS 托管。本地sam
服务器和托管环境同步并使用相同的template.yaml
。所有三台服务器都接受Content-Type
中的application/json
和application/x-www-form-urlencoded
。
Content-Type
、服务器实例和 HttpClient 方法(post
或 request(“POST”,...)
)的每个组合都可以在托管的 lambda 函数中使用 Json。它似乎立即被拒绝了。
该调用从未进入 Cloudwatch 日志,我猜这意味着它的格式不正确并被我不知道是什么过滤掉了。我对 AWS 很陌生,不熟悉它的特殊性,所以我不确定我可以在托管环境中打开哪些日志记录来捕获它。它失败得如此之快,从来没有到达日志,更不用说我的代码了,我很好奇它有什么问题。
Curl with Json 也可以:curl -X POST -H "Content-Type:application/json" ...
。
总之,当使用.post()
或.request()
方法将Json 或Form 样式发布到非AWS 和本地AWS Web 服务器时,一切都很好。表单样式 POST 到 AWS 托管(通过 API 网关)也可以工作。使用 Json 手工制作的命令行 POST 也适用于托管的 AWS(通过 API 网关)。
只有从 Angular 托管的 POST 到 AWS 不起作用。
ETA 这是一个代码 sn-p:
const URI_LOCAL = “/api/music”;
const URI_HOSTED = “https://…amazonaws.com/Prod/api/music”;
const headers_j = new HttpHeaders( 'Content-Type': 'application/json' );
const album = "title":"Mullet Beginnings","band":"The Wallabys”;
const body_j = JSON.stringify(album);
// This fails
let res_j$ = this.http.post<any>(URI_HOSTED, body_j, headers: headers_j );
// This works
const headers_x = new HttpHeaders( 'Content-Type': 'application/x-www-form-urlencoded' );
const body_x = 'title=Dancing Beers&band=Evils Ypsley’;
let res_x$ = this.http.post<any>(URI_HOSTED, body_x, headers: headers_x );
我也尝试过传递 album
而不是 body_j
。两个选项(对象或 JSON 字符串)都适用于 URI_LOCAL。对 URI_HOSTED 都不起作用。
某个地方的某个人必须成功地将 Json 从 Angular 发布到 AWS 托管环境。关于我做错了什么的任何提示?
[ETA] 这是来自浏览器控制台的错误日志:
[Error] Preflight response is not successful
[Error] XMLHttpRequest cannot load https://_SNIP_.amazonaws.com/Prod/api/rebuild due to access control checks.
[Log] POST: (main.js, line 194)
HttpErrorResponse
error: XMLHttpRequestProgressEvent isTrusted: true, position: 0, totalSize: 0, lengthComputable: false, loaded: 0, …
headers: HttpHeaders normalizedNames: Map, lazyUpdate: null, headers: Map
message: "Http failure response for https://_SNIP_.amazonaws.com/Prod/api/rebuild: 0 Unknown Error"
name: "HttpErrorResponse"
ok: false
status: 0
statusText: "Unknown Error"
url: "https://_SNIP_.amazonaws.com/Prod/api/rebuild"
[Error] Failed to load resource: Preflight response is not successful (rebuild, line 0)
client | content-type | server | Result |
---|---|---|---|
HttpClient.post | json | aws hosted | Failure |
HttpClient.request | json | aws hosted | Failure |
curl | json | aws hosted | Success |
HttpClient.post | json | sam local | Success |
HttpClient.post | json | nestjs | Success |
HttpClient.post | x-www-form | aws hosted | Success |
HttpClient.post | x-www-form | sam local | Success |
HttpClient.post | x-www-form | nestjs | Success |
【问题讨论】:
【参考方案1】:听起来像CORS 问题。
您不仅需要在 API Gateway 中启用 CORS,而且您的 Lambda API Gateway 响应还必须包含访问控制标头。
您的回复应如下所示:
response =
statusCode: 204,
headers:
"Access-Control-Allow-Headers" : "Content-Type",
"Access-Control-Allow-Origin": "https://www.example.com",
"Access-Control-Allow-Methods": "OPTIONS,POST,GET",
,
;
return response;
;
【讨论】:
谢谢。这正是它。我稍微编辑了您的示例以匹配我使用的内容。 太棒了。不久前,这让我头疼了好几个小时。 24 小时把我的头撞到墙上。所以,是的,我就在你身边。如此神奇的魔力让一切都可以端到端地工作。我想我永远不会忘记 CORS,现在。我认为它仅用于客户端跨站点脚本,而不是询问服务器的功能。 我知道 CORS,但我不知道我必须在回复中返回标题。很高兴它得到了解决。以上是关于在 Angular 11 中,如何通过 API Gateway 将应用程序/json HTTP POST 到 AWS Lambda?的主要内容,如果未能解决你的问题,请参考以下文章
如何使用 Angular 在 mat-header-cell 行中呈现动态数据
如何通过 API App 公开 Azure APIM API?