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 des formats de requête et de réponse HTTPS utilisés par les SDK clients pour mettre en œuvre l'API. Ces informations peuvent vous être utiles si vos exigences ne peuvent pas être satisfaites à l'aide des plates-formes Android, Apple ou des SDK Web.

Format de requête: en-têtes

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

  • Obligatoire : Content-Type: application/json
    • Un ; charset=utf-8 facultatif est autorisé.
  • Facultatif : Authorization: Bearer <token>
    • Jeton d'ID utilisateur Firebase Authentication de l'utilisateur connecté qui effectue la requête. Le backend vérifie automatiquement ce jeton et le rend disponible dans le context du gestionnaire. Si le jeton n'est pas valide, la requête est rejetée.
  • Facultatif : Firebase-Instance-ID-Token: <iid>
    • Jeton d'enregistrement FCM du SDK client Firebase. Il doit s'agir d'une chaîne. Cette information est disponible dans le fichier 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 requête. Le backend valide et décode automatiquement ce jeton, en injectant le appId dans le context du gestionnaire. Si le jeton ne peut pas être validé, la requête est rejetée. (Disponible pour le SDK 3.14.0 et versions ultérieures)

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

Remarque : Dans les clients JavaScript, ces requêtes déclenchent une vérification préliminaire CORS OPTIONS, car :

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 :

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

Si d'autres champs sont présents dans la requête, le backend considère que la requête est incorrecte et elle est refusée.

Format de réponse : codes d'état

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

  1. En cas d'erreur HTTP avant l'appel du déclencheur client, la réponse n'est pas gérée en tant que fonction cliente. Par exemple, si un client tente d'appeler une fonction qui n'existe pas, il reçoit une réponse 404 Not Found.

  2. Si le déclencheur client est appelé, mais que la requête n'est pas au bon format (par exemple, qu'elle n'est pas au format JSON, qu'elle comporte des champs non valides ou qu'il manque le champ data), la requête est rejetée avec 400 Bad Request, avec un code d'erreur INVALID_ARGUMENT.

  3. Si le jeton d'autorisation 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 requête 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 ayant échoué, la requête est rejetée avec 500 Internal Server Error, avec un code d'erreur INTERNAL. Cela évite que les erreurs de codage ne soient 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 requête échoue. Le code d'état HTTP renvoyé est basé sur la mise en correspondance officielle de l'état d'erreur avec l'état HTTP, comme 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 détaillé ci-dessous. Cela signifie que si la fonction renvoie une erreur explicite avec l'état OK, la réponse a l'état 200 OK, mais que le champ error est défini dans la réponse.

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

Format de réponse: en-têtes

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

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

Corps de la réponse

La réponse d'un point de terminaison client est toujours un objet JSON. Il contient au moins result ou error, ainsi que des champs facultatifs. Si la réponse n'est pas un objet JSON ou ne contient pas data ou error, le SDK client doit considérer la requête comme ayant échoué avec le code d'erreur Google INTERNAL (13).

  • error : si ce champ est présent, la requête est considérée comme ayant échoué, quel que soit le code d'état HTTP ou si data est également présent. La valeur de ce champ doit être un objet JSON au format standard de mappage HTTP Google Cloud 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 contient une valeur non valide, le client doit traiter l'état comme INTERNAL, conformément à code.proto. Si details est présent, il est inclus dans les informations utilisateur associées à 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 triées par type de proto, comme dans le format Status de Google.
  • result : 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 clients 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 des charges utiles de données arbitraires est le même pour la requête et la réponse.

Pour assurer la cohérence de la plate-forme, ils sont encodés en JSON comme s'il s'agissait de la valeur d'un champ Any dans un tampon de protocole proto3, à l'aide du 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. Par conséquent, un float et un double sont encodés de la même manière, et vous ne pouvez pas savoir lequel est reçu à l'autre bout de l'appel. Pour les types qui ne sont pas natifs en JSON, l'encodage proto3 typé pour la valeur est utilisé. Pour en savoir plus, consultez la documentation sur l'encodage JSON.

Les types suivants sont autorisés:

  • null - null
  • int (signé ou non signé, jusqu'à 32 bits) : par exemple, 3 ou -30.
  • float (par exemple, 3.14)
  • double (ex. : 3.14)
  • booléen : true ou false
  • chaîne (par exemple, "hello world")
  • map<chaîne, any=""> (par exemple, {"x": 3}</chaîne,>)
  • list (par exemple, [1, 2, 3])
  • long (signé ou non signé, jusqu'à 64 bits) - [voir ci-dessous pour en savoir plus]

Les valeurs NaN et Infinity pour float et double ne sont pas acceptées.

Notez que long est un type spécial normalement non autorisé en JSON, mais couvert par la spécification proto3. Par exemple, ils sont encodé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 ne pas être utilisée pour les cartes transmises.

Étant donné que le type n'est pas spécifié pour les types simples, certaines valeurs changent de type après avoir été transmises sur le fil. Un float transmis devient un double. short devient int, et ainsi de suite. Sous Android, List et JSONArray sont acceptés pour les valeurs de liste. Dans ce cas, la transmission d'un objet JSONArray génère une erreur List.

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

Exemples de code

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

  • Exemple de callable.call en Swift
  • Une réponse indiquant que l'appel a réussi
  • Réponse d'échec pour l'appel

Exemple d'utilisation de Callable.call en Swift pour l'encodage

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 à l'encodage

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

En-tête de réponse ayant échoué :

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

Corps de la réponse ayant échoué :

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