https.onCall 的協議規範

Cloud Functions 的https.onCall觸發器是 HTTPS 觸發器,具有特定的請求和回應格式。本節提供客戶端 SDK 用於實作 API 的 HTTPS 請求和回應格式的規格。如果使用 Android、Apple 平台或 Web SDK 無法滿足您的要求,則此資訊可能對您有用。

請求格式:標頭

可呼叫觸發器端點的 HTTP 請求必須是具有以下標頭的POST

  • 必需: Content-Type: application/json
    • 一個可選的; charset=utf-8允許使用; charset=utf-8
  • 可選: Authorization: Bearer <token>
    • 發出要求的登入使用者的 Firebase 驗證使用者 ID 令牌。後端自動驗證此令牌並使其在處理程序的context中可用。如果令牌無效,則請求被拒絕。
  • 可選: Firebase-Instance-ID-Token: <iid>
    • 來自 Firebase 用戶端 SDK 的 FCM 註冊令牌。這必須是一個字串。這在處理程序的context中可用。它用於定位推播通知。
  • 可選: X-Firebase-AppCheck: <token>
    • 發出請求的用戶端應用程式提供的 Firebase 應用程式檢查權杖。後端會自動驗證此令牌並對其進行解碼,將appId注入處理程序的context中。如果無法驗證令牌,則請求將被拒絕。 (適用於 SDK >=3.14.0)

如果包含任何其他標頭,則請求將被拒絕,如下面的回應文件中所述。

注意:在 JavaScript 用戶端中,這些請求會觸發 CORS OPTIONS預檢,因為:

  • 不允許application/json 。它必須是text/plainapplication/x-www-form-urlencoded
  • Authorization標頭不是CORS 安全清單中的 request-header
  • 其他標頭同樣也是不允許的。

可呼叫觸發器會自動處理這些OPTIONS請求。

請求正文

HTTP 請求的正文應該是具有以下任意欄位的 JSON 物件:

  • 必需: data - 傳遞給函數的參數。這可以是任何有效的 JSON 值。它會根據下面描述的序列化格式自動解碼為本機 JavaScript 類型。

如果請求中存在任何其他字段,後端會認為該請求格式錯誤,並拒絕該請求。

回應格式:狀態碼

在多種情況下,可能會導致回應中的錯誤出現不同的 HTTP 狀態碼和字串狀態碼。

  1. 如果在呼叫client觸發器之前發生 HTTP 錯誤,則回應不會作為客戶端函數進行處理。例如,如果客戶端嘗試呼叫不存在的函數,它將收到404 Not Found回應。

  2. 如果呼叫客戶端觸發器,但請求的格式錯誤,例如不是 JSON、具有無效字段或缺少data字段,則請求將被拒絕並返回400 Bad Request ,錯誤代碼為INVALID_ARGUMENT

  3. 如果請求中提供的身份驗證令牌無效,則請求將被拒絕,並傳回401 Unauthorized ,錯誤代碼為UNAUTHENTICATED

  4. 如果請求中提供的 FCM 註冊令牌無效,則行為未定義。不會對每個請求檢查令牌,除非用於透過 FCM 發送推播通知。

  5. 如果呼叫可呼叫觸發器,但因未處理的異常而失敗或傳回失敗的承諾,則請求將被拒絕,並傳回500 Internal Server Error ,錯誤代碼為INTERNAL 。這可以防止編碼錯誤意外地暴露給最終用戶。

  6. 如果使用可呼叫函數提供的 API 呼叫可呼叫函數並傳回明確錯誤條件,則請求將失敗。傳回的 HTTP 狀態碼是基於錯誤狀態到 HTTP 狀態的官方映射,如code.proto中所定義。傳回的特定錯誤代碼、訊息和詳細資訊在回應正文中進行編碼,如下所述。這意味著,如果函數傳回狀態為OK明確錯誤,則回應的狀態為200 OK ,但error欄位在回應中設定。

  7. 如果客戶端觸發成功,則回應狀態為200 OK

回應格式:標頭

響應具有以下標頭:

  • Content-Type: application/json
  • 一個可選的; charset=utf-8允許使用; charset=utf-8

響應體

來自客戶端端點的回應始終是 JSON 物件。它至少包含resulterror以及任何可選字段。如果回應不是 JSON 對象,或不包含dataerror ,則用戶端 SDK 應將請求視為失敗,並顯示 Google 錯誤代碼INTERNAL (13)

  • error - 如果此欄位存在,則請求被視為失敗,無論 HTTP 狀態碼或data是否也存在。此欄位的值應該是標準Google Cloud HTTP 錯誤對應格式的 JSON 對象,其中包含statusmessage和(可選) details欄位。不應包含code字段。如果status欄位未設置,或是無效值,則用戶端應根據code.proto將狀態視為INTERNAL 。如果存在details ,則它會包含在客戶端 SDK 中錯誤所附加的任何用戶資訊中(如果適用)。
    注意:此處的details欄位是使用者提供的值。它不一定是像 Google Status格式那樣由原型類型鍵入的值清單。
  • result - 函數傳回的值。這可以是任何有效的 JSON 值。 firebase-functions SDK 會自動將使用者傳回的值編碼為這種 JSON 格式。客戶端 SDK 根據下面描述的序列化格式自動將這些參數解碼為本機類型。

如果存在其他字段,則應忽略它們。

序列化

請求和回應的任意資料有效負載的序列化格式是相同的。

為了平台一致性,這些使用標準 JSON 映射以 JSON 進行編碼,就好像它們是 proto3 協定緩衝區中的Any欄位的值一樣。簡單類型(例如nullintdoublestring的值直接編碼,且不包含其明確類型。因此, floatdouble的編碼方式相同,您可能不知道調用的另一端收到的是哪一個。對於非 JSON 原生的類型,將使用值的類型化 proto3 編碼。有關更多信息,請參閱任何 JSON 編碼的文檔

允許使用以下類型:

  • 空 - null
  • int (有符號或無符號,最多 32 位元) - 例如3-30
  • 浮動 - 例如3.14
  • 雙 - 例如3.14
  • 布林值 - truefalse
  • 字串 - 例如"hello world"
  • 地圖- 例如{"x": 3}
  • 清單- 例如[1, 2, 3]
  • 長(有符號或無符號,最多 64 位元)- [詳細資訊請見下文]

不支援floatdoubleNaNInfinity值。

請注意, long是 JSON 中通常不允許的特殊類型,但 proto3 規範涵蓋了它。例如,它們被編碼為:

長的

{
    '@type': 'type.googleapis.com/google.protobuf.Int64Value',
    'value': '-123456789123456'
}

無符號長

{
    '@type': 'type.googleapis.com/google.protobuf.UInt64Value',
    'value': '123456789123456'
}

一般來說, @type鍵應該被認為是保留的,並且不用於傳入的映射。

由於沒有為簡單類型指定類型,因此某些值在透過線路傳遞後會變更類型。傳入的float變成doubleshort變成int ,等等。在 Android 中,列表值支援ListJSONArray 。在這些情況下,傳入 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"
        }
    }
}