本指南将指导您为现有的 API 设置一个简单的代理,该 API 部署在Backstage外部,并在Backstage前端插件中向该 API 发送请求。
如果您的插件需要访问应用程序接口,Backstage可提供3 种选择:
目录
设置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 newApiRef
* register anApiFactory
with your plugin usingcreateApiFactory
. This will wrap your API implementation, associate yourApiRef
with your implementation and tell backstage how to instantiate it * finally, you can use your API in your components by callinguseApi
定义应用程序接口客户端界面
接着前面的例子,我们假设_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(
..
)
}