Spesifikasi protokol untuk https.onCall

Pemicu https.onCall untuk Cloud Functions adalah pemicu HTTPS dengan format khusus untuk permintaan dan respons. Bagian ini menjelaskan spesifikasi format permintaan dan respons HTTPS yang digunakan oleh SDK klien untuk mengimplementasikan API. Informasi ini mungkin berguna bagi Anda jika kebutuhan Anda tidak dapat dipenuhi menggunakan SDK Android, platform Apple, atau web.

Format permintaan: header

Permintaan HTTP ke sebuah endpoint pemicu callable harus berupa POST dengan header berikut:

  • Wajib: Content-Type: application/json
    • ; charset=utf-8 opsional diizinkan.
  • Opsional: Authorization: Bearer <token>
    • Token ID pengguna Firebase Authentication untuk pengguna yang login dan membuat permintaan. Backend secara otomatis memverifikasi token ini dan menyediakannya pada context pengendali. Jika token tidak valid, permintaan akan ditolak.
  • Opsional: Firebase-Instance-ID-Token: <iid>
    • Token pendaftaran FCM dari SDK klien Firebase. Token ini harus berupa string. Dan tersedia dalam context pengendali. Digunakan untuk menargetkan notifikasi push.
  • Opsional: X-Firebase-AppCheck: <token>
    • Token Firebase App Check yang disediakan oleh aplikasi klien yang membuat permintaan. Backend secara otomatis memverifikasi token ini dan mendekodenya, memasukkan appId dalam context pengendali. Jika token tidak dapat diverifikasi, permintaan akan ditolak. (Tersedia untuk SDK >= 3.14.0)

Jika ada header lain yang disertakan, permintaan akan ditolak, seperti yang dijelaskan dalam dokumentasi respons di bawah.

Catatan: Pada klien JavaScript, permintaan ini memicu preflight OPTIONS CORS, karena:

Pemicu callable menangani permintaan OPTIONS ini secara otomatis.

Isi permintaan

Isi permintaan HTTP harus berupa objek JSON dengan salah satu kolom berikut:

  • Wajib: data - Argumen yang diteruskan ke fungsi. Nilai ini dapat berupa sembarang nilai JSON yang valid. Nilai otomatis didekode ke dalam jenis JavaScript native sesuai dengan format serialisasi yang dijelaskan di bawah.

Jika ada kolom lain dalam permintaan, backend akan menganggap permintaan tersebut salah format, sehingga akan ditolak.

Format respons: kode status

Ada beberapa kasus yang dapat menghasilkan kode status HTTP dan kode status string yang berbeda untuk error dalam respons.

  1. Jika terjadi error HTTP sebelum pemicu client dipanggil, respons tidak ditangani sebagai fungsi klien. Misalnya, jika klien mencoba memanggil fungsi yang tidak ada, respons 404 Not Found akan diterima.

  2. Jika pemicu klien dipanggil, tetapi format permintaannya salah, misalnya tidak menggunakan format JSON, memuat kolom yang tidak valid, atau kolom data tidak ada, permintaan akan ditolak dengan 400 Bad Request, dengan kode error INVALID_ARGUMENT.

  3. Jika token autentikasi yang dimasukkan ke dalam permintaan tidak valid, permintaan akan ditolak dengan 401 Unauthorized, dengan kode error UNAUTHENTICATED.

  4. Jika token pendaftaran FCM yang dimasukkan ke dalam permintaan tidak valid, perilaku tidak dapat ditentukan. Token tidak diperiksa pada setiap permintaan, kecuali saat digunakan untuk mengirim notifikasi push dengan FCM.

  5. Jika pemicu callable dipanggil, tetapi gagal dengan pengecualian yang tidak tertangani atau menampilkan promise yang gagal, permintaan akan ditolak dengan 500 Internal Server Error, dengan kode error INTERNAL. Hal ini mencegah pemunculan error coding ke pengguna akhir secara tidak sengaja.

  6. Jika callable dipanggil dan menampilkan kondisi error eksplisit menggunakan API yang disediakan untuk fungsi callable, permintaan akan gagal. Kode status HTTP yang ditampilkan didasarkan pada pemetaan resmi status error ke status HTTP, seperti yang ditentukan dalam code.proto. Kode error, pesan, dan detail spesifik yang ditampilkan akan dienkode dalam isi respons seperti dijelaskan di bawah. Artinya, jika fungsi ini menampilkan error eksplisit dengan status OK, respons akan memiliki status 200 OK, tetapi kolom error akan ditetapkan dalam respons.

  7. Jika pemicu klien berhasil, status responsnya adalah 200 OK.

Format respons: header

Respons memiliki header berikut:

  • Content-Type: application/json
  • ; charset=utf-8 opsional diizinkan.

Isi respons

Respons dari endpoint klien selalu berupa objek JSON. Respons ini harus memuat kolom result atau error, beserta kolom opsional. Jika respons tidak berupa objek JSON, atau tidak memuat kolom data atau error, SDK klien harus menganggap permintaan tersebut gagal dengan kode error Google INTERNAL (13).

  • error - Jika kolom ini ada, permintaan dianggap gagal, terlepas dari kode status HTTP atau apakah kolom data ada atau tidak. Nilai kolom ini harus berupa objek JSON dalam format Pemetaan HTTP Google Cloud standar untuk error, dengan kolom untuk status, message, dan details (opsional). Kolom code tidak boleh disertakan. Jika kolom status tidak ditetapkan, atau merupakan nilai yang tidak valid, klien harus menganggap statusnya sebagai INTERNAL, sesuai dengan code.proto. Jika details ada, kolom ini akan disertakan dalam info pengguna yang ditambahkan ke error dalam SDK klien, jika sesuai.
    Catatan: Kolom details di sini adalah nilai yang diisi oleh pengguna. Nilai ini tidak harus berupa daftar nilai yang dimasukkan oleh jenis proto seperti dalam format Status Google.
  • result - Nilai yang ditampilkan oleh fungsi. Nilai ini dapat berupa sembarang nilai JSON yang valid. Firebase Functions SDK secara otomatis mengenkode nilai yang ditampilkan oleh pengguna ke dalam format JSON ini. SDK klien mendekode parameter ini ke dalam jenis native secara otomatis, sesuai dengan format serialisasi yang dijelaskan di bawah.

Jika ada kolom lain, abaikan.

Serialisasi

Format serialisasi untuk payload data arbitrer sama antara permintaan dan respons.

Untuk menjaga konsistensi platform, payload dienkode ke dalam JSON seolah-olah merupakan nilai dari kolom Any dalam buffering protokol proto3, menggunakan pemetaan JSON standar. Nilai berjenis sederhana seperti null, int, double, atau string dienkode langsung, dan tidak menyertakan jenis eksplisitnya. Jadi, float dan double dienkode dengan cara yang sama, dan Anda mungkin tidak tahu nilai mana yang diterima oleh tujuan panggilan. Untuk jenis yang bukan native JSON, encoding proto3 yang diketikkan untuk nilai itu akan digunakan. Untuk informasi selengkapnya, lihat dokumentasi untuk encoding JSON mana saja.

Jenis-jenis berikut diizinkan:

  • null - null
  • int (bertanda atau tidak, hingga 32 bit) - misalnya 3 atau -30.
  • float - misalnya 3.14
  • double - misalnya 3.14
  • boolean - true atau false
  • string - misalnya "hello world"
  • map<string, any=""> - misalnya {"x": 3}</string,>
  • list - misalnya [1, 2, 3]
  • long (bertanda atau tidak, hingga 64 bit) - [lihat detailnya di bawah]

Nilai NaN dan Infinity untuk float dan double tidak didukung.

Harap diperhatikan bahwa long adalah jenis khusus yang biasanya tidak diizinkan di JSON, tetapi dicakup oleh spesifikasi proto3. Misalnya, long berikut ini dienkode sebagai:

long

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

long tidak bertanda

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

Secara umum, kunci @type harus dianggap dicadangkan, dan tidak digunakan untuk map yang diterima.

Karena jenis ini tidak ditentukan untuk nilai berjenis sederhana, beberapa nilai akan berubah jenis setelah diteruskan. float yang diterima akan menjadi double. short akan menjadi int, dan seterusnya. Pada Android, List dan JSONArray didukung untuk nilai daftar. Dalam hal ini, meneruskan JSONArray akan menghasilkan List.

Jika deserialisasi dilakukan pada map dengan kolom @type yang tidak dikenal, map akan dibiarkan apa adanya. Dengan begitu developer dapat menambahkan kolom berjenis baru ke nilai yang ditampilkan tanpa membobol klien yang lebih lama.

Contoh kode

Contoh dalam bagian ini menggambarkan cara mengenkode berikut ini:

  • Contoh callable.call di Swift
  • Respons keberhasilan untuk panggilan
  • Respons kegagalan untuk panggilan

Contoh callable.call di Swift untuk dienkode

callable.call([
    "aString": "some string",
    "anInt": 57,
    "aFloat": 1.23,
    "aLong": -123456789123456 as Int64
])

Header permintaan:

Method: POST
Content-Type: application/json; charset=utf-8
Authorization: Bearer some-auth-token
Firebase-Instance-ID-Token: some-iid-token

Isi permintaan:

{
    "data": {
        "aString": "some string",
        "anInt": 57,
        "aFloat": 1.23,
        "aLong": {
            "@type": "type.googleapis.com/google.protobuf.Int64Value",
            "value": "-123456789123456"
        }
    }
}

Respons untuk dienkode

return {
    "aString": "some string",
    "anInt": 57,
    "aFloat": 1.23
};

Header respons yang berhasil:

200 OK
Content-Type: application/json; charset=utf-8

Isi respons yang berhasil:

{
    "response": {
        "aString": "some string",
        "anInt": 57,
        "aFloat": 1.23
    }
}

Respons kegagalan untuk dienkode

throw new HttpsError("unauthenticated", "Request had invalid credentials.", {
  "some-key": "some-value"
});

Header respons yang gagal:

401 UNAUTHENTICATED
Content-Type: application/json; charset=utf-8

Isi respons yang gagal:

{
    "error": {
        "message": "Request had invalid credentials.",
        "status": "UNAUTHENTICATED",
        "details": {
            "some-key": "some-value"
        }
    }
}