以编程方式修改远程配置

本文档介绍如何以编程方式读取和修改一组 JSON 格式的参数和条件(称为远程配置模板)。这样您就可以在后端更改模板(客户端应用可以使用客户端库获取这些更改)。

借助此指南中所述 远程配置 REST APIAdmin SDK,您可以绕过在 Firebase 控制台中管理模板这种方式,直接将远程配置更改集成到您自己的流程中。例如,使用远程配置后端 API,您可以:

  • 安排远程配置更新。通过将 API 调用与 Cron 作业结合使用,您可以定期更改远程配置的值。
  • 批量导入配置值,从而高效地从您自己的专有系统过渡到 Firebase 远程配置。
  • 将远程配置与 Cloud Functions for Firebase 搭配使用,并根据服务器端发生的事件更改应用中的值。例如,您可以使用远程配置在应用中推广某项新功能,然后在检测到有足够多的用户与这项新功能进行交互后,自动关停该推广。

本指南的以下部分介绍了使用远程配置后端 API 可以执行的操作。要查看通过 REST API 执行这些任务的某些代码,请参阅以下示例应用之一:

使用 Firebase Admin SDK 修改远程配置

Admin SDK 是一组服务器库,让您可以从特权环境与 Firebase 进行交互。除了对远程配置执行更新之外,Admin SDK 还支持生成和验证 Firebase 身份验证令牌,读取和写入实时数据库等。 如需详细了解 Admin SDK 的使用要求和设置,请参阅将 Firebase Admin SDK 添加至服务器

在典型的远程配置流程中,您可能会获取当前模板,修改一些参数或参数组和条件,验证该模板,然后发布该模板。在发出这些 API 调用之前,您必须先对 SDK 发出的请求进行授权。

初始化 SDK 并授权 API 请求

如果在初始化 Admin SDK 时未提供任何参数,该 SDK 使用 Google 应用默认凭据并从 FIREBASE_CONFIG 环境变量中读取选项。如果 FIREBASE_CONFIG 变量的内容以一个 { 开头,则会被解析为一个 JSON 对象。如果不是以该字符开头,则 SDK 会假定该字符串是包含选项的 JSON 文件的名称。

例如:

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

获取当前的远程配置模板

使用远程配置模板时,请注意以下要求:这些模板受版本控制,每个版本的有效期均为 90 天(从创建之日起到将其替换为更新版本为止),而存储的版本总数不能超过 300 个。如需了解详情,请参阅模板和版本控制

您可以使用后端 API 以 JSON 格式获取当前活跃版本的远程配置模板。 要获取模板,请按以下步骤操作:

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

修改远程配置参数

您可以通过编程方式修改和添加远程配置参数和参数组。例如,向名为“new_menu”的现有参数组添加一个参数,以控制季节性信息的显示:

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

该 API 可让您创建新参数和参数组,或修改默认值、条件值和说明。 在任何情况下,您都必须在修改后明确发布模板。

修改远程配置条件

您可以通过编程方式修改和添加远程配置条件和条件值。例如,要添加新条件:

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

在任何情况下,您都必须在修改后明确发布模板。

远程配置后端 API 提供了多个条件和比较运算符,可供您更改应用的行为和外观。如需详细了解条件以及这些条件支持的运算符,请参阅条件表达式参考文档

验证远程配置模板

您也可以选择在发布更新之前对其进行验证,如下所示:

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

此验证过程会检查错误,例如参数和条件的重复键、无效的条件名称、不存在的条件或错误的电子标记格式。 例如,如果请求包含的键数超过允许的数量(2000 个),则会返回错误消息Param count too large

发布远程配置模板

检索到模板并使用所需更新对其进行了修改后,您就可以发布该模板了。按照本部分中的说明发布模板,将整个现有配置模板替换为更新的文件,系统会为新的有效模板分配一个版本号,该版本号比替换的模板大一号。

如有必要,可以使用 REST API 回滚到先前版本。 为了减轻更新中存在错误的风险,您可以在发布之前先进行验证

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

使用 REST API 修改远程配置

本部分介绍 https://firebaseremoteconfig.googleapis.com 上远程配置 REST API 的主要功能。 如需了解完整详情,请参阅 API 参考

获取访问令牌以对 API 请求进行身份验证和授权

Firebase 项目支持 Google 服务帐号,您可以使用这些帐号从应用服务器或受信任环境调用 Firebase 服务器 API。如果您在本地开发代码,或在本地部署您的应用,则可以使用通过此服务帐号获取的凭据来向服务器请求授权。

如需对服务帐号进行身份验证并授权其访问 Firebase 服务,您必须生成 JSON 格式的私钥文件。

如需为您的服务帐号生成私钥文件,请执行以下操作:

  1. 在 Firebase 控制台中,打开设置 > 服务帐号

  2. 点击生成新的私钥,然后点击生成密钥进行确认。

  3. 妥善存储包含密钥的 JSON 文件。

通过服务帐号进行授权时,有两种方式可为您的应用提供凭据。您可以设置 GOOGLE_APPLICATION_CREDENTIALS 环境变量,也可以在代码中明确传递指向服务帐号密钥的路径。第一种方式更为安全,因此我们强烈推荐。

如需设置环境变量,请执行以下操作

将环境变量 GOOGLE_APPLICATION_CREDENTIALS 设置为包含服务帐号密钥的 JSON 文件的文件路径:此变量仅适用于当前的 Shell 会话,因此请在开始新的会话时重新设置该变量。

Linux 或 macOS

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

Windows

使用 PowerShell:

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

完成上述步骤后,应用默认凭据 (ADC) 能够隐式确定您的凭据,如此您便能在非 Google 环境中测试或运行时使用服务帐号凭据。

将您的 Firebase 凭据与 Google API 客户端库一起用于首选语言,以检索短期有效的 OAuth 2.0 访问令牌:

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

在此示例中,Google API 客户端库使用 JSON Web 令牌(JWT)对请求进行身份验证。有关详情,请参阅 JSON 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

private static String getAccessToken() throws IOException {
  GoogleCredential googleCredential = GoogleCredential
      .fromStream(new FileInputStream("service-account.json"))
      .createScoped(Arrays.asList(SCOPES));
  googleCredential.refreshToken();
  return googleCredential.getAccessToken();
}

在您的访问令牌到期后,系统会自动调用令牌刷新方法以检索更新的访问令牌。

如需授予访问远程配置的权限,应请求 https://www.googleapis.com/auth/firebase.remoteconfig 范围。

修改远程配置模板

使用远程配置模板时,请注意以下要求:这些模板受版本控制,每个版本的有效期均为 90 天(从创建之日起到将其替换为更新版本为止),而存储的版本总数不能超过 300 个。如需了解详情,请参阅模板和版本控制

获取当前的远程配置模板

您可以使用后端 API 获取 JSON 格式的当前活跃版本的远程配置模板。 可执行以下命令:

cURL

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

此命令会将 JSON 有效载荷输出到一个文件中,并将标头(包括 Etag)输出到一个单独的文件中。

原始 HTTP 请求

Host: firebaseremoteconfig.googleapis.com

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

此 API 调用会返回以下 JSON 以及一个单独的标头,其中包含用于后续请求的ETag

验证远程配置模板

您也可以选择在发布更新前对其进行验证。 将网址参数 ?validate_only=true 附加到您的发布请求,验证模板更新。 如果响应中包含状态代码 200 以及后缀为 -0 的更新后的 ETag,则表示您的更新已成功通过验证。如果响应中的状态代码不是 200,则表示 JSON 数据包含错误,您必须在发布前进行更正。

更新远程配置模板

检索模板并使用所需更新修改 JSON 内容后,您就可以发布该模板了。按照本部分中的说明发布模板,将整个现有配置模板替换为更新的文件,系统会为新的有效模板分配一个版本号,该版本号比替换的模板大一号。

如有必要,可以使用 REST API 回滚到先前版本。 为了减轻更新中存在错误的风险,您可以在发布之前先进行验证

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

对于 curl 命令,您可以使用“@”字符后跟文件名来指定相应的内容。

原始 HTTP 请求

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

由于这是一个写入请求,因此该命令将修改 ETag,并将在下一个 PUT 命令的响应标头中提供更新后的 ETag。

修改远程配置条件

您可以通过编程方式修改远程配置条件和条件值。使用 REST API 时,必须直接编辑模板以修改条件,然后才能发布模板。

{
  "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."
    }
  }
}

上述修改首先定义了一组条件,然后为每个参数定义了默认值和基于条件的参数(条件值)值。它还为每个元素添加了说明(可选);像代码注释一样,这些是供开发者使用的,并不显示在应用中。另外,为便于版本控制,还提供了一个 ETag

远程配置后端 API 提供了多个条件和比较运算符,可供您更改应用的行为和外观。如需详细了解条件以及这些条件支持的运算符,请参阅条件表达式参考文档

HTTP 错误代码

状态代码 含义
200 已成功更新
400 发生验证错误。例如,如果某个请求包含的键数超过允许的数量(2000 个),则会返回 400(请求错误)错误,并显示错误消息 Param count too large。 另外,在以下两种情况下,可能会出现此 HTTPS 状态代码:
  • 由于值和条件集自您上次检索 ETag 值后发生了更新,因此导致版本不匹配错误。要解决此错误,您应该使用 GET 命令获取最新的模板和 ETag 值,更新该模板,然后使用该模板和最新 ETag 值进行提交。
  • 在未指定 If-Match 标头的情况下执行了 PUT 命令(更新远程配置模板请求)。
401 发生授权错误(未提供访问令牌;或者 Firebase Remote Config REST API 尚未添加到您在 Cloud Developer Console 中的项目)
403 发生身份验证错误(提供的访问令牌有误)
500 发生内部错误。如果发生此错误,请提交 Firebase 支持服务工单

如果看到状态代码 200,则意味着远程配置模板(项目的参数、值和条件)已更新,现已可用于使用此项目的应用。如果看到其他状态代码,则意味着以前存在的远程配置模板仍然有效。

在您提交对模板的更新后,请转到 Firebase 控制台,以验证您所做的更改是否按预期显示。这一步至关重要,因为条件的排序会影响它们的求值方式(第一个求值为 true 的条件会生效)。

ETag 用法和强制更新

Remote Config REST API 使用了实体标记 (ETag) 来避免竞态条件和对资源的重叠更新。要详细了解 ETag,请参阅 ETag - HTTP

针对 REST API,Google 建议您缓存最新 GET 命令提供的 ETag,并在发出 PUT 命令时在 If-Match 请求标头中使用该 ETag 值。如果您的 PUT 命令导致出现 HTTPS 状态代码 409,您应该发出最新 GET 命令来获取新的 ETag 和模板,供您的下一个 PUT 命令使用。

通过强制远程配置模板按如下方式进行更新,您可以不使用 ETag 及其提供的保护:If-Match: *。但是,我们不建议使用此方法,因为如果有多个客户端正在更新远程配置模板,此方法可能会导致对远程配置模板的更新丢失。如果多个客户端都在使用 API,或者来自 API 客户端和 Firebase 控制台用户的更新存在冲突,都可能会引发这种冲突。

如需如何管理远程配置模板版本的指导,请参阅远程配置模板和版本控制