Especificación de protocolo de https.onCall

Un activador https.onCall para Cloud Functions es un activador HTTPS con un formato específico para la solicitud y la respuesta. En esta sección, se proporciona una especificación para los formatos de solicitud y respuesta HTTPS que utilizan los SDK cliente a fin de implementar la API. Esta información puede ser útil para los usuarios que no pueden cumplir con los requisitos mediante los SDK de Android, de las plataformas de Apple o de la Web.

Formato de la solicitud: encabezados

La solicitud HTTP a un extremo de activador que admite llamadas debe ser un POST con los siguientes encabezados:

  • Obligatorio: Content-Type: application/json
    • Se permite un ; charset=utf-8 opcional.
  • Opcional: Authorization: Bearer <token>
    • Un token de ID de usuario de Firebase Authentication para el usuario que accedió y realiza la solicitud. El backend verifica automáticamente el token y lo pone a disposición en el context del controlador. Si el token no es válido, se rechaza la solicitud.
  • Opcional: Firebase-Instance-ID-Token: <iid>
    • El token de registro de FCM del SDK cliente de Firebase. Este encabezado debe ser una string. Se encuentra disponible en el context del controlador. Se usa para orientar las notificaciones push.
  • Opcional: X-Firebase-AppCheck: <token>
    • El token de Verificación de aplicaciones de Firebase que proporciona la app cliente que realiza la solicitud. El backend verifica automáticamente este token y lo decodifica para que se inserte el appId en el context del controlador. Si no se puede verificar el token, se rechaza la solicitud (disponible para el SDK 3.14.0 y versiones posteriores).

Si se incluyen otros encabezados, se rechaza la solicitud, tal como se describe en la siguiente documentación sobre respuestas.

Nota: En los clientes JavaScript, estas solicitudes activan una comprobación previa OPTIONS de CORS debido a lo siguiente:

El activador que admite llamadas maneja de forma automática estas solicitudes OPTIONS.

Cuerpo de la solicitud

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

  • Obligatorio: data. El argumento que se pasa a la función. Puede ser cualquier valor JSON válido. Se decodifica automáticamente en tipos nativos de JavaScript según el formato de serialización que se describe a continuación.

Si se definen otros campos en la solicitud, el backend considera incorrecto el formato de la solicitud y la rechaza.

Formato de la respuesta: códigos de estado

Existen diversos casos que pueden producir diferentes códigos de estado de HTTP y códigos de estado de string para los errores de la respuesta.

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

  2. Si se invoca el activador del cliente, pero el formato de la solicitud es incorrecto (por ejemplo, no es JSON, contiene campos no válidos o no contiene el campo data), se rechaza la solicitud con el mensaje 400 Bad Request y se emite el código de error INVALID_ARGUMENT.

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

  4. Si el token de registro de FCM proporcionado en la solicitud no es válido, el comportamiento es indefinido. No se verifica el token en cada solicitud, a menos que se use para enviar notificaciones push con FCM.

  5. Si se invoca el activador que admite llamadas, pero se produce un error con una excepción no controlada o se muestra una promesa con errores, se rechaza la solicitud con el mensaje 500 Internal Server Error y se emite el código de error INTERNAL. Esto evita que se expongan accidentalmente errores de programación a los usuarios finales.

  6. Si se invoca el activador que admite llamadas y se devuelve una condición de error explícita mediante la API provista para las funciones que admiten llamadas, se produce un error en la solicitud. El código de estado HTTP que se muestra se basa en el mapeo oficial de estados de error y estados HTTP, como se define en code.proto. El código de error, el mensaje y los detalles específicos que se muestran se codifican en el cuerpo de la respuesta como se detalla a continuación. Esto significa que, si la función muestra un error explícito con el estado OK, la respuesta tiene el estado 200 OK, pero se establece el campo error en la respuesta.

  7. Si el activador del cliente funciona sin problemas, el estado de la respuesta es 200 OK.

Formato de la respuesta: encabezados

La respuesta tiene los siguientes encabezados:

  • Content-Type: application/json
  • Se permite un ; charset=utf-8 opcional.

Cuerpo de la respuesta

La respuesta de un extremo de cliente siempre es un objeto JSON. Debe contener, como mínimo, result o error, junto con cualquier campo opcional. Si la respuesta no es un objeto JSON o no contiene data ni error, el SDK cliente debe considerar la solicitud como si tuviera errores y emitir el código de error de Google INTERNAL (13).

  • error: si este campo está presente, se considera que la solicitud contiene errores, independientemente del código de estado de HTTP o de la presencia de data. El valor de este campo debe ser un objeto JSON en el formato estándar de Asignación de HTTP de Google Cloud en el caso de errores, con campos para status, message y, de forma opcional, details. No se debe incluir el campo code. Si no se configura el campo status, o su valor no es válido, el cliente debe tratar el estado como INTERNAL, de acuerdo con code.proto. Si se especifica details, se debe incluir en toda información del usuario que se adjunte al error en el SDK de cliente, si corresponde.
    Nota: El campo details de aquí es un valor proporcionado por el usuario. No es necesariamente una lista de valores con clave por tipo de proto como en el formato Status de Google.
  • result: el valor que muestra 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 de cliente decodifican automáticamente estos parámetros en tipos nativos de acuerdo con el formato de serialización que se describe a continuación.

Se debe omitir el resto de los campos presentes.

Serialización

El formato de serialización para cargas útiles de datos arbitrarios es el mismo para la solicitud y la respuesta.

Para mantener la coherencia de la plataforma, estos datos se codifican en JSON como si fueran el valor de un campo Any en un búfer de protocolo proto3 mediante el mapeo estándar de JSON. Los valores de tipos simples, como null, int, double o string, se codifican directamente y no incluyen su tipo explícito. De este modo, float y double se codifican de la misma manera y es posible no detectar cuál se recibe del otro extremo de la llamada. Si los tipos no son nativos para JSON, se utiliza la codificación de tipo proto3 para el valor. Para obtener más información, consulta la documentación de cualquier codificación JSON.

Se permiten los siguientes tipos:

  • null: null
  • int (con o sin firma, hasta 32 bits): p. ej., 3 o -30
  • float: p. ej., 3.14
  • double: p. ej., 3.14
  • boolean: true o false
  • string: p. ej., "hello world"
  • map<string, any="">: p. ej., {"x": 3}</string,>
  • list: p. ej., [1, 2, 3]
  • long (con o sin firma, hasta 64 bits): [consulta los detalles a continuación]

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

Ten en cuenta que long es un tipo especial que normalmente no se permite en JSON, pero se incluye en la especificación proto3. Por ejemplo, estos se codifican de la siguiente manera:

long

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

long sin firma

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

Por lo general, la clave @type se debe considerar reservada y no se debe utilizar para los mapas que se pasan.

Como en los tipos simples no se especifica el tipo, algunos valores lo cambian 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 produce un List.

Si se deserializa un mapa con un campo @type desconocido, se deja como un mapa. Esto permite que los desarrolladores agreguen campos con nuevos tipos a sus valores de retorno sin interrumpir los clientes anteriores.

Ejemplos de código

En los ejemplos de esta sección, se ilustra la forma de codificar los siguientes elementos:

  • Un ejemplo de callable.call en Swift
  • Una respuesta de ejecución correcta para la llamada
  • Una respuesta de ejecución con errores 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 la 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 para codificar

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

Encabezado de respuesta de ejecución correcta:

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

Cuerpo de respuesta de ejecución correcta:

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

Respuesta de ejecución con errores para codificar

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

Encabezado de respuesta de ejecución con errores:

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

Cuerpo de respuesta de ejecución con errores:

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