Spécification du protocole pour https.onCall

Un déclencheur https.onCall pour Cloud Functions est un déclencheur HTTPS avec un format spécifique pour la requête et la réponse. Cette section fournit une spécification pour les formats de demande et de réponse HTTPS utilisés par les SDK clients pour implémenter l'API. Ces informations peuvent vous être utiles si vos besoins ne peuvent pas être satisfaits à l'aide des plates-formes Android, Apple ou des SDK Web.

Format de la requête : en-têtes

La requête HTTP adressée à un point de terminaison de déclencheur appelable doit être un POST avec les en-têtes suivants :

  • Obligatoire : Content-Type: application/json
    • Un ; charset=utf-8 est autorisé.
  • Facultatif : Authorization: Bearer <token>
    • Un jeton d'ID utilisateur Firebase Authentication pour l'utilisateur connecté effectuant la demande. Le backend vérifie automatiquement ce jeton et le rend disponible dans le context du gestionnaire. Si le jeton n'est pas valide, la demande est rejetée.
  • Facultatif : Firebase-Instance-ID-Token: <iid>
    • Le jeton d'enregistrement FCM du SDK client Firebase. Ce doit être une chaîne. Ceci est disponible dans le context du gestionnaire. Il est utilisé pour cibler les notifications push.
  • Facultatif : X-Firebase-AppCheck: <token>
    • Jeton Firebase App Check fourni par l'application cliente à l'origine de la demande. Le backend vérifie automatiquement ce jeton et le décode, en injectant l' appId dans le context du gestionnaire. Si le jeton ne peut pas être vérifié, la demande est rejetée. (Disponible pour SDK >=3.14.0)

Si d'autres en-têtes sont inclus, la demande est rejetée, comme décrit dans la documentation de réponse ci-dessous.

Remarque : dans les clients JavaScript, ces requêtes déclenchent un contrôle en amont CORS OPTIONS , car :

  • application/json n'est pas autorisé. Il doit être text/plain ou application/x-www-form-urlencoded .
  • L'en-tête Authorization n'est pas un en-tête de demande de liste sécurisée CORS .
  • Les autres en-têtes ne sont pas non plus autorisés.

Le déclencheur appelable gère automatiquement ces requêtes OPTIONS .

Corps de la requête

Le corps de la requête HTTP doit être un objet JSON avec l'un des champs suivants :

  • Requis : data - L'argument passé à la fonction. Il peut s'agir de n'importe quelle valeur JSON valide. Ceci est automatiquement décodé en types JavaScript natifs selon le format de sérialisation décrit ci-dessous.

S'il y a d'autres champs présents dans la requête, le backend considère que la requête est mal formée et elle est rejetée.

Format de réponse : codes d'état

Plusieurs cas peuvent entraîner des codes d'état HTTP et des codes d'état de chaîne différents pour les erreurs dans la réponse.

  1. Dans le cas d'une erreur HTTP avant l'appel du déclencheur client , la réponse n'est pas traitée comme une fonction client. Par exemple, si un client essaie d'invoquer une fonction inexistante, il reçoit une réponse 404 Not Found .

  2. Si le déclencheur client est appelé, mais que la demande est au mauvais format, par exemple si elle n'est pas JSON, s'il y a des champs non valides ou s'il manque le champ data , la demande est rejetée avec 400 Bad Request , avec un code d'erreur INVALID_ARGUMENT .

  3. Si le jeton d'authentification fourni dans la requête n'est pas valide, la requête est rejetée avec 401 Unauthorized , avec un code d'erreur UNAUTHENTICATED .

  4. Si le jeton d'enregistrement FCM fourni dans la demande n'est pas valide, le comportement n'est pas défini. Le jeton n'est pas vérifié à chaque requête, sauf lorsqu'il est utilisé pour envoyer une notification push avec FCM.

  5. Si le déclencheur appelable est appelé, mais échoue avec une exception non gérée ou renvoie une promesse échouée, la demande est rejetée avec 500 Internal Server Error , avec un code d'erreur INTERNAL . Cela empêche les erreurs de codage d'être accidentellement exposées aux utilisateurs finaux.

  6. Si l'appelable est appelé et renvoie une condition d'erreur explicite à l'aide de l'API fournie pour les fonctions appelables, la demande échoue. Le code de statut HTTP renvoyé est basé sur le mappage officiel du statut d'erreur au statut HTTP, tel que défini dans code.proto . Le code d'erreur spécifique, le message et les détails renvoyés sont encodés dans le corps de la réponse, comme indiqué ci-dessous. Cela signifie que si la fonction renvoie une erreur explicite avec le statut OK , alors la réponse a le statut 200 OK , mais le champ error est défini dans la réponse.

  7. Si le déclencheur client réussit, l'état de la réponse est 200 OK .

Format de réponse : en-têtes

La réponse comporte les en-têtes suivants :

  • Content-Type: application/json
  • Un ; charset=utf-8 est autorisé.

Corps de la réponse

La réponse d'un point de terminaison client est toujours un objet JSON. Au minimum, il contient soit result soit error , ainsi que tous les champs facultatifs. Si la réponse n'est pas un objet JSON ou ne contient pas data ou error , le SDK client doit traiter la demande comme ayant échoué avec le code d'erreur Google INTERNAL (13) .

  • error - Si ce champ est présent, la demande est considérée comme ayant échoué, quel que soit le code d'état HTTP ou si data sont également présentes. La valeur de ce champ doit être un objet JSON au format standard Google Cloud HTTP Mapping pour les erreurs, avec des champs pour status , message et (éventuellement) details . Le champ code ne doit pas être inclus. Si le champ status n'est pas défini ou s'il s'agit d'une valeur non valide, le client doit traiter l'état comme INTERNAL , conformément à code.proto . Si details sont présents, ils sont inclus dans toutes les informations utilisateur jointes à l'erreur dans le SDK client, le cas échéant.
    Remarque : Le champ details ici est une valeur fournie par l'utilisateur. Il ne s'agit pas nécessairement d'une liste de valeurs saisies par type de prototype comme dans le format Google Status .
  • result - La valeur renvoyée par la fonction. Il peut s'agir de n'importe quelle valeur JSON valide. Le SDK firebase-functions encode automatiquement la valeur renvoyée par l'utilisateur dans ce format JSON. Les SDK client décodent automatiquement ces paramètres en types natifs selon le format de sérialisation décrit ci-dessous.

Si d'autres champs sont présents, ils doivent être ignorés.

Sérialisation

Le format de sérialisation pour les charges utiles de données arbitraires est le même pour la requête et la réponse.

Pour la cohérence de la plate-forme, ceux-ci sont encodés en JSON comme s'il s'agissait de la valeur d'un champ Any dans un tampon de protocole proto3, en utilisant le mappage JSON standard . Les valeurs de types simples tels que null , int , double ou string sont encodées directement et n'incluent pas leur type explicite. Ainsi, un float et double sont encodés de la même manière, et vous ne savez peut-être pas lequel est reçu à l'autre bout de l'appel. Pour les types qui ne sont pas natifs de JSON, l'encodage proto3 typé pour la valeur est utilisé. Pour plus d'informations, consultez la documentation relative à Tout encodage JSON .

Les types suivants sont autorisés :

  • nul - null
  • int (signé ou non signé, jusqu'à 32 bits) - par exemple 3 ou -30 .
  • flotteur - par exemple 3.14
  • double - par exemple 3.14
  • booléen - true ou false
  • chaîne - par exemple "hello world"
  • carte - par exemple {"x": 3}
  • liste - par exemple [1, 2, 3]
  • long (signé ou non signé, jusqu'à 64 bits) - [voir ci-dessous pour plus de détails]

Les valeurs NaN et Infinity pour float et double ne sont pas prises en charge.

Notez que long est un type spécial qui n'est normalement pas autorisé dans JSON, mais qui est couvert par la spécification proto3. Par exemple, ceux-ci sont codés comme suit :

long

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

long non signé

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

En général, la clé @type doit être considérée comme réservée et non utilisée pour les cartes transmises.

Étant donné que le type n'est pas spécifié pour les types simples, certaines valeurs changeront de type après être passées sur le fil. Un float passé devient un double . Un short devient un int , et ainsi de suite. Dans Android, List et JSONArray sont pris en charge pour les valeurs de liste. Dans ces cas, la transmission d'un JSONArray donnera un List .

Si une carte avec un champ @type inconnu est désérialisée, elle est laissée en tant que carte. Cela permet aux développeurs d'ajouter des champs avec de nouveaux types à leurs valeurs de retour sans casser les anciens clients.

Exemples de code

Les exemples de cette section illustrent comment encoder les éléments suivants :

  • Un exemple callable.call dans Swift
  • Une réponse positive à l'appel
  • Une réponse d'échec pour l'appel

Exemple Callable.call dans Swift pour encoder

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

En-tête de requête :

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

Corps de la requête :

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

Réponse à encoder

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

En-tête de réponse réussie :

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

Corps de la réponse réussie :

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

Réponse d'échec à l'encodage

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

Échec de l'en-tête de réponse :

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

Échec du corps de la réponse :

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