Especificación de protocolo para https.onCall

Un desencadenador https.onCall para Cloud Functions es un desencadenador HTTPS con un formato específico para la solicitud y la respuesta. Esta sección proporciona una especificación para los formatos de solicitud y respuesta HTTPS utilizados por los SDK del cliente para implementar la API. Esta información puede resultarle útil si sus requisitos no se pueden cumplir mediante las plataformas Android, Apple o los SDK web.

Formato de solicitud: encabezados

La solicitud HTTP a un punto final desencadenante invocable debe ser una POST con los siguientes encabezados:

  • Requerido: Content-Type: application/json
    • Un opcional ; charset=utf-8 está permitido.
  • Opcional: Authorization: Bearer <token>
    • Un token de ID de usuario de Firebase Authentication para el usuario que inició sesión y que realiza la solicitud. El backend verifica automáticamente este token y lo pone a disposición en el context del controlador. Si el token no es válido, la solicitud se rechaza.
  • Opcional: Firebase-Instance-ID-Token: <iid>
    • El token de registro de FCM del SDK del cliente de Firebase. Esto debe ser una cuerda. Esto está disponible en el context del controlador. Se utiliza para orientar notificaciones push.
  • Opcional: X-Firebase-AppCheck: <token>
    • El token de Firebase App Check proporcionado por la aplicación cliente que realiza la solicitud. El backend verifica automáticamente este token y lo decodifica, inyectando el appId en el context del controlador. Si el token no se puede verificar, la solicitud se rechaza. (Disponible para SDK >=3.14.0)

Si se incluyen otros encabezados, la solicitud se rechaza, como se describe en la documentación de respuesta a continuación.

Nota: En clientes JavaScript, estas solicitudes activan una verificación previa de CORS OPTIONS porque:

El disparador invocable maneja automáticamente estas solicitudes OPTIONS .

Cuerpo de la solicitud

El cuerpo de la solicitud HTTP debe ser un objeto JSON con cualquiera de los siguientes campos:

  • Requerido: data : el argumento pasado a la función. Puede ser cualquier valor JSON válido. Esto se decodifica automáticamente en tipos de JavaScript nativos de acuerdo con el formato de serialización que se describe a continuación.

Si hay otros campos presentes en la solicitud, el backend considera que la solicitud tiene un formato incorrecto y la rechaza.

Formato de respuesta: códigos de estado

Hay varios casos que podrían dar lugar a diferentes códigos de estado HTTP y códigos de estado de cadena para errores en la respuesta.

  1. En el caso de un error HTTP antes de que se invoque el activador client , la respuesta no se maneja como una función del cliente. Por ejemplo, si un cliente intenta invocar una función inexistente, recibe una respuesta 404 Not Found .

  2. Si se invoca el activador del cliente, pero la solicitud tiene el formato incorrecto, como no ser JSON, tener campos no válidos o faltar el campo de data , la solicitud se rechaza con 400 Bad Request , con un código de error INVALID_ARGUMENT .

  3. Si el token de autenticación proporcionado en la solicitud no es válido, la solicitud se rechaza con 401 Unauthorized , con un código de error UNAUTHENTICATED .

  4. Si el token de registro de FCM proporcionado en la solicitud no es válido, el comportamiento no está definido. El token no se verifica en cada solicitud, excepto cuando se usa para enviar una notificación push con FCM.

  5. Si se invoca el desencadenador invocable, pero falla con una excepción no controlada o devuelve una promesa fallida, la solicitud se rechaza con 500 Internal Server Error , con un código de error INTERNAL . Esto evita que los errores de codificación queden expuestos accidentalmente a los usuarios finales.

  6. Si se invoca el invocable y devuelve una condición de error explícita utilizando la API proporcionada para las funciones invocables, entonces la solicitud falla. El código de estado HTTP devuelto se basa en la asignación oficial del estado de error al estado HTTP, como se define en code.proto . El código de error específico, el mensaje y los detalles devueltos están codificados en el cuerpo de la respuesta como se detalla a continuación. Esto significa que si la función devuelve un error explícito con estado OK , entonces la respuesta tiene el estado 200 OK , pero el campo error está configurado en la respuesta.

  7. Si el activador del cliente tiene éxito, el estado de respuesta es 200 OK .

Formato de respuesta: encabezados

La respuesta tiene los siguientes encabezados:

  • Content-Type: application/json
  • Un opcional ; charset=utf-8 está permitido.

Cuerpo de respuesta

La respuesta de un punto final del cliente es siempre un objeto JSON. Como mínimo contiene result o error , junto con cualquier campo opcional. Si la respuesta no es un objeto JSON o no contiene data ni error , el SDK del cliente debe tratar la solicitud como fallida con el código de error INTERNAL (13) de Google.

  • error : si este campo está presente, la solicitud se considera fallida, independientemente del código de estado HTTP o de si data también están presentes. El valor de este campo debe ser un objeto JSON en el formato estándar de mapeo HTTP de Google Cloud para errores, con campos para status , message y (opcionalmente) details . No se incluirá el campo code . Si el campo status no está configurado o es un valor no válido, el cliente debe tratar el estado como INTERNAL , de acuerdo con code.proto . Si hay details presentes, se incluyen en cualquier información de usuario adjunta al error en el SDK del cliente, si corresponde.
    Nota: El campo details aquí es un valor proporcionado por el usuario. No es necesariamente una lista de valores codificados por tipo de prototipo como en el formato Status de Google.
  • result : el valor devuelto por la función. Puede ser cualquier valor JSON válido. El SDK de firebase-functions codifica automáticamente el valor devuelto por el usuario en este formato JSON. Los SDK del cliente decodifican automáticamente estos parámetros en tipos nativos según el formato de serialización que se describe a continuación.

Si hay otros campos presentes, deben ignorarse.

Publicación por entregas

El formato de serialización para cargas de datos arbitrarios es el mismo tanto para la solicitud como para la respuesta.

Para mantener la coherencia de la plataforma, estos están codificados en JSON como si fueran el valor de un campo Any en un búfer de protocolo proto3, utilizando el mapeo JSON estándar . Los valores de tipos simples como null , int , double o string se codifican directamente y no incluyen su tipo explícito. Por lo tanto, un float y double se codifican de la misma manera y es posible que no sepa cuál se recibe en el otro extremo de la llamada. Para los tipos que no son nativos de JSON, se utiliza la codificación proto3 escrita para el valor. Para obtener más información, consulte la documentación sobre cualquier codificación JSON .

Se permiten los siguientes tipos:

  • nulo - null
  • int (con o sin signo, hasta 32 bits), por ejemplo 3 o -30 .
  • flotador - por ejemplo 3.14
  • doble - por ejemplo 3.14
  • booleano: true o false
  • cadena - por ejemplo "hello world"
  • mapa - por ejemplo {"x": 3}
  • lista - por ejemplo [1, 2, 3]
  • de largo (con o sin signo, hasta 64 bits) - [ver más abajo para más detalles]

No se admiten los valores NaN e Infinity para float y double .

Tenga en cuenta que long es un tipo especial que normalmente no se permite en JSON, pero está cubierto por la especificación proto3. Por ejemplo, estos están codificados como:

largo

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

largo sin firmar

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

En general, la clave @type debe considerarse reservada y no usarse para los mapas pasados.

Debido a que el tipo no se especifica para tipos simples, algunos valores cambiarán de tipo después de pasar por el cable. Un float pasado se convierte en un double . Un short se convierte en un int y así sucesivamente. En Android, tanto List como JSONArray son compatibles con los valores de lista. En esos casos, pasar un JSONArray generará un List .

Si se deserializa un mapa con un campo @type desconocido, se deja como mapa. Esto permite a los desarrolladores agregar campos con nuevos tipos a sus valores de retorno sin interrumpir a los clientes más antiguos.

Ejemplos de código

Los ejemplos de esta sección ilustran cómo codificar lo siguiente:

  • Un ejemplo de callable.call en Swift
  • Una respuesta exitosa a la convocatoria.
  • Una respuesta de error para la llamada.

Ejemplo de Callable.call en Swift para codificar

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

Encabezado de solicitud:

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

Cuerpo de la solicitud:

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

Respuesta a codificar

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

Encabezado de respuesta exitosa:

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

Cuerpo de respuesta exitosa:

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

Respuesta de error para codificar

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

Encabezado de respuesta fallida:

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

Cuerpo de respuesta fallida:

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