Skip to main content

URL 阅读器

概念​

Backstage 的某些核心插件必须从外部位置读取文件。软件目录必须读取目录信息.yaml实体描述符文件来注册和跟踪实体。软件模板在创建新组件之前,必须下载模板骨架文件。技术文档必须先下载标记源文件,然后才能生成文档网站。

由于读取文件的要求对 Backstage 插件非常重要,因此@backstage/backend-common软件包提供了专用的 API,用于从基于 URL 的远程位置(如 GitHub、GitLab、Bitbucket、Google Cloud Storage 等)读取文件,通常称为 "URL 阅读器"。 它负责向远程主机发出经过验证的请求,以便安全地读取私有文件。 如果用户拥有基于 GitHub 应用程序的身份验证设置,URL 阅读器甚至会刷新令牌,以避免达到 GitHub API 的速率限制。

因此,插件作者在尝试读取文件时不必担心这些问题。

接口​

当Backstage后端启动时,会创建一个新的 URL 阅读器实例。 您可以在Backstage后端的索引文件中看到它,即packages/backend/src/index.ts.示例

// File: packages/backend/src/index.ts

import { UrlReaders } from '@backstage/backend-common';

function makeCreateEnv(config: Config) {
// ....
const reader = UrlReaders.default({ logger: root, config });
//
}

该实例包含所有默认 URL 阅读器提供商随着需求的增加,更多的 URL 阅读器正在编写中,以支持不同的提供商。

URL 阅读器实例的通用接口如下所示。

export type UrlReader = {
/* Used to read a single file and return its content. */
readUrl(url: string, options?: ReadUrlOptions): Promise<ReadUrlResponse>;
/* Used to read a file tree and download as a directory. */
readTree(url: string, options?: ReadTreeOptions): Promise<ReadTreeResponse>;
/* Used to search a file in a tree. */
search(url: string, options?: SearchOptions): Promise<SearchResponse>;
};

在插件中使用 URL 阅读器​

reader实例在后端插件环境中可用,并传递给所有后端插件。范例当使用 URL 调用该实例的任何方法时,URL 阅读器会提取该 URL 的主机(例如github.com,ghe.mycompany.com使用@backstage/integration软件包,它会在集成:配置的app-config.yaml来了解如何根据提供的配置(如身份验证令牌、API 基本 URL 等)与主机协同工作。

确保您的特定插件后端文件位于packages/backend/src/plugins/<PLUGIN>.ts正在转发reader作为PluginEnvironment到实际插件的createRouter请参阅目录和技术文档后端插件。

阅读器实例一旦在插件中可用,其方法之一就可以直接与 URL 结合使用。 一些使用示例如下

  • readUrl - Catalogs 使用 readUrl 方法读取版本库中的 CODEOWNERS 文件。 * readTree - TechDocs 使用 readTree 方法下载 markdown 文件,以便生成文档站点。 * readTree - TechDocs 使用 NotModifiedError 来维护缓存,并加快和限制请求数量。 * search - Catalogs 使用 search 方法为包含 glob 模式的位置 URL 查找文件。

请注意,以基于 git 的版本控制系统为目标的 URL 阅读器可能会利用基于特定 git 提交创建 tar 压缩包的功能。 这样做的后果是,配置了的经由.gitattributes时,URL 阅读器将无法看到readTree或search方法。

请注意这一限制,并确保您插件的最终用户也能通过文档等途径了解这一限制。

编写新的 URL 阅读器​

如果现有的 URL 阅读器不能满足您的使用要求,而您又想为其他提供商添加新的 URL 阅读器,我们非常欢迎您提供新的 URL 阅读器!

请随意使用GitHub URL 阅读器作为灵感的源泉。

1.​

新 URL 阅读器的提供程序在Backstage也可以称为 "集成"。integrations:Backstage "部分的app-config.yaml配置文件应该是Backstage集成人员定义集成的主机 URL、身份验证详细信息和其他集成相关配置的地方。

@backstage/integration集成包是大部分集成特定代码的存放处,以便在整个 Backstage 中共享。 诸如 "读取集成配置并进行处理"、"为向主机发出的验证请求构建头文件 "或 "将普通文件 URL 转换为用于下载文件的 API URL "等功能都将存放在该集成包中。

2.创建 URL 阅读器​

创建一个新类,实现读取器内侧@backstage/backend-common创建并导出静态factory方法读取集成配置,并返回新阅读器应使用的主机 URL 映射。 参见GitHub URL 阅读器例如

3.​

我们希望确保所有 URL 阅读器的行为方式相同,因此,如果可能的话,所有的UrlReader不过,也可以先只实现其中一个接口,然后再解决其他接口的问题。

readUrl​

readUrl方法需要一个用户友好的 URL,当用户在浏览器中浏览提供商时,可以自然地从浏览器中复制这个 URL。

  • ✅ 有效 URL : https://github.com/backstage/backstage/blob/master/ADOPTERS.md * ❌ 无效 URL : https://raw.githubusercontent.com/backstage/backstage/master/ADOPTERS.md * ❌ 无效 URL : https://github.com/backstage/backstage/ADOPTERS.md

收到 URL 后、readUrl将用户友好型 URL 转换为 API URL,用于请求提供商的 API。

readUrl然后向提供程序接口发出验证请求,并返回包含文件内容和 ETag(如果提供程序支持)的响应。

readTree​

readTree方法也期望用户友好的 URL 类似于read但 URL 应指向一棵树(可以是版本库的根目录,甚至是子目录)。

  • ✅ 有效 URL : https://github.com/backstage/backstage * ✅ 有效 URL : https://github.com/backstage/backstage/blob/master * ✅ 有效 URL : https://github.com/backstage/backstage/blob/master/docs

使用提供者的 API 文档,找出可用于下载 zip 或 tar 包的 API 端点。 您可以下载整个树(如版本库),并在用户只期望下载子树的情况下过滤掉。 但有些 API 足够聪明,可以接受路径,并在下载的归档文件中只返回子树。

搜索​

search方法接收一个 URL 的 glob 模式,并返回一个与查询匹配的文件列表。

  • ✅ 有效 URL:https://github.com/backstage/backstage/blob/master/**/catalog-info.yaml * ✅ 有效 URL:https://github.com/backstage/backstage/blob/master/**/*.md * ✅ 有效 URL:https://github.com/backstage/backstage/blob/master/*/package.json * ✅ 有效 URL:https://github.com/backstage/backstage/blob/master/READM。

其核心逻辑是readTree可用于提取树内的所有文件,并返回与url.

添加到可用的 URL 阅读器​

有两种方法可以使用新的 URL 阅读器。

您可以通过更新默认方法的 URL 阅读器。

但对于不想开源的内部内容,您可以更新您的packages/backend/src/index.ts文件,并更新reader实例已创建。

// File: packages/backend/src/index.ts
const reader = UrlReaders.default({
logger: root,
config,
// This is where your internal URL Readers would go.
factories: [myCustomReader.factory],
});

5.​

上述所有方法都支持基于 ETag 的缓存。etag,则响应包含资源的 ETag(最好是转发提供者返回的 ETag)。 如果调用该方法时使用了etag,它会首先比较 ETag,然后返回一个NotModifiedError这种方法与实际的ETag和不匹配HTTP 标头。

6.​

调试 URL 阅读器时,可以直接使用读者当后端程序启动时,调用其中一个带有调试 URL 的方法。

// File: packages/backend/src/index.ts

async function main() {
// ...
const createEnv = makeCreateEnv(config);

const testReader = createEnv('test-url-reader').reader;
const response = await testReader.readUrl(
'https://github.com/backstage/backstage/blob/master/catalog-info.yaml',
);
console.log((await response.buffer()).toString());
// ...
}

每次重启后端时都会运行。 请注意,URL 阅读器代码发生任何变化后,都需要停止后端并重启。reader此外,我们还为 URL 阅读器编写了大量单元测试,您可以加以利用。