Especificação de protocolo para https.onCall

Um gatilho https.onCall para Cloud Functions é um gatilho HTTPS com um formato específico para solicitação e resposta. Esta seção fornece uma especificação para os formatos de solicitação e resposta HTTPS usados ​​pelos SDKs do cliente para implementar a API. Essas informações podem ser úteis se seus requisitos não puderem ser atendidos usando as plataformas Android, Apple ou SDKs da Web.

Formato de solicitação: cabeçalhos

A solicitação HTTP para um endpoint de gatilho que pode ser chamado deve ser um POST com os seguintes cabeçalhos:

  • Obrigatório: Content-Type: application/json
    • Um opcional ; charset=utf-8 é permitido.
  • Opcional: Authorization: Bearer <token>
    • Um token de ID de usuário do Firebase Authentication para o usuário conectado que faz a solicitação. O back-end verifica automaticamente esse token e o disponibiliza no context do manipulador. Se o token não for válido, a solicitação será rejeitada.
  • Opcional: Firebase-Instance-ID-Token: <iid>
    • O token de registro do FCM do SDK do cliente do Firebase. Deve ser uma string. Isso está disponível no context do manipulador. É usado para direcionar notificações push.
  • Opcional: X-Firebase-AppCheck: <token>
    • O token do Firebase App Check fornecido pelo aplicativo cliente que faz a solicitação. O back-end verifica automaticamente esse token e o decodifica, injetando o appId no context do manipulador. Se o token não puder ser verificado, a solicitação será rejeitada. (Disponível para SDK >=3.14.0)

Se quaisquer outros cabeçalhos forem incluídos, a solicitação será rejeitada, conforme descrito na documentação de resposta abaixo.

Observação: em clientes JavaScript, essas solicitações acionam uma simulação CORS OPTIONS porque:

  • application/json não é permitido. Deve ser text/plain ou application/x-www-form-urlencoded .
  • O cabeçalho Authorization não é um request-header na lista segura do CORS .
  • Outros cabeçalhos também não são permitidos.

O gatilho que pode ser chamado lida automaticamente com essas solicitações OPTIONS .

Solicitar corpo

O corpo da solicitação HTTP deve ser um objeto JSON com qualquer um dos seguintes campos:

  • Obrigatório: data – O argumento passado para a função. Pode ser qualquer valor JSON válido. Isso é automaticamente decodificado em tipos JavaScript nativos de acordo com o formato de serialização descrito abaixo.

Se houver algum outro campo presente na solicitação, o backend considera a solicitação malformada e ela é rejeitada.

Formato de resposta: códigos de status

Existem vários casos que podem resultar em diferentes códigos de status HTTP e códigos de status de string para erros na resposta.

  1. No caso de um erro HTTP antes do gatilho client ser invocado, a resposta não é tratada como uma função do cliente. Por exemplo, se um cliente tentar invocar uma função inexistente, ele receberá uma resposta 404 Not Found .

  2. Se o gatilho do cliente for invocado, mas a solicitação estiver no formato errado, como não ser JSON, ter campos inválidos ou faltar o campo de data , a solicitação será rejeitada com 400 Bad Request , com um código de erro INVALID_ARGUMENT .

  3. Se o token de autenticação fornecido na solicitação for inválido, a solicitação será rejeitada com 401 Unauthorized , com um código de erro UNAUTHENTICATED .

  4. Se o token de registro do FCM fornecido na solicitação for inválido, o comportamento será indefinido. O token não é verificado em todas as solicitações, exceto quando é usado para enviar uma notificação push ao FCM.

  5. Se o gatilho que pode ser chamado for invocado, mas falhar com uma exceção não tratada ou retornar uma promessa com falha, a solicitação será rejeitada com 500 Internal Server Error , com um código de erro INTERNAL . Isso evita que erros de codificação sejam acidentalmente expostos aos usuários finais.

  6. Se o callable for invocado e retornar uma condição de erro explícita usando a API fornecida para funções que podem ser chamadas, a solicitação falhará. O código de status HTTP retornado é baseado no mapeamento oficial do status de erro para o status HTTP, conforme definido em code.proto . O código de erro específico, a mensagem e os detalhes retornados são codificados no corpo da resposta conforme detalhado abaixo. Isso significa que se a função retornar um erro explícito com status OK , então a resposta terá status 200 OK , mas o campo error será definido na resposta.

  7. Se o acionador do cliente for bem-sucedido, o status da resposta será 200 OK .

Formato de resposta: cabeçalhos

A resposta tem os seguintes cabeçalhos:

  • Content-Type: application/json
  • Um opcional ; charset=utf-8 é permitido.

Corpo de resposta

A resposta de um endpoint do cliente é sempre um objeto JSON. No mínimo, ele contém result ou error , juntamente com quaisquer campos opcionais. Se a resposta não for um objeto JSON ou não contiver data ou error , o SDK do cliente deverá tratar a solicitação como falha com o código de erro do Google INTERNAL (13) .

  • error - Se este campo estiver presente, a solicitação será considerada com falha, independentemente do código de status HTTP ou se data também estiverem presentes. O valor deste campo deve ser um objeto JSON no formato padrão de mapeamento HTTP do Google Cloud para erros, com campos para status , message e (opcionalmente) details . O campo code não deve ser incluído. Se o campo status não estiver definido ou tiver um valor inválido, o cliente deverá tratar o status como INTERNAL , de acordo com code.proto . Se houver details , eles serão incluídos em qualquer informação do usuário anexada ao erro no SDK do cliente, se aplicável.
    Nota: O campo details aqui é um valor fornecido pelo usuário. Não é necessariamente uma lista de valores codificados por tipo de protótipo como no formato Google Status .
  • result - O valor retornado pela função. Pode ser qualquer valor JSON válido. O SDK do firebase-functions codifica automaticamente o valor retornado pelo usuário neste formato JSON. Os SDKs do cliente decodificam automaticamente esses parâmetros em tipos nativos de acordo com o formato de serialização descrito abaixo.

Se outros campos estiverem presentes, eles deverão ser ignorados.

Serialização

O formato de serialização para cargas de dados arbitrárias é o mesmo para a solicitação e a resposta.

Para consistência da plataforma, eles são codificados em JSON como se fossem o valor de um campo Any em um buffer de protocolo proto3, usando o mapeamento JSON padrão . Valores de tipos simples como null , int , double ou string são codificados diretamente e não incluem seu tipo explícito. Portanto, float e double são codificados da mesma maneira e você pode não saber qual é recebido do outro lado da chamada. Para tipos que não são nativos do JSON, é usada a codificação proto3 digitada para o valor. Para obter mais informações, consulte a documentação sobre Qualquer codificação JSON .

Os seguintes tipos são permitidos:

  • nulo null
  • int (assinado ou não assinado, até 32 bits) - por exemplo 3 ou -30 .
  • flutuar - por exemplo 3.14
  • duplo - por exemplo 3.14
  • booleano - true ou false
  • string - por exemplo "hello world"
  • mapa - por exemplo {"x": 3}
  • lista - por exemplo [1, 2, 3]
  • longo (assinado ou não, até 64 bits) - [veja detalhes abaixo]

Os valores NaN e Infinity para float e double não são suportados.

Observe que long é um tipo especial normalmente não permitido em JSON, mas é coberto pela especificação proto3. Por exemplo, eles são codificados como:

longo

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

não assinado há muito tempo

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

Em geral, a chave @type deve ser considerada reservada e não usada para mapas transmitidos.

Como o tipo não é especificado para tipos simples, alguns valores mudarão de tipo após passarem pela ligação. Um float passado torna-se um double . Um short se torna um int e assim por diante. No Android, tanto List quanto JSONArray são suportados para valores de lista. Nesses casos, passar um JSONArray produzirá um List .

Se um mapa com um campo @type desconhecido for desserializado, ele será deixado como um mapa. Isso permite que os desenvolvedores adicionem campos com novos tipos aos seus valores de retorno sem interromper os clientes mais antigos.

Amostras de código

Os exemplos nesta seção ilustram como codificar o seguinte:

  • Um exemplo callable.call em Swift
  • Uma resposta de sucesso para a chamada
  • Uma resposta de falha para a chamada

Exemplo Callable.call em Swift para codificar

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

Cabeçalho da solicitação:

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

Corpo da solicitação:

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

Resposta à codificação

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

Cabeçalho de resposta bem-sucedido:

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

Corpo de resposta bem-sucedido:

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

Resposta de falha na codificação

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

Cabeçalho de resposta com falha:

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

Corpo de resposta com falha:

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