Aller au contenu principal
Version: 2.0.0

Serverless 触发器 POST 情况差异

阿里云 API 网关

阿里云 API 网关支持不同类型的的 POST 请求。

入参透传的 POST

网关配置如下。

网关透传的 event 特征为有 body 字段以及 isBase64Encoded 为 true,解码比较容易,直接解 base64 即可。

info

透传了之后,即为所有的结果交给函数处理。

示例一 (text/html)

下面的 event,是一个最简单的透传示例,因为其中的 content-type  为 text/html ,所以 body 传递过来 base64 解码的结果也同样是字符串。

{
"body": "eyJjIjoiYiJ9",
"headers": {
"x-ca-dashboard-action": "DEBUG",
"x-ca-dashboard-uid": "125087",
"x-ca-stage": "RELEASE",
"x-ca-dashboard-role": "USER",
"user-agent": "Apache-HttpClient/4.5.6 (Java/1.8.0_172)",
"accept-encoding": "gzip,deflate",
"content-md5": "Kry+hjKjc2lvIrwoJqdY9Q==",
"content-type": "text/html; charset=utf-8"
},
"httpMethod": "POST",
"isBase64Encoded": true,
"path": "/api/321",
"pathParameters": {
"userId": "321"
},
"queryParameters": {}
}

函数结果。

ctx.request.body; // '{"c":"b"}'   => string

示例二(application/json)

使用 content-type  为 application/json ,这样框架认为是一个 JSON,会自动被 JSON.parse。

{
"body": "eyJjIjoiYiJ9",
"headers": {
"X-Ca-Dashboard-Action": "DEBUG",
"X-Ca-Dashboard-Uid": "125087",
"X-Ca-Stage": "RELEASE",
"X-Ca-Dashboard-Role": "USER",
"User-Agent": "Apache-HttpClient/4.5.6 (Java/1.8.0_172)",
"Accept-Encoding": "gzip,deflate",
"Content-MD5": "Kry+hjKjc2lvIrwoJqdY9Q==",
"Content-Type": "application/json; charset=utf-8"
},
"httpMethod": "POST",
"isBase64Encoded": true,
"path": "/api/321",
"pathParameters": {
"userId": "321"
},
"queryParameters": {}
}

函数结果。

ctx.request.body; // {"c":"b"}   => object

示例三 (application/x-www-form-urlencoded)

使用 content-type  为 application/x-www-form-urlencoded ,这个时候网关不会以 base64 格式透传,这也是前端原生表单的默认提交类型。

info

在 API 网关侧测试,保持“入参透传”下,似乎没有效果,于是我换到了 Postman 进行测试。

Postman 模拟请求如下:

函数拿到的 event 值如下。

{
"body": "{\"c\":\"b\"}",
"headers": {
"accept": "*/*",
"cache-control": "no-cache",
"user-agent": "PostmanRuntime/7.24.1",
"postman-token": "feb51b11-9103-463a-92ff-73076d37b683",
"accept-encoding": "gzip, deflate, br",
"content-type": "application/x-www-form-urlencoded"
},
"httpMethod": "POST",
"isBase64Encoded": false,
"path": "/api/321",
"pathParameters": {
"userId": "321"
},
"queryParameters": {}
}

函数结果。

ctx.request.body; // {"c":"b"}   => object

入参映射的 POST

网关配置选择入参映射之后,body 数据类型有两种选择。

一旦选了映射,整个函数拿到的 Headers 中就 没有了 content-type

这个时候,网关的返回 event 为

{
"body": "eyJjIjoiYiJ9",
"headers": {
"X-Ca-Dashboard-Action": "DEBUG",
"X-Ca-Dashboard-Uid": "111111",
"X-Ca-Dashboard-Role": "USER"
},
"httpMethod": "POST",
"isBase64Encoded": true,
"path": "/api/321",
"pathParameters": {
"userId": "321"
},
"queryParameters": {}
}

函数由于默认没有拿到 header 头,只会对 base64 的结果做处理,结果为字符串。

ctx.request.body; // '{"c":"b"}'   => string

阿里云 HTTP 触发器

函数提供的 HTTP 触发器(和网关不同)。

普通 POST(application/json)

验证代码如下。

const body = this.ctx.request.body;
return {
type: typeof body,
body,
};

字符串格式。

ctx.request.body; // "bbb"   => string

JSON 格式

ctx.request.body; // {"b":"c"}   => object

表单(application/x-www-form-urlencoded)

ctx.request.body; // {"b":"c"}   => object

文件上传(Binary)

暂未支持

腾讯云网关

腾讯云提供单独网关。

普通 POST(application/json)

验证代码如下。

const body = this.ctx.request.body;
return {
type: typeof body,
body,
};

使用 Postman 请求。

字符串格式,正常解析。

ctx.request.body; // "bbb"   => string

JSON 格式,能正常解析。

ctx.request.body; // {"c":"b"}   => object

表单(application/x-www-form-urlencoded)

正常解析为 JSON。

ctx.request.body; // {"c":"b"}   => object