https.onCall 的通訊協定規格

Cloud Functions 的 https.onCall 觸發條件是 HTTPS 觸發條件, 要求和回應的特定格式。本節將介紹 用戶端 SDK 使用的 HTTPS 要求和回應格式規格 實作 API若您的要求,這些資訊可能對您有所幫助 就無法使用 Android、Apple 平台或網頁 SDK。

要求格式:標頭

對可呼叫觸發條件端點的 HTTP 要求,必須是POST 下列標題:

  • 必填:Content-Type: application/json
    • 但允許使用選用的 ; charset=utf-8
  • 可選:Authorization: Bearer <token>
    • 提出要求的登入使用者專屬的 Firebase 驗證使用者 ID 權杖。後端會自動「驗證」這個權杖,並在處理常式的 context 中提供該權杖。如果權杖無效,要求就會遭到拒絕。
  • 可選:Firebase-Instance-ID-Token: <iid>
    • Firebase 用戶端 SDK 的 FCM 註冊權杖。必須為字串。可在處理常式的 context 中找到。用於指定推播通知。
  • 可選:X-Firebase-AppCheck: <token>
    • 用戶端應用程式提供的 Firebase App Check 權杖, 請求。後端會自動驗證這個權杖並加以解碼 在處理常式的 context 中插入 appId。如果無法建立權杖 就表示要求遭到拒絕(適用於 SDK 3.14.0 以上版本)。

如果包含任何其他標頭,要求會遭到拒絕,詳情請參閱下方回應說明文件。

注意:在 JavaScript 用戶端中,這些要求會觸發 CORS OPTIONS 預檢,原因如下:

  • 不允許使用 application/json。必須為 text/plainapplication/x-www-form-urlencoded
  • Authorization 標頭不是 CORS-safelisted request-header
  • 不得使用其他標頭。

可呼叫觸發條件會自動處理這些 OPTIONS 要求。

要求主體

HTTP 要求的主體應為具有下列任一欄位的 JSON 物件:

  • 必要:data - 傳遞至函式的引數。可以是任何有效的 JSON 值。系統會根據下方所述的序列化格式,自動將這個事件解碼為原生 JavaScript 類型。

如果要求中存在任何其他欄位,後端會將要求格式錯誤,並拒絕要求。

回應格式:狀態碼

在某些情況下,可能造成不同的 HTTP 狀態碼和 errors 的字串狀態碼 回應。

  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

回應主體

用戶端端點的回應一律為 JSON 物件。最低 包含 resulterror,以及任何選填欄位。如果 回應不是 JSON 物件,或不含 dataerror, 用戶端 SDK 應將請求視為失敗 以及 Google 錯誤代碼 INTERNAL (13)

  • error:如果有這個欄位,不論 HTTP 狀態碼或 data 是否存在,要求都會視為失敗。這個欄位的值應為錯誤時採用標準 Google Cloud HTTP Mapping 格式的 JSON 物件,並提供 statusmessage 與 (選擇性) details 欄位。不得加入「code」欄位。如果 status 欄位未設定或為無效值,用戶端應根據 code.proto 將狀態視為 INTERNAL。如果有 details,則包含在用戶端 SDK 錯誤附加的使用者資訊中 (如果有的話)。
    注意:這裡的 details 欄位是使用者提供的值。它不一定是採用 proto 類型特徵的值清單,就像 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
  • boolean:truefalse
  • string - 例如"hello world"
  • map<string, any="">例如{"x": 3}</string,>
  • list - 例如[1, 2, 3]
  • 長 (有符號或未簽署,最多 64 位元) - [詳見下方說明]

floatdouble 不支援 NaNInfinity 值。

請注意,long 是 JSON 中通常不允許的特殊類型,但已包含在 proto3 規格中。舉例來說,這些會編碼為:

long

{
    '@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"
        }
    }
}