מפרט הפרוטוקול עבור https.onCall

טריגר https.onCall ב-Cloud Functions הוא טריגר HTTPS עם פורמט ספציפי לבקשה ולתגובה. בקטע הזה אנחנו מפרט לפורמטים של בקשות ותגובה ב-HTTPS שבהן משתמשים ערכות ה-SDK של הלקוח כדי להטמיע את ה-API. המידע הזה יכול להיות שימושי אם אי אפשר לעמוד בדרישות שלכם באמצעות פלטפורמות Android או Apple או ערכות SDK לאינטרנט.

פורמט הבקשה: כותרות

בקשת ה-HTTP לנקודת קצה (endpoint) של טריגר שניתן לקריאה צריכה להיות POST עם הפרמטר הכותרות הבאות:

  • חובה: Content-Type: application/json
    • אפשר להוסיף את הערך ; charset=utf-8.
  • Authorization: Bearer <token> (אופציונלי)
    • אסימון מזהה המשתמש ב-Firebase Authentication של המשתמש המחובר ששלח את הבקשה. הקצה העורפי מאמת באופן אוטומטי את האסימון הזה והופך אותו לזמין ב-context של ה-handler. אם האסימון לא תקף, הבקשה תידחה.
  • Firebase-Instance-ID-Token: <iid> (אופציונלי)
    • אסימון הרישום של FCM מ-SDK של הלקוח ב-Firebase. הערך הזה חייב להיות מחרוזת. הוא זמין ב-context של הטיפול. היא משמשת לטירגוט התראות.
  • אופציונלי: X-Firebase-AppCheck: <token>
    • האסימון של Firebase App Check שסופק על ידי אפליקציית הלקוח ששולחת את הבקשה. הקצה העורפי מאמת את האסימון הזה באופן אוטומטי ומפענח אותו, ומחדיר את appId ל-context של הטיפול. אם לא ניתן לאמת את האסימון, הבקשה נדחית. (זמין ל-SDK בגרסה 3.14.0 ואילך)

אם תכללו כותרות אחרות, הבקשה תידחה, כפי שמתואר במסמכי התיעוד של התגובות שבהמשך.

הערה: בלקוחות JavaScript, הבקשות האלה גורמות לקדם-הפעלה של OPTIONS של CORS, מהסיבות הבאות:

  • לא ניתן להפר את המדיניות: application/json הערך חייב להיות text/plain או application/x-www-form-urlencoded.
  • הכותרת Authorization היא לא כותרת בקשה ברשימת ההיתרים של CORS.
  • אסור להשתמש בכותרות אחרות באופן דומה.

הטריגר שניתן לקריאה מטפל באופן אוטומטי בבקשות OPTIONS האלה.

גוף הבקשה

גוף הבקשה של ה-HTTP צריך להיות אובייקט JSON עם אחד מהשדות הבאים:

  • חובה: data – הארגומנט המועבר לפונקציה. זה יכול להיות כל ערך JSON חוקי. הנתונים מקודדים באופן אוטומטי לסוגי JavaScript מקומיים בהתאם לפורמט הסריאליזציה שמתואר בהמשך.

אם יש שדות אחרים בבקשה, הקצה העורפי מתייחס לבקשה כאל בקשה עם פורמט שגוי והיא נדחית.

פורמט תגובה: קודי סטטוס

יש כמה מקרים שיכולים לגרום לקודי סטטוס HTTP שונים ולקודי סטטוס מחרוזת שונים של שגיאות בתגובה.

  1. במקרה של שגיאת HTTP לפני ההפעלה של הטריגר client, התגובה לא מטופלת כפונקציית לקוח. לדוגמה, אם לקוח מנסה להפעיל פונקציה שלא קיימת, הוא יקבל את תגובת 404 Not Found.

  2. אם הטריגר של הלקוח הופעל אבל הבקשה בפורמט שגוי, למשל היא לא בפורמט JSON, יש בה שדות לא חוקיים או שהשדה data חסר, הבקשה תידחה עם 400 Bad Request וקוד השגיאה INVALID_ARGUMENT.

  3. אם אסימון האימות שסופק בבקשה לא תקף, הבקשה תידחה עם 401 Unauthorized וקוד השגיאה UNAUTHENTICATED.

  4. אם אסימון הרישום של FCM שסופק בבקשה אינו חוקי, ההתנהגות לא מוגדרת. האסימון לא נבדק בכל בקשה, אלא רק כשמשתמשים בו כדי לשלוח התראה ב-push באמצעות 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. לכל הפחות מכיל result או error, יחד עם כל שדה אופציונלי. אם התגובה היא לא אובייקט JSON או שהיא לא מכילה את הערכים data או error, ה-SDK של הלקוח צריך להתייחס לבקשה ככישלון עם קוד השגיאה של Google‏ INTERNAL (13).

  • error – אם השדה הזה מופיע, הבקשה נחשבת כנכשלה, בלי קשר לקוד הסטטוס של ה-HTTP או אם קיים גם data. הערך בשדה הזה צריך להיות אובייקט JSON בפורמט הסטנדרטי Google Cloud HTTP Mapping לשגיאות, עם שדות עבור status, message ו-details (אופציונלי). השדה code לא ייכלל. אם השדה status לא מוגדר, או שהוא ערך לא חוקי, הלקוח צריך להתייחס לסטטוס בתור INTERNAL, בהתאם ל-code.proto. אם details קיים, הוא ייכלל בכל פרטי המשתמש שמקושרים לשגיאה ב-SDK של הלקוח, אם רלוונטי.
    הערה: השדה details כאן הוא ערך שסופק על ידי המשתמש. זו לא בהכרח רשימה של ערכים המקודמים לפי סוג אב-טיפוס כמו בפורמט Status של Google.
  • result – הערך שהפונקציה מחזירה. הוא יכול להיות כל ערך JSON חוקי. ה-SDK של firebase-functions מקודד באופן אוטומטי את הערך שהמשתמש מחזיר לפורמט JSON הזה. ערכות ה-SDK של הלקוח מפענחות באופן אוטומטי את הפרמטרים האלה לסוגי נתונים מקומיים בהתאם לפורמט הסריאליזציה שמתואר בהמשך.

אם יש שדות אחרים, המערכת תתעלם מהם.

סריאליזציה

פורמט הסדרת הנתונים במטענים ייעודיים (payloads) שרירותיים זהה גם לבקשה וגם לתשובה.

כדי לשמור על עקביות בפלטפורמה, המפתחות האלה מקודדים ב-JSON כאילו הם הערך של שדה Any במאגר נתונים זמני של פרוטוקול proto3, באמצעות מיפוי JSON סטנדרטי. ערכים של סוגים פשוטים כמו null,‏ int,‏ double או string מקודדים ישירות ולא כוללים את הסוג המפורש שלהם. לכן, float ו-double מקודדים באותו אופן, ויכול להיות שלא תדעו איזה מהם התקבל בצד השני של השיחה. לסוגי נתונים שלא אופייניים ל-JSON, נעשה שימוש בקידוד proto3 עם טיפוס עבור הערך. למידע נוסף, עיינו במסמכי התיעוד של כל קידוד JSON.

מותר להשתמש בסוגים הבאים:

  • null – null
  • int (חתום או לא חתום, עד 32 ביט) - למשל 3 או -30.
  • float – לדוגמה, 3.14
  • כפול – למשל 3.14
  • boolean – true או false
  • מחרוזת – למשל "hello world"
  • map<string, any=""> – לדוגמה, {"x": 3}</string,>
  • רשימה - למשל [1, 2, 3]
  • long (signed או unsigned, עד 64 ביט) – [פרטים נוספים מופיעים בהמשך]

הערכים NaN ו-Infinity של float ו-double לא נתמכים.

הערה: long הוא סוג מיוחד שאסור בדרך כלל ב-JSON, אבל הוא מכוסה במפרט של proto3. לדוגמה, הם מקודדים כך:

long

{
    '@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 לא ידוע עוברת deserialize, היא נשארת כמפה. כך מפתחים יכולים להוסיף שדות עם סוגים חדשים לערכי ההחזרה שלהם בלי לפגוע בלקוחות ישנים יותר.

דוגמאות קוד

הדוגמאות בקטע הזה ממחישות איך לקודד את הנתונים הבאים:

  • דוגמה ל-callable.call ב-Swift
  • תגובה על הצלחה של הקריאה
  • תגובה שנכשלה לשיחה

דוגמה ל-Callable.call ב-Swift לקידוד

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"
        }
    }
}