Cloud Functions 的 https.onCall
触发器是一个采用特定格式的请求和响应的 HTTPS 触发器。本部分介绍了客户端 SDK 实现 API 时使用的 HTTPS 请求和响应的格式规范。如果使用 Android SDK、Apple 平台 SDK 或 Web SDK 无法满足您的需求,这些信息可能对您会很有用。
请求格式:标头
向 Callable 触发器端点发送的 HTTP 请求必须是带有以下标头的 POST
:
- 必填:
Content-Type: application/json
- 允许使用可选的
; charset=utf-8
。
- 允许使用可选的
- 可选:
Authorization: Bearer <token>
- 发出请求的已登录用户的 Firebase Authentication 证用户 ID 令牌。后端会自动验证此令牌并在处理程序的
context
中提供此令牌。如果此令牌无效,则请求会被拒绝。
- 发出请求的已登录用户的 Firebase Authentication 证用户 ID 令牌。后端会自动验证此令牌并在处理程序的
- 可选:
Firebase-Instance-ID-Token: <iid>
- 来自 Firebase 客户端 SDK 的 FCM 注册令牌。这必须是一个字符串。可以在处理程序的
context
中找到此令牌。它用于定位推送通知。
- 来自 Firebase 客户端 SDK 的 FCM 注册令牌。这必须是一个字符串。可以在处理程序的
- 可选:
X-Firebase-AppCheck: <token>
- 由发出请求的客户端应用提供的 Firebase App Check 令牌。后端会自动验证此令牌并对其进行解码,从而在处理程序的
context
中注入appId
。如果令牌无法验证,请求将被拒绝。(适用于 SDK 3.14.0 及更高版本)
- 由发出请求的客户端应用提供的 Firebase App Check 令牌。后端会自动验证此令牌并对其进行解码,从而在处理程序的
如果请求中还包含任何其他标头,则会被拒绝(如下面的响应文档中所述)。
注意:在 JavaScript 客户端中,这些请求会触发 CORS OPTIONS
预检,这是因为:
- 不允许使用
application/json
。必须为text/plain
或application/x-www-form-urlencoded
。 Authorization
标头不是 CORS 安全名单中的请求标头。- 同样,其他标头也是不允许使用的。
Callable 触发器会自动处理这些 OPTIONS
请求。
请求正文
HTTP 请求的正文应该是具有以下任何字段的 JSON 对象:
- 必需:
data
- 传递给函数的参数。这可以是任何有效的 JSON 值。该参数会根据如下所述的序列化格式自动解码为本机 JavaScript 类型。
如果请求中有任何其他字段,则后端会将该请求视为格式错误,并拒绝该请求。
响应格式:状态代码
以下几种情况可能导致响应中的错误会有不同的 HTTP 状态代码和字符串状态代码。
如果在调用
client
触发器之前发生 HTTP 错误,则响应不会作为客户端函数进行处理。例如,如果客户端尝试调用不存在的函数,则它会收到404 Not Found
响应。如果调用了客户端触发器,但请求的格式不正确(例如不是 JSON、包含无效字段或缺少
data
字段),则请求将被拒绝并返回400 Bad Request
,错误代码为INVALID_ARGUMENT
。如果请求中提供的身份验证令牌无效,则请求将被拒绝并返回
401 Unauthorized
,错误代码为UNAUTHENTICATED
。如果请求中提供的 FCM 注册令牌无效,那么这种行为属于未定义的行为。系统并不会针对每个请求检查令牌,但使用这种令牌通过 FCM 发送推送通知时除外。
如果调用了 Callable 触发器,但调用失败并产生未处理的异常或返回失败的 Promise,则请求将被拒绝并返回
500 Internal Server Error
,错误代码为INTERNAL
。这可以避免编码错误意外地向最终用户显示。如果使用为可调用函数提供的 API 调用了 Callable 并返回显式错误条件,则请求会失败。系统会根据错误状态与 HTTP 状态的官方映射(如 code.proto 中所定义)返回 HTTP 状态代码。返回的具体错误代码、消息和详细信息会在响应正文中进行编码(如下所述)。这意味着如果函数返回状态为
OK
的显式错误,则响应的状态为200 OK
,但error
字段会在响应中进行设置。如果客户端触发器成功,则响应状态为
200 OK
。
响应格式:标头
响应具有以下标头:
Content-Type: application/json
- 允许使用可选的
; charset=utf-8
。
响应正文
来自客户端端点的响应始终是 JSON 对象。它至少包含 result
或 error
以及任何可选字段。如果响应不是 JSON 对象,或者不包含 data
或 error
,则客户端 SDK 应将请求视为失败并返回 Google 错误代码 INTERNAL (13)
。
error
- 如果此字段存在,则请求将被视为失败,无论 HTTP 状态代码为何或data
是否也存在。此字段的值应该是一个 JSON 对象(采用为错误制定的标准 Google Cloud HTTP 映射格式),并且包含status
、message
及(可选)details
字段。不应包含code
字段。如果status
字段未设置或是无效值,则客户端应根据 code.proto 将状态视为INTERNAL
。如果存在details
,则其包含在客户端 SDK 中随附于错误的用户信息中(若有)。
注意:这里的details
字段是用户提供的值。它未必是像在 GoogleStatus
格式中那样由原型键控的值列表。result
- 函数返回的值。这可以是任何有效的 JSON 值。firebase-functions SDK 会自动将用户返回的值编码为这种 JSON 格式。客户端 SDK 会根据下文所述的序列化格式自动将这些参数解码为本机类型。
如果存在其他字段,则应忽略它们。
序列化
无论是请求还是响应,任意数据载荷的序列化格式是相同的。
为保证平台一致性,这些数据载荷会像 proto3 协议缓冲区中 Any
字段的值一样,使用标准 JSON 映射进行 JSON 编码。简单类型(如 null
、int
、double
或 string
)的值将直接编码,不会包含它们的显式类型。因此,float
和 double
的编码方式相同,并且您可能不知道在调用的另一端收到了哪一个。对于非 JSON 本机类型,将使用相应值的类型化 proto3 编码。如需了解详情,请参阅任何 JSON 编码的文档。
允许使用以下类型:
- null -
null
- 整数(有符号或无符号,最多 32 位)- 例如
3
或-30
。 - 浮点数 - 例如
3.14
- 双精度浮点数 - 例如
3.14
- 布尔值 -
true
orfalse
- 字符串 - 例如
"hello world"
- map<string, any=""> - 如
{"x": 3}
</string,> - 列表
- 例如 [1, 2, 3]
- 长整型(有符号或无符号,最多 64 位)- [详见下文]
不支持 float
和 double
的 NaN
和 Infinity
值。
请注意,long
是 JSON 中通常不允许的特殊类型,但被 proto3 规范涵盖。例如,这些类型的编码方式如下:
长整型
{
'@type': 'type.googleapis.com/google.protobuf.Int64Value',
'value': '-123456789123456'
}
无符号长整型
{
'@type': 'type.googleapis.com/google.protobuf.UInt64Value',
'value': '123456789123456'
}
一般情况下,@type
键应视为已预留,并且不应该用于传入的映射。
由于没有将相应类型指定为简单类型,因此某些值会在在线传递后改变类型。传入的 float
将变为 double
。short
变为 int
,以此类推。在 Android 中,列表值支持 List
和 JSONArray
。在这些情况下,传入 JSONArray 将生成一个 List
。
如果包含未知 @type
字段的映射被去序列化,则会被保留为映射。这样,开发者可以将包含新类型的字段添加到返回值中,而不会使较旧的客户端发生服务中断。
代码示例
此部分中的示例说明如何对以下内容编码:
- Swift 中的 callable.call 示例
- 调用的成功响应
- 调用的失败响应
要编码的 Swift 中的 Callable.call 示例
callable.call([
"aString": "some string",
"anInt": 57,
"aFloat": 1.23,
"aLong": -123456789123456 as Int64
])
请求标头:
Method: POST
Content-Type: application/json; charset=utf-8
Authorization: Bearer some-auth-token
Firebase-Instance-ID-Token: some-iid-token
请求正文:
{
"data": {
"aString": "some string",
"anInt": 57,
"aFloat": 1.23,
"aLong": {
"@type": "type.googleapis.com/google.protobuf.Int64Value",
"value": "-123456789123456"
}
}
}
要编码的响应
return {
"aString": "some string",
"anInt": 57,
"aFloat": 1.23
};
成功响应标头:
200 OK
Content-Type: application/json; charset=utf-8
成功响应正文:
{
"response": {
"aString": "some string",
"anInt": 57,
"aFloat": 1.23
}
}
要编码的失败响应
throw new HttpsError("unauthenticated", "Request had invalid credentials.", {
"some-key": "some-value"
});
失败的响应标头:
401 UNAUTHENTICATED
Content-Type: application/json; charset=utf-8
失败的响应正文:
{
"error": {
"message": "Request had invalid credentials.",
"status": "UNAUTHENTICATED",
"details": {
"some-key": "some-value"
}
}
}