使用 Hosting REST API 向您的网站部署内容

Firebase Hosting REST API 让您可以对 Firebase 托管的网站进行程序化和自定义的部署。 使用此 REST API 可以部署全新或经过更新的托管配置和内容文件。

如果不想使用 Firebase 命令行界面 (CLI) 进行部署,您可以使用 Firebase Hosting REST API 以编程方式为您的网站创建资源的新 version,将文件上传到该版本,然后将该版本部署到您的网站。

例如,可以使用 Firebase Hosting REST API 执行下列操作:

  • 安排部署时间。通过将 REST API 与 Cron 作业结合使用,您可以定期更改 Firebase 托管的内容(例如,部署与特殊节日或事件相关的内容版本)。

  • 与开发者工具集成。您可以在您的工具中创建一个选项,只需点击一下即可将 Web 应用项目部署到 Firebase 托管(例如,点击 IDE 中的部署按钮)。

  • 在生成静态内容时自动部署。当某个进程以编程方式生成静态内容(例如,Wiki 或新闻文章等由用户生成的内容)时,您可以将生成的内容部署为静态文件,而不是动态地提供这些内容。这可以为您节省昂贵的计算资源,并以更具可扩缩性的方式提供文件。

本指南首先介绍如何启用 API 并对其进行身份验证和授权,然后通过一个示例来逐步演示如何创建 Firebase 托管版本,将所需文件上传到该版本,最后部署该版本。

您还可以在完整的 Hosting REST API 参考文档中详细了解此 REST API。

准备工作:启用 REST API

您必须在 Google API 控制台中启用 Firebase Hosting REST API:

  1. 在 Google API 控制台中打开 Firebase Hosting API 页面

  2. 出现提示时,选择您的 Firebase 项目。

  3. 在 Firebase Hosting API 页面上点击启用

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

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

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

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

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

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

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

将您的 Firebase 凭据与适用于您的偏好语言的 Google API 客户端库结合使用,以检索短期有效的 OAuth 2.0 访问令牌:

node.js

const {google} = require('googleapis');
function getAccessToken() {
  return new Promise(function(resolve, reject) {
    var key = require('./service-account.json');
    var jwtClient = new google.auth.JWT(
      key.client_email,
      null,
      key.private_key,
      SCOPES,
      null
    );
    jwtClient.authorize(function(err, tokens) {
      if (err) {
        reject(err);
        return;
      }
      resolve(tokens.access_token);
    });
  });
}

在此示例中,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();
}

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

第 2 步:为您的网站创建新版本

您的第一个 API 调用是为您的网站创建新的 Version。在本指南的后面部分,您会将文件上传到此版本,然后将其部署到您的网站。

  1. 确定您要部署新版本的网站的 site-name

  2. 在调用中使用您的 site-name 来调用 versions.create 端点。

    (可选)您还可以在调用中传递 Firebase 托管配置对象,包括设置将所有文件缓存指定时间长度的标头。

    例如:

    cURL 命令

    curl -H "Content-Type: application/json" \
           -H "Authorization: Bearer access-token" \
           -d '{
                 "config": {
                   "headers": [{
                     "glob": "**",
                     "headers": {
                       "Cache-Control": "max-age=1800"
                     }
                   }]
                 }
               }' \
    https://firebasehosting.googleapis.com/v1beta1/sites/site-name/versions
    

    原始 HTTP 请求

    Host: firebasehosting.googleapis.com
    
    POST /v1beta1/sites/site-name/versions HTTP/1.1
    Authorization: Bearer access-token
    Content-Type: application/json
    Content-Length: 134
    
    {
      "config": {
        "headers": [{
          "glob": "**",
          "headers": {
            "Cache-Control": "max-age=1800"
          }
        }]
      }
    }
    

versions.create 进行的这一 API 调用会返回以下 JSON:

{
  "name": "sites/site-name/versions/version-id",
  "status": "CREATED",
  "config": {
    "headers": [{
      "glob": "**",
      "headers": {
        "Cache-Control": "max-age=1800"
      }
    }]
  }
}

此响应包含新版本的唯一标识符,格式为 sites/site-name/versions/version-id。在本指南中,您将需要此唯一标识符来引用此特定版本。

第 3 步:指定要部署的文件列表

有了新的版本标识符后,您需要告诉 Firebase 托管您希望最终在此新版本中部署哪些文件。

此 API 要求您用 SHA256 哈希值来标识文件。因此,在进行 API 调用之前,首先需要计算每个静态文件的哈希值。为此,请使用 Gzip 对文件进行压缩,然后计算压缩后的每个文件的 SHA256 哈希值。

在此示例中,假设您想要在新版本中部署三个文件:file1file2file3

  1. 用 Gzip 压缩文件:

    gzip file1 && gzip file2 && gzip file3

    您现在有三个压缩文件 file1.gzfile2.gzfile3.gz

  2. 获取每个压缩文件的 SHA256 哈希值:

    cat file1.gz | openssl dgst -sha256
    
    66d61f86bb684d0e35f94461c1f9cf4f07a4bb3407bfbd80e518bd44368ff8f4
    
    cat file2.gz | openssl dgst -sha256
    
    490423ebae5dcd6c2df695aea79f1f80555c62e535a2808c8115a6714863d083
    
    cat file3.gz | openssl dgst -sha256
    
    59cae17473d7dd339fe714f4c6c514ab4470757a4fe616dfdb4d81400addf315
    

    您现在拥有了三个压缩文件的三个 SHA256 哈希值。

  3. 在一个 API 请求中将这三个哈希值发送到 versions.populateFiles 端点。按已上传文件(在此示例中为 /file1/file2/file3)的目标路径列出每个哈希值。

    例如:

    cURL 命令

    $ curl -H "Content-Type: application/json" \
             -H "Authorization: Bearer access-token" \
             -d '{
                   "files": {
                     "/file1": "66d61f86bb684d0e35f94461c1f9cf4f07a4bb3407bfbd80e518bd44368ff8f4",
                     "/file2": "490423ebae5dcd6c2df695aea79f1f80555c62e535a2808c8115a6714863d083",
                     "/file3": "59cae17473d7dd339fe714f4c6c514ab4470757a4fe616dfdb4d81400addf315"
                   }
                 }' \
    https://firebasehosting.googleapis.com/v1beta1/sites/site-name/versions/version-id:populateFiles
    

    原始 HTTP 请求

    Host: firebasehosting.googleapis.com
    
    POST /v1beta1/sites/site-name/versions/version-id:populateFiles HTTP/1.1
    Authorization: Bearer access-token
    Content-Type: application/json
    Content-Length: 181
    
    {
      "files": {
        "/file1": "66d61f86bb684d0e35f94461c1f9cf4f07a4bb3407bfbd80e518bd44368ff8f4",
        "/file2": "490423ebae5dcd6c2df695aea79f1f80555c62e535a2808c8115a6714863d083",
        "/file3": "59cae17473d7dd339fe714f4c6c514ab4470757a4fe616dfdb4d81400addf315"
      }
    }
    

versions.populateFiles 进行的这一 API 调用会返回以下 JSON:

{
  "uploadRequiredHashes": [
    "490423ebae5dcd6c2df695aea79f1f80555c62e535a2808c8115a6714863d083",
    "59cae17473d7dd339fe714f4c6c514ab4470757a4fe616dfdb4d81400addf315"
  ],
  "uploadUrl": "https://upload-firebasehosting.googleapis.com/upload/sites/site-name/versions/version-id/files"
}

此响应包括:

  • 需要上传的每个文件的哈希值。例如,在此示例中,file1 已经在先前版本中上传,因此其哈希值不包含在 uploadRequiredHashes 列表中。

  • 新版本专属的 uploadUrl

下一步是上传这两个新文件,您将需要这些哈希值和来自 versions.populateFiles 响应的 uploadURL

第 4 步:上传必需的文件

您需要单独上传每个必需的文件(这些文件由上一步中来自 versions.populateFiles 响应的 uploadRequiredHashes 列出)。上传这些文件时,您需要上一步中的文件哈希值和 uploadUrl

  1. uploadUrl 后附加正斜杠文件哈希值来创建文件专属网址,格式如下:https://upload-firebasehosting.googleapis.com/upload/sites/site-name/versions/version-id/files/file-hash

  2. 使用一系列请求将所有必需文件(在此示例中,只有 file2.gzfile3.gz)逐个上传到该文件专属网址。

    例如,上传压缩后的 file2.gz

    cURL 命令

    curl -H "Authorization: Bearer access-token" \
           -H "Content-Type: application/octet-stream" \
           --data-binary @./file2.gz \
    https://upload-firebasehosting.googleapis.com/upload/sites/site-name/versions/version-id/files/file-hash
    

    原始 HTTP 请求

    Host: upload-firebasehosting.googleapis.com
    
    POST /upload/sites/site-name/versions/version-id/files/file-hash HTTP/1.1
    Authorization: Bearer access-token
    Content-Type: application/octet-stream
    Content-Length: 500
    
    content-of-file2.gz
    

成功上传后会返回 200 OK HTTP 响应。

第 5 步:将版本的状态更新为 FINALIZED

上传 versions.populateFiles 响应中列出的所有文件后,您可以将版本状态更新为 FINALIZED

调用 versions.patch 端点,并将 API 请求中的 status 字段设置为 FINALIZED

例如:

cURL 命令

curl -H "Content-Type: application/json" \
       -H "Authorization: Bearer access-token" \
       -X PATCH \
       -d '{"status": "FINALIZED"}' \
https://firebasehosting.googleapis.com/v1beta1/sites/site-name/versions/version-id?update_mask=status

原始 HTTP 请求

Host: firebasehosting.googleapis.com

PATCH /v1beta1/sites/site-name/versions/version-id?update_mask=status HTTP/1.1
Authorization: Bearer access-token
Content-Type: application/json
Content-Length: 23

{"status": "FINALIZED"}

versions.patch 进行的这一 API 调用会返回以下 JSON。请检查 status 是否已更新为 FINALIZED

{
  "name": "sites/site-name/versions/version-id",
  "status": "FINALIZED",
  "config": {
    "headers": [{
      "glob": "**",
      "headers": {"Cache-Control": "max-age=1800"}
    }]
  },
  "createTime": "2018-12-02T13:41:56.905743Z",
  "createUser": {
    "email": "service-account-email@site-name.iam.gserviceaccount.com"
  },
  "finalizeTime": "2018-12-02T14:56:13.047423Z",
  "finalizeUser": {
    "email": "your-email@domain.tld"
  },
  "fileCount": "5",
  "versionBytes": "114951"
}

第 6 步:发布要部署的版本

有了最终确定的版本之后,请发布该版本以进行部署。在这一步中,您需要为版本创建 Release,其中包含新版本的托管配置和所有内容文件。

调用 releases.create 端点以创建您的发布内容。

例如:

cURL 命令

curl -H "Authorization: Bearer access-token" \
       -X POST
https://firebasehosting.googleapis.com/v1beta1/sites/site-name/releases?versionName=sites/site-name/versions/version-id

原始 HTTP 请求

Host: firebasehosting.googleapis.com

POST /v1beta1/sites/site-name/releases?versionName=sites/site-name/versions/version-id HTTP/1.1
Authorization: Bearer access-token

releases.create 进行的这一 API 调用会返回以下 JSON:

{
  "name": "sites/site-name/releases/release-id",
  "version": {
    "name": "sites/site-name/versions/version-id",
    "status": "FINALIZED",
    "config": {
    "headers": [{
      "glob": "**",
      "headers": {"Cache-Control": "max-age=1800"}
    }]
  }
  },
  "type": "DEPLOY",
  "releaseTime": "2018-12-02T15:14:37Z"
}

现在新版本的托管配置和所有文件应该都已部署到您的网站,而且您可以使用以下网址访问您的文件了:

  • https://site-name.web.app/file1
  • https://site-name.web.app/file2
  • https://site-name.web.app/file3

这些文件还可以通过与您的 site-name.firebaseapp.com 网域关联的网址进行访问。

您还可以在 Firebase 控制台中的托管页面上看到新的发布内容。