Skip to main content

本指南将指导您为现有的 API 设置一个简单的代理,该 API 部署在Backstage外部,并在Backstage前端插件中向该 API 发送请求。

如果您的插件需要访问应用程序接口,Backstage可提供3 种选择:

  1. 您可以直接访问 API, 2. 您可以创建一个后端插件,如果您是在使用前端插件的同时实现 API, 3. 您可以配置Backstage代理现有的 API。

目录

设置Backstage代理

假设您插件的应用程序接口托管在_https://api.myawesomeservice.com/v1_您希望能在Backstage的`/api/proxy/并添加名为X-Custom-Source您需要将以下内容添加到app-config.yaml`:

proxy:
'/<your-proxy-uri>':
target: https://api.myawesomeservice.com/v1
headers:
X-Custom-Source: backstage

有关代理配置选项的更多详情,请参阅代理部分.

使用Backstage代理调用应用程序接口

如果您遵循了前面的步骤,现在应该可以通过调用${backend-url}/api/proxy/<your-proxy-uri>原因是backend-url之所以引用代理,是因为Backstage后端创建并运行代理。 Backstage的结构使您可以独立于Backstage运行Backstage前端。 因此,在调用 API 时,您需要在 http 调用前加上Backstage URL。

调用服务的推荐模式是用一个实用程序应用编程接口本节介绍将 API 客户端封装到实用程序 API 中的步骤:

  • use createApiRef to create a new ApiRef * register an ApiFactory with your plugin using createApiFactory. This will wrap your API implementation, associate your ApiRef with your implementation and tell backstage how to instantiate it * finally, you can use your API in your components by calling useApi

定义应用程序接口客户端界面

接着前面的例子,我们假设_https://api.myawesomeservice.com/v1_有以下端点

| 方法 | 说明 | | :----------------------- | :---------------------- | |GET /users| 返回用户列表GET /users/{userId}| 返回单个用户DELETE /users/{userId}| 删除用户

下面是该应用程序接口的定义示例,它遵循Backstage的apiRef风格

/* src/api.ts */
import { createApiRef } from '@backstage/core-plugin-api';

export interface User {
name: string;
email: string;
}

export interface MyAwesomeApi {
url: string;
listUsers: () => Promise<List<User>>;
getUser: (userId: string) => Promise<User>;
deleteUser: (userId: string) => Promise<boolean>;
}

export const myAwesomeApiRef = createApiRef<MyAwesomeApi>({
id: 'plugin.my-awesome-api.service',
});

创建应用程序接口客户端

myAwesomeApiRef是您在 backstage 中用来引用插件中的 API 客户端的。 API ref 本身是一个全局单例对象,允许您引用实例化的 API。 实际实现过程如下:

/* src/api.ts */

/* .. */

import { DiscoveryApi } from '@backstage/core-plugin-api';

export class MyAwesomeApiClient implements MyAwesomeApi {
discoveryApi: DiscoveryApi;

constructor({discoveryApi}: {discoveryApi: DiscoveryApi}) {
this.discoveryApi = discoveryApi;
}

private async fetch<T = any>(input: string, init?: RequestInit): Promise<T> {
// As configured previously for the backend proxy
const proxyUri = '${await this.discoveryApi.getBaseUrl('proxy')}/<your-proxy-uri>';

const resp = await fetch(`${proxyUri}${input}`, init);
if (!resp.ok) throw new Error(resp);
return await resp.json();
}

async listUsers(): Promise<List<User>> {
return await this.fetch<List<User>>('/users');
}

async getUser(userId: string): Promise<User> {
return await this.fetch<User>(`/users/${userId}`);
}

async deleteUser(userId: string): Promise<boolean> {
return await this.fetch<boolean>(
`/users/${userId}`,
{ method: 'DELETE' }
);
}

有关 DiscoveryApi 的更多信息,请查看 > docs

将 ApiRef 与插件捆绑在一起

最后一块拼图是将myAwesomeApiRef工厂MyAwesomeApiClient通常在plugin.ts文件在插件的src这是一个示例,假设你在一个名为api.ts:

/* src/plugin.ts */
import { myAwesomeApiRef, MyAwesomeApiClient } from './api';
import {
createPlugin,
createRouteRef,
createApiFactory,
createRoutableExtension,
createComponentExtension,
discoveryApiRef,
} from '@backstage/core-plugin-api';

//..

export const myCustomPlugin = createPlugin({
id: '<your-plugin-name>',

// Configure a factory for myAwesomeApiRef
apis: [
createApiFactory({
api: myAwesomeApiRef,
deps: { discoveryApi: discoveryApiRef },
factory: ({ discoveryApi }) => new MyAwesomeApiClient({ discoveryApi }),
}),
],
});

在组件中使用应用程序接口

现在,您应该可以使用Backstage钩子访问应用程序接口了使用应用程序的插件代码。

/* plugins/my-awesome-plugin/src/components/AwesomeUsersTable.tsx */
import { useApi } from '@backstage/core-plugin-api';
import { myAwesomeApiRef } from '../../api';

export const AwesomeUsersTable = () => {
const apiClient = useApi(myAwesomeApiRef);

apiClient.listUsers()
.then(
..
)
}