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 阅读器将无法看到readTreesearch方法。

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

编写新的 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 阅读器编写了大量单元测试,您可以加以利用。