https.onCall 的通訊協定規格

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

要求格式:標頭

傳送至可呼叫的觸發事件端點的 HTTP 要求必須是 POST,且包含下列標頭:

  • 必要項目:Content-Type: application/json
    • 但允許使用選用的 ; charset=utf-8
  • 可選:Authorization: Bearer <token>
    • 提出要求的登入使用者 Firebase Authentication 使用者 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 安全清單要求標頭
  • 不得使用其他標頭。

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

要求主體

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

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

如果要求中包含任何其他欄位,後端會將要求視為格式錯誤,並予以拒絕。

回應格式:狀態碼

有幾種情況可能會導致回應中出現不同的 HTTP 狀態碼和字串狀態碼,代表錯誤

  1. 如果在叫用 client 觸發事件之前發生 HTTP 錯誤,系統不會將回應視為用戶端函式處理。舉例來說,如果用戶端嘗試叫用不存在的函式,就會收到 404 Not Found 回應。

  2. 如果叫用用戶端觸發條件,但要求的格式錯誤 (例如非 JSON、含有無效欄位或缺少 data 欄位),則要求會以 400 Bad Request 拒絕,並顯示錯誤代碼 INVALID_ARGUMENT

  3. 如果要求中提供的驗證權杖無效,系統會拒絕要求,並傳回 401 UnauthorizedUNAUTHENTICATED 錯誤代碼。

  4. 如果要求中提供的 FCM 註冊權杖無效,系統就不會定義該行為。權杖只會在透過 FCM 傳送推播通知時,才會在每個要求中檢查。

  5. 如果可呼叫的觸發事件遭到叫用,但因未處理的例外狀況而失敗,或傳回失敗的承諾,系統會使用 500 Internal Server Error 拒絕要求,並傳回 INTERNAL 錯誤代碼。這樣可避免程式碼錯誤不慎曝光給使用者。

  6. 如果叫用可呼叫函式,並使用為可呼叫函式提供的 API 傳回明確的錯誤情況,則要求會失敗。系統會根據 code.proto 中定義的錯誤狀態與 HTTP 狀態官方對應,傳回 HTTP 狀態碼。系統會在回應主體中編碼特定錯誤代碼、訊息和詳細資料,詳情請參閱下文。這表示如果函式傳回狀態為 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。這個欄位的值應為 JSON 物件,採用標準 Google Cloud HTTP 對應格式,其中包含 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,>
  • 清單 - 例如 [1, 2, 3]
  • 長 (有符號或未簽署,最多 64 位元) - [詳見下方說明]

系統不支援 floatdoubleNaNInfinity 值。

請注意,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"
        }
    }
}