مشخصات پروتکل برای https.onCall

یک تریگر https.onCall برای توابع ابری، یک تریگر HTTPS با فرمت خاصی برای درخواست و پاسخ است. این بخش مشخصاتی را برای فرمت‌های درخواست و پاسخ HTTPS که توسط SDK های کلاینت برای پیاده‌سازی API استفاده می‌شوند، ارائه می‌دهد. اگر نیازهای شما با استفاده از SDK های اندروید، اپل یا وب برآورده نشود، این اطلاعات ممکن است برای شما مفید باشد.

قالب درخواست: سربرگ‌ها

درخواست HTTP به یک نقطه پایانی تریگر قابل فراخوانی باید از نوع POST و با هدرهای زیر باشد:

  • مورد نیاز: Content-Type: application/json
    • یک ; charset=utf-8 اختیاری مجاز است.
  • اختیاری: Authorization: Bearer <token>
    • یک توکن شناسه کاربری Firebase Authentication برای کاربر وارد شده که درخواست را ارسال می‌کند. بک‌اند به طور خودکار این توکن را تأیید می‌کند و آن را در context کنترل‌کننده در دسترس قرار می‌دهد. اگر توکن معتبر نباشد، درخواست رد می‌شود.
  • اختیاری: Firebase-Instance-ID-Token: <iid>
    • توکن ثبت FCM از SDK کلاینت Firebase. این باید یک رشته باشد. این در context هندلر موجود است. برای هدف‌گیری اعلان‌های فشاری استفاده می‌شود.
  • اختیاری: X-Firebase-AppCheck: <token>
    • توکن Firebase App Check که توسط برنامه کلاینتِ درخواست‌دهنده ارائه می‌شود. بک‌اند به‌طور خودکار این توکن را تأیید و رمزگشایی می‌کند و appId در context هندلر تزریق می‌کند. اگر توکن قابل تأیید نباشد، درخواست رد می‌شود. (برای SDK >=3.14.0 موجود است)

اگر هر هدر دیگری اضافه شده باشد، درخواست رد می‌شود، همانطور که در مستندات پاسخ زیر توضیح داده شده است.

توجه: در کلاینت‌های جاوا اسکریپت، این درخواست‌ها پیش‌اجرای CORS OPTIONS را آغاز می‌کنند، زیرا:

تریگر قابل فراخوانی به طور خودکار این درخواست‌های OPTIONS را مدیریت می‌کند.

درخواست بدنه

بدنه درخواست HTTP باید یک شیء JSON با هر یک از فیلدهای زیر باشد:

  • الزامی: data - آرگومان ارسالی به تابع. این می‌تواند هر مقدار JSON معتبری باشد. این مقدار به طور خودکار طبق فرمت سریال‌سازی که در زیر توضیح داده شده است، به انواع بومی جاوا اسکریپت رمزگشایی می‌شود.

اگر فیلدهای دیگری در درخواست وجود داشته باشد، backend درخواست را ناقص در نظر می‌گیرد و آن را رد می‌کند.

قالب پاسخ: کدهای وضعیت

موارد مختلفی وجود دارد که می‌تواند منجر به کدهای وضعیت HTTP و کدهای وضعیت رشته‌ای مختلف برای خطاهای موجود در پاسخ شود.

  1. در صورت بروز خطای HTTP قبل از فراخوانی تریگر client ، پاسخ به عنوان یک تابع کلاینت مدیریت نمی‌شود. برای مثال، اگر کلاینتی سعی کند تابعی را که وجود ندارد فراخوانی کند، پاسخ 404 Not Found دریافت می‌کند.

  2. اگر تریگر کلاینت فراخوانی شود، اما درخواست در قالب نادرستی باشد، مثلاً JSON نباشد، فیلدهای نامعتبر داشته باشد یا فیلد data از دست داده باشد، درخواست با خطای 400 Bad Request و کد خطای INVALID_ARGUMENT رد می‌شود.

  3. اگر توکن احراز هویت ارائه شده در درخواست نامعتبر باشد، درخواست با 401 Unauthorized و کد خطای UNAUTHENTICATED رد می‌شود.

  4. اگر توکن ثبت FCM ارائه شده در درخواست نامعتبر باشد، رفتار نامشخص خواهد بود. این توکن در هر درخواست بررسی نمی‌شود، مگر زمانی که برای ارسال اعلان فشار با FCM استفاده شود.

  5. اگر تریگر قابل فراخوانی فراخوانی شود، اما با یک استثنای مدیریت نشده شکست بخورد یا یک promise ناموفق را برگرداند، درخواست با 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 در قالب استاندارد نگاشت HTTP گوگل کلود برای خطاها باشد، که شامل فیلدهایی برای status ، message و (اختیاری) details باشد. فیلد code نباید گنجانده شود. اگر فیلد status تنظیم نشده باشد یا مقدار نامعتبری داشته باشد، کلاینت باید وضعیت را مطابق با code.proto به عنوان INTERNAL در نظر بگیرد. اگر details وجود داشته باشد، در صورت لزوم در هر اطلاعات کاربری پیوست شده به خطا در SDK کلاینت گنجانده می‌شود.
    نکته: فیلد details در اینجا یک مقدار ارائه شده توسط کاربر است. لزوماً لیستی از مقادیر نیست که بر اساس نوع اولیه مانند فرمت Status گوگل، کلیدگذاری شده باشند.
  • result - مقداری که توسط تابع برگردانده می‌شود. این می‌تواند هر مقدار JSON معتبری باشد. کیت توسعه نرم‌افزار firebase-functions به طور خودکار مقدار برگردانده شده توسط کاربر را در این قالب JSON کدگذاری می‌کند. کیت توسعه نرم‌افزار کلاینت به طور خودکار این پارامترها را طبق قالب سریال‌سازی که در زیر توضیح داده شده است، به انواع بومی رمزگشایی می‌کند.

اگر فیلدهای دیگری وجود داشته باشند، باید نادیده گرفته شوند.

سریال‌سازی

قالب سریال‌سازی برای بارهای داده دلخواه، هم برای درخواست و هم برای پاسخ یکسان است.

برای سازگاری پلتفرم، این‌ها با استفاده از نگاشت استاندارد JSON، طوری در JSON کدگذاری می‌شوند که انگار مقدار یک فیلد Any در بافر پروتکل proto3 هستند. مقادیر انواع ساده مانند null ، int ، double یا string مستقیماً کدگذاری می‌شوند و نوع صریح خود را شامل نمی‌شوند. بنابراین، float و double به یک شکل کدگذاری می‌شوند و ممکن است ندانید کدام یک در طرف دیگر فراخوانی دریافت می‌شود. برای انواعی که بومی JSON نیستند، از کدگذاری typed proto3 برای مقدار استفاده می‌شود. برای اطلاعات بیشتر، به مستندات مربوط به کدگذاری Any JSON مراجعه کنید.

انواع زیر مجاز است:

  • تهی - null
  • int (علامت‌دار یا بدون علامت، تا ۳۲ بیت) - مثلاً 3 یا -30 .
  • عدد اعشاری - مثلاً 3.14
  • دو برابر - مثلاً 3.14
  • بولی - true یا false
  • رشته - مثلاً "hello world"
  • نقشه - مثال {"x": 3}
  • فهرست - مثال [1, 2, 3]
  • طولانی (امضادار یا بدون امضا، تا ۶۴ بیت) - [برای جزئیات بیشتر به زیر مراجعه کنید]

مقادیر NaN و Infinity برای نوع float و double پشتیبانی نمی‌شوند.

توجه داشته باشید که long یک نوع خاص است که معمولاً در JSON مجاز نیست، اما توسط مشخصات proto3 پوشش داده می‌شود. برای مثال، این موارد به صورت زیر کدگذاری می‌شوند:

طولانی

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

طولانی بدون امضا

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

به طور کلی، کلید @type باید رزرو شده در نظر گرفته شود و برای نقشه‌های ارسالی استفاده نشود.

از آنجا که نوع برای انواع ساده مشخص نشده است، برخی از مقادیر پس از عبور از سیم، نوعشان تغییر می‌کند. یک float که ارسال می‌شود به double تبدیل می‌شود. یک short به int تبدیل می‌شود و به همین ترتیب. در اندروید، هم List و هم JSONArray برای مقادیر لیست پشتیبانی می‌شوند. در این موارد، ارسال JSONArray منجر به تولید یک List می‌شود.

اگر یک map با فیلد @type ناشناخته deserialize شود، به عنوان یک map باقی می‌ماند. این به توسعه‌دهندگان اجازه می‌دهد تا فیلدهایی با انواع جدید را به مقادیر بازگشتی خود اضافه کنند، بدون اینکه کلاینت‌های قدیمی‌تر را از کار بیندازند.

نمونه‌های کد

نمونه‌های این بخش نحوه کدگذاری موارد زیر را نشان می‌دهند:

  • مثالی از callable.call در سوئیفت
  • پاسخ موفقیت‌آمیز برای تماس
  • پاسخ ناموفق برای تماس

مثال 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"
        }
    }
}