Modificar o Configuração remota de maneira programática

Neste documento, descrevemos como ler e modificar de forma programática o conjunto de parâmetros e condições formatados em JSON conhecidos como modelo da Configuração remota. Isso permite que você modifique o modelo do back-end que o app cliente pode buscar usando a biblioteca de cliente.

Usando a API REST da Configuração remota ou os SDKs Admin descritos neste guia, é possível ignorar o gerenciamento do modelo no Console do Firebase para integrar diretamente as modificações da Configuração remota nos seus próprios processos. Por exemplo, com as APIs de back-end da Configuração remota, é possível fazer o seguinte:

  • Agendar atualizações da Configuração remota: ao usar chamadas de API com um cron job, é possível alterar os valores da Configuração remota regularmente.
  • Importar valores de configuração em lotes: realize esta ação para fazer a transação de modo eficiente do seu próprio sistema para a Configuração remota do Firebase.
  • Usar a Configuração remota com o Cloud Functions para Firebase: você muda valores no seu app com base em eventos no lado do servidor. Por exemplo, é possível utilizar a Configuração remota para promover um novo recurso no seu app e desativar imediatamente a promoção se perceber que um número suficiente de pessoas já interagiu com a nova função.

    Diagrama mostrando o back-end da Configuração remota interagindo com ferramentas e servidores personalizados

Confira as seções a seguir deste guia para conhecer as operações que você consegue realizar com as APIs de back-end da Configuração remota. Para descobrir alguns códigos que executam essas tarefas usando a API REST, consulte um destes apps de exemplo (em inglês):

Modificar a Configuração remota usando o SDK Admin do Firebase

O SDK Admin é um conjunto de bibliotecas de servidor que permite interagir com o Firebase em ambientes com privilégios. Além de realizar atualizações na Configuração remota, o SDK Admin permite gerar e verificar tokens de autenticação do Firebase, ler e gravar no Realtime Database, entre outros. Para saber mais sobre os pré-requisitos e a configuração do SDK Admin, consulte Adicionar o SDK Admin do Firebase ao servidor.

Em um fluxo típico da Configuração remota, é possível ver o modelo atual, modificar alguns dos parâmetros ou grupos e condições de parâmetros, validar o modelo e publicar. Antes de fazer essas chamadas de API, você precisa autorizar solicitações do SDK.

Inicializar o SDK e autorizar solicitações de API

Quando você inicializa o SDK Admin sem parâmetros, o SDK usa o Google Application Default Credentials e lê as opções da variável de ambiente FIREBASE_CONFIG. Caso o conteúdo da variável FIREBASE_CONFIG comece com uma {, ele será analisado como um objeto JSON. Caso contrário, a string será tratada pelo SDK como o nome de um arquivo JSON que contém as opções.

Exemplo:

Node.js

const admin = require('firebase-admin');
admin.initializeApp();

Java

FileInputStream serviceAccount = new FileInputStream("service-account.json");
FirebaseOptions options = FirebaseOptions.builder()
        .setCredentials(GoogleCredentials.fromStream(serviceAccount))
        .build();
FirebaseApp.initializeApp(options);

Ver o modelo atual da Configuração remota

Ao trabalhar com modelos da Configuração remota, lembre que cada versão tem uma vida útil limitada, que vai desde a criação até a substituição por meio de uma atualização: 90 dias, com um limite total de 300 versões armazenadas. Consulte Modelos e controle de versões para mais informações.

É possível usar as APIs de back-end para ver a versão ativa atual do modelo da Configuração remota no formato JSON.

Os parâmetros e os valores de parâmetro criados especificamente como variantes em um experimento do Teste A/B não estão incluídos nos modelos exportados.

Para ver o modelo:

Node.js

function getTemplate() {
  var config = admin.remoteConfig();
  config.getTemplate()
      .then(function (template) {
        console.log('ETag from server: ' + template.etag);
        var templateStr = JSON.stringify(template);
        fs.writeFileSync('config.json', templateStr);
      })
      .catch(function (err) {
        console.error('Unable to get template');
        console.error(err);
      });
}

Java

Template template = FirebaseRemoteConfig.getInstance().getTemplateAsync().get();
// See the ETag of the fetched template.
System.out.println("ETag from server: " + template.getETag());

Modificar parâmetros da Configuração remota

É possível modificar e adicionar parâmetros e grupos de parâmetros da Configuração remota. Por exemplo, para um grupo de parâmetros atual chamado "new_menu", é possível adicionar um parâmetro para controlar a exibição de informações sazonais:

Node.js

function addParameterToGroup(template) {
  template.parameterGroups['new_menu'].parameters['spring_season'] = {
    defaultValue: {
      useInAppDefault: true
    },
    description: 'spring season menu visibility.',
  };
}

Java

template.getParameterGroups().get("new_menu").getParameters()
        .put("spring_season", new Parameter()
                .setDefaultValue(ParameterValue.inAppDefault())
                .setDescription("spring season menu visibility.")
        );

A API permite que você crie novos parâmetros e grupos de parâmetros ou modifique valores padrão, valores condicionais e descrições. Em todos os casos, você precisa publicar explicitamente o modelo depois de fazer as modificações.

Modificar condições da Configuração remota

É possível modificar e adicionar de forma programática condições e valores condicionais da Configuração remota. Por exemplo, para adicionar uma nova condição:

Node.js

function addNewCondition(template) {
  template.conditions.push({
    name: 'android_en',
    expression: 'device.os == \'android\' && device.country in [\'us\', \'uk\']',
    tagColor: 'BLUE',
  });
}

Java

template.getConditions().add(new Condition("android_en",
        "device.os == 'android' && device.country in ['us', 'uk']", TagColor.BLUE));

Em todos os casos, você precisa publicar explicitamente o modelo depois de fazer as modificações.

As APIs de back-end da Configuração remota oferecem várias condições e operadores de comparação que podem ser usados para mudar o comportamento e a aparência do seu app. Para saber mais sobre as condições e os operadores compatíveis, consulte a referência de expressão condicional.

Validar o modelo da Configuração remota

Se preferir, valide as atualizações antes de publicá-las, conforme mostrado a seguir:

Node.js

function validateTemplate(template) {
  admin.remoteConfig().validateTemplate(template)
      .then(function (validatedTemplate) {
        // The template is valid and safe to use.
        console.log('Template was valid and safe to use');
      })
      .catch(function (err) {
        console.error('Template is invalid and cannot be published');
        console.error(err);
      });
}

Java

try {
  Template validatedTemplate = FirebaseRemoteConfig.getInstance()
          .validateTemplateAsync(template).get();
  System.out.println("Template was valid and safe to use");
} catch (ExecutionException e) {
  if (e.getCause() instanceof FirebaseRemoteConfigException) {
    FirebaseRemoteConfigException rcError = (FirebaseRemoteConfigException) e.getCause();
    System.out.println("Template is invalid and cannot be published");
    System.out.println(rcError.getMessage());
  }
}

Esse processo de validação verifica se há erros, como chaves duplicadas de parâmetros e condições, nomes de condições inválidas ou condições não existentes ou etags incorretas. Por exemplo, uma solicitação que contém mais do que o número permitido de chaves (2.000) retornaria a mensagem de erro Param count too large.

Publicar o modelo da Configuração remota

Depois de recuperar um modelo e revisá-lo com as atualizações desejadas, será possível publicá-lo. Ao publicar um modelo, conforme descrito nesta seção, você substitui todo o modelo atual pelo arquivo atualizado. Além disso, o novo modelo ativo recebe uma versão que é um número maior do que aquele que foi substituído.

Se necessário, use a API REST para reverter para a versão anterior. Para reduzir o risco de erros em uma atualização, valide antes de publicar.

As personalizações e condições da Configuração remota estão incluídas nos modelos salvos. Por isso, é importante estar ciente das seguintes limitações ao tentar publicar em um projeto diferente:

  • As personalizações não podem ser importadas de um projeto para outro.

    Por exemplo, se as personalizações estiverem ativadas no seu projeto e você fizer o download e editar um modelo, é possível publicá-lo no mesmo projeto, mas não em outro, a menos que você exclua as personalizações.

  • As condições podem ser importadas de projeto para projeto. No entanto, é necessário que todos os valores condicionais específicos (como IDs do app ou públicos-alvo) apareçam no projeto de destino antes da publicação.

    Por exemplo, se você tiver um parâmetro da Configuração remota usando uma condição que especifique um valor de iOS para a plataforma, o modelo pode ser publicado em outro projeto, porque os valores da plataforma são iguais para qualquer projeto. No entanto, se houver uma condição que depende de um ID do app ou público de usuário específico que não existe no projeto de destino, a validação vai apresentar falhas.

  • Se o modelo que você planeja publicar contém condições que dependem do Google Analytics, ele precisa estar ativo no projeto de destino.

Node.js

function publishTemplate() {
  var config = admin.remoteConfig();
  var template = config.createTemplateFromJSON(
      fs.readFileSync('config.json', 'UTF8'));
  config.publishTemplate(template)
      .then(function (updatedTemplate) {
        console.log('Template has been published');
        console.log('ETag from server: ' + updatedTemplate.etag);
      })
      .catch(function (err) {
        console.error('Unable to publish template.');
        console.error(err);
      });
}

Java

try {
  Template publishedTemplate = FirebaseRemoteConfig.getInstance()
          .publishTemplateAsync(template).get();
  System.out.println("Template has been published");
  // See the ETag of the published template.
  System.out.println("ETag from server: " + publishedTemplate.getETag());
} catch (ExecutionException e) {
  if (e.getCause() instanceof FirebaseRemoteConfigException) {
    FirebaseRemoteConfigException rcError = (FirebaseRemoteConfigException) e.getCause();
    System.out.println("Unable to publish template.");
    System.out.println(rcError.getMessage());
  }
}

Modificar a Configuração remota usando a API REST

Nesta seção, descrevemos os principais recursos da API REST da Configuração remota em https://firebaseremoteconfig.googleapis.com. Para detalhes completos, consulte a referência da API.

Receber um token de acesso para autenticar e autorizar solicitações de API

Os projetos do Firebase oferecem suporte a contas de serviço do Google, que podem ser usadas para chamar APIs do servidor do Firebase a partir do seu servidor de aplicativos ou de um ambiente confiável. Se você estiver desenvolvendo código ou implantando o aplicativo localmente, será possível usar credenciais recebidas por essa conta de serviço para autorizar solicitações do servidor.

Para autenticar uma conta de serviço e autorizá-la para acessar os serviços do Firebase, gere um arquivo de chave privada no formato JSON.

Para gerar um arquivo de chave privada da conta de serviço, siga estas etapas:

  1. No Console do Firebase, abra Configurações > Contas de serviço.

  2. Clique em Gerar nova chave privada e selecione Gerar chave para confirmar.

  3. Armazene com segurança o arquivo JSON que contém a chave.

Ao autorizar por meio de uma conta de serviço, existem duas opções para fornecer as credenciais ao seu aplicativo. Defina a variável de ambiente GOOGLE_APPLICATION_CREDENTIALS ou transmita explicitamente o caminho para a chave da conta de serviço no código. A primeira opção é mais segura e é altamente recomendável.

Para definir a variável de ambiente:

Defina a variável de ambiente GOOGLE_APPLICATION_CREDENTIALS como o caminho do arquivo JSON que contém a chave da conta de serviço. Essa variável só se aplica à sessão de shell atual. Dessa maneira, se você abrir uma nova sessão, defina a variável novamente.

Linux ou macOS

export GOOGLE_APPLICATION_CREDENTIALS="/home/user/Downloads/service-account-file.json"

Windows

Com o PowerShell:

$env:GOOGLE_APPLICATION_CREDENTIALS="C:\Users\username\Downloads\service-account-file.json"

Depois de concluir as etapas acima, o Application Default Credentials (ADC) pode determinar implicitamente suas credenciais, permitindo que você use as credenciais da conta de serviço ao testar ou executar em ambientes que não são do Google.

Use as credenciais do Firebase com a Biblioteca do Google Auth para sua linguagem preferida e recupere um token de acesso do OAuth 2.0 de curta duração:

node.js

 function getAccessToken() {
  return admin.credential.applicationDefault().getAccessToken()
      .then(accessToken => {
        return accessToken.access_token;
      })
      .catch(err => {
        console.error('Unable to get access token');
        console.error(err);
      });
}

Neste exemplo, a biblioteca de cliente da API do Google autentica a solicitação com um token JSON da Web ou JWT. Para mais informações, consulte tokens JSON da web.

Python

def _get_access_token():
  """Retrieve a valid access token that can be used to authorize requests.

  :return: Access token.
  """
  credentials = ServiceAccountCredentials.from_json_keyfile_name(
      'service-account.json', SCOPES)
  access_token_info = credentials.get_access_token()
  return access_token_info.access_token

Java

public static String getAccessToken() throws IOException {
  GoogleCredentials googleCredentials = GoogleCredentials
          .fromStream(new FileInputStream("service-account.json"))
          .createScoped(Arrays.asList(SCOPES));
  googleCredentials.refreshAccessToken();
  return googleCredentials.getAccessToken().getTokenValue();
}

O método de atualização de token é chamado automaticamente para recuperar um token atualizado após o de acesso expirar.

Para autorizar o acesso à Configuração remota, solicite o escopo https://www.googleapis.com/auth/firebase.remoteconfig.

Modificar o modelo da Configuração remota

Ao trabalhar com modelos da Configuração remota, lembre que cada versão tem uma vida útil limitada, que vai desde a criação até a substituição por meio de uma atualização: 90 dias, com um limite total de 300 versões armazenadas. Consulte Modelos e controle de versões para mais informações.

Ver o modelo atual da Configuração remota

É possível usar as APIs de back-end para ver a versão ativa atual do modelo da Configuração remota no formato JSON.

Os parâmetros e os valores de parâmetro criados especificamente como variantes em um experimento do Teste A/B não estão incluídos nos modelos exportados.

Use os seguintes comandos:

cURL

curl --compressed -D headers -H "Authorization: Bearer token" -X GET https://firebaseremoteconfig.googleapis.com/v1/projects/my-project-id/remoteConfig -o filename

Este comando exporta o payload do JSON para um arquivo e os cabeçalhos (incluindo a ETag) para um arquivo separado.

Solicitação HTTP bruta

Host: firebaseremoteconfig.googleapis.com

GET /v1/projects/my-project-id/remoteConfig HTTP/1.1
Authorization: Bearer token
Accept-Encoding: gzip

Essa chamada de API retorna o JSON a seguir com um cabeçalho separado que inclui uma ETag usada para a solicitação subsequente.

Validar o modelo da Configuração remota

Se preferir, valide suas atualizações antes de publicá-las. Para validar as atualizações do modelo, inclua o parâmetro de URL ?validate_only=true na solicitação de publicação. Na resposta, um código de status 200 e uma ETag atualizada com o sufixo -0 significa que sua atualização foi validada com êxito. Qualquer resposta que não tenha o código 200 indica que os dados JSON contêm erros que precisam ser corrigidos antes da publicação.

Atualizar o modelo da Configuração remota

Depois de recuperar um modelo e revisar o conteúdo do JSON com as atualizações desejadas, ele estará pronto para publicação. Ao publicar um modelo, conforme descrito nesta seção, você substitui todo o modelo atual pelo arquivo atualizado. Além disso, o novo modelo ativo recebe uma versão que é um número maior do que aquele que foi substituído.

Se necessário, use a API REST para reverter para a versão anterior. Para reduzir o risco de erros em uma atualização, valide antes de publicar.

As personalizações e condições da Configuração remota estão incluídas nos modelos salvos. Por isso, é importante estar ciente das seguintes limitações ao tentar publicar em um projeto diferente:

  • As personalizações não podem ser importadas de um projeto para outro.

    Por exemplo, se as personalizações estiverem ativadas no seu projeto e você fizer o download e editar um modelo, é possível publicá-lo no mesmo projeto, mas não em outro, a menos que você exclua as personalizações.

  • As condições podem ser importadas de projeto para projeto. No entanto, é necessário que todos os valores condicionais específicos (como IDs do app ou públicos-alvo) apareçam no projeto de destino antes da publicação.

    Por exemplo, se você tiver um parâmetro da Configuração remota usando uma condição que especifique um valor de iOS para a plataforma, o modelo pode ser publicado em outro projeto, porque os valores da plataforma são iguais para qualquer projeto. No entanto, se houver uma condição que depende de um ID do app ou público de usuário específico que não existe no projeto de destino, a validação vai apresentar falhas.

  • Se o modelo que você planeja publicar contém condições que dependem do Google Analytics, ele precisa estar ativo no projeto de destino.

cURL

curl --compressed -H "Content-Type: application/json; UTF8" -H "If-Match: last-returned-etag" -H "Authorization: Bearer token" -X PUT https://firebaseremoteconfig.googleapis.com/v1/projects/my-project-id/remoteConfig -d @filename

Para este comando curl, especifique o conteúdo usando o caractere "@" seguido pelo nome do arquivo.

Solicitação HTTP bruta

Host: firebaseremoteconfig.googleapis.com
PUT /v1/projects/my-project-id/remoteConfig HTTP/1.1
Content-Length: size
Content-Type: application/json; UTF8
Authorization: Bearer token
If-Match: expected ETag
Accept-Encoding: gzip
JSON_HERE

Como esta é uma solicitação de gravação, a ETag é modificada por esse comando e uma ETag atualizada é fornecida nos cabeçalhos da resposta ao próximo comando PUT.

Modificar condições da Configuração remota

É possível modificar de maneira programática as condições e os valores condicionais da Configuração remota. Na API REST, antes de publicar o modelo, é necessário editá-lo diretamente para modificar as condições.

{
  "conditions": [{
    "name": "android_english",
    "expression": "device.os == 'android' && device.country in ['us', 'uk']",
    "tagColor": "BLUE"
  }, {
    "name": "tenPercent",
    "expression": "percent <= 10",
    "tagColor": "BROWN"
  }],
  "parameters": {
    "welcome_message": {
      "defaultValue": {
        "value": "Welcome to this sample app"
      },
      "conditionalValues": {
        "tenPercent": {
          "value": "Welcome to this new sample app"
        }
      },
      "description": "The sample app's welcome message"
    },
    "welcome_message_caps": {
      "defaultValue": {
        "value": "false"
      },
      "conditionalValues": {
        "android_english": {
          "value": "true"
        }
      },
      "description": "Whether the welcome message should be displayed in all capital letters."
    }
  }
}

As modificações acima definem primeiro um conjunto de condições e, em seguida, os valores padrão e de parâmetros baseados em condições (valores condicionais) de cada parâmetro. Além disso, adicionam uma descrição opcional para cada elemento. Assim como os comentários de código, eles são para uso do desenvolvedor e não são exibidos no aplicativo. Uma ETag também é fornecida para fins de controle de versão.

As APIs de back-end da Configuração remota oferecem várias condições e operadores de comparação que podem ser usados para mudar o comportamento e a aparência do seu app. Para saber mais sobre as condições e os operadores compatíveis, consulte a referência de expressão condicional.

Códigos de erro HTTP

Código de status Significado
200 Atualizado com sucesso.
400 Ocorreu um erro de validação. Por exemplo, uma solicitação que contém mais do que o número de chaves permitido (2.000) retorna o código 400 (Solicitação inválida) com a mensagem de erro Param count too large. Além disso, código de status HTTPS pode ocorrer em duas situações:
  • Ocorreu um erro de incompatibilidade de versão porque o conjunto de valores e condições foi atualizado após a última vez em que você recuperou um valor de ETag. Para resolver esse problema, você deve usar um comando GET para receber um novo modelo e valor de ETag e, depois, atualize e envie o modelo.
  • Um comando PUT (solicitação de modelo atualizado da Configuração remota) foi usado sem um cabeçalho If-Match.
401 Ocorreu um erro de autorização. Isso significa que nenhum token de acesso foi enviado ou que a API REST da Configuração remota do Firebase não foi adicionada ao seu projeto no Console para desenvolvedores do Cloud.
403 Ocorreu um erro de autenticação. O token de acesso fornecido está incorreto.
500 Ocorreu um erro interno. Se esse erro ocorrer, envie um tíquete de suporte para o Firebase.

Um código de status 200 indica que o modelo da Configuração remota (parâmetros, valores e condições do projeto) foi atualizado e agora está disponível para apps que usam esse projeto. Outros códigos de status indicam que o modelo da Configuração remota previamente existente ainda está em vigor.

Depois de enviar atualizações para seu modelo, acesse o Console do Firebase e verifique se as mudanças estão aparecendo conforme o esperado. Esta ação é fundamental, já que a ordem das condições afeta o modo como elas são definidas. A primeira condição que tiver uma definição true entrará em vigor.

Uso de ETag e atualizações forçadas

A API REST da Configuração remota usa uma tag de entidade (ETag) para evitar que ocorram disputas e sobreposições das atualizações nos recursos. Para saber mais sobre ETags, acesse ETag – HTTP (em inglês).

Para a API REST, o Google recomenda armazenar em cache a ETag fornecida pelo comando GET mais recente e usar esse valor de ETag no cabeçalho da solicitação If-Match ao emitir comandos PUT. Se o comando PUT resultar em um código de status HTTPS 409, emita um novo comando GET para receber uma nova ETag e um novo modelo a ser usado com seu próximo comando PUT.

É possível contornar a ETag e a proteção que ela oferece. Para isso, basta forçar a atualização do modelo da Configuração remota da seguinte forma: If-Match: * No entanto, essa abordagem não é recomendada porque você corre o risco de perder as atualizações do seu modelo caso vários clientes estejam atualizando o modelo. Esse tipo de conflito poderá ocorrer se vários clientes estiverem usando a API ou se houver atualizações conflitantes de clientes de APIs e usuários do Console do Firebase.

Para conferir orientações sobre o gerenciamento de versões de modelos da Configuração remota, consulte Modelos e controle de versões da Configuração remota.