客户端中间件
在 Hilla 中,中间件会拦截每一次调用的请求和响应,从而能够处理请求及其响应。
Hilla 中的中间件是一种特殊的 TypeScript 异步回调函数,在前端调用后端时执行。 它截获每次调用的请求和响应。 中间件可以获取调用上下文信息,包括端点(endpoint)和方法的名称,提供的参数及其他客户端调用选项。
客户端中间件属于高级主题,不建议大部分用户使用。
中间件结构
以下是一个用于日志记录的中间件示例及其结构解析。
Source code
my-log-middleware.ts
import { Middleware, MiddlewareContext, MiddlewareNext } from '@vaadin/hilla-frontend';
// 中间件就是一个异步函数,接收 `context` 和 `next` 参数
export const MyLogMiddleware: Middleware = async function(
context: MiddlewareContext,
next: MiddlewareNext
) {
// context 对象包含调用参数,详细描述见 ConnectClient 类的 `call` 方法
const {endpoint, method, params} = context;
console.log(
`Sending request to endpoint: ${endpoint} ` +
`method: ${method} ` +
`parameters: ${JSON.stringify(params)} `
);
// 另外,context 包含一个将通过网络发送的 Fetch API `Request` 实例。
const request: Request = context.request;
console.log(`${request.method} ${request.url}`);
// 调用下一个(next)异步函数,发送请求并获取响应。
const response: Response = await next(context);
// 响应为 Fetch API 的 `Response` 对象。
console.log(`Received response: ${response.status} ${response.statusText}`);
// 如果需要读取响应正文,可以克隆响应对象
const responseClone = response.clone();
console.log(await responseClone.text());
// 中间件返回一个响应。
return response;
}|
Note
|
Request 与 Response 是 Fetch API 接口。Hilla 中间件并未创建新的数据结构以表示网络请求与响应,而是使用由 Fetch API specification 声明的接口。 请访问 MDN web 文档以了解更多关于 Request API 和 Response API的信息。 |
在客户端中使用中间件
如需使用中间件,在实例化 Hilla TypeScript 客户端时,将您自定义的中间件放入 middlewares 数组选项:
Source code
connect-client.ts
connect-client.tsimport { ConnectClient } from '@vaadin/hilla-frontend';
import { MyLogMiddleware } from './my-log-middleware';
const client = new ConnectClient({
prefix: '/connect',
middlewares: [MyLogMiddleware]
});
export default client;或者,您也可以在已有客户端(例如生成的客户端)上修改 middlewares 数组:
Source code
index.ts
import client from 'Frontend/generated/connect-client.default';
import { MyLogMiddleware } from './my-log-middleware';
client.middlewares = [MyLogMiddleware];|
Caution
|
在运行时修改中间件
如果修改了 middlewares 数组,只有在修改后发起的请求才会使用新的 middlewares 数组。
为避免因此导致的问题,建议避免修改 middlewares,或只在首次调用前修改 middlewares。
|
使用中间件修改请求
如需在中间件内部对请求进行低级别修改,可将 context.request 替换为新的 Fetch API Request 实例:
Source code
my-api-dispatcher-middleware.ts
my-api-dispatcher-middleware.tsimport { Middleware, MiddlewareContext, MiddlewareNext } from '@vaadin/hilla-frontend';
// 一个示例中间件,针对特定请求使用另一台服务器
export const MyApiDispatcherMiddleware: Middleware = async function(
context: MiddlewareContext,
next: MiddlewareNext
) {
if (context.endpoint === 'ExternalEndpoint') {
const url = context.request.url.replace(
'http//my-app.example.com',
'http://external-endpoint.example.com'
);
context.request = new Request(url, context.request);
}
return await next(context);
};使用中间件自定义响应
中间件也可以通过返回一 个自定义的 Response 实例替换实际响应:
Source code
my-stub-middleware.ts
my-stub-middleware.tsimport { Middleware, MiddlewareContext, MiddlewareNext } from '@vaadin/hilla-frontend';
// 一个示例中间件,针对特定端点返回空响应,而不是调用后端端点
export const MyStubMiddleware: Middleware = async function(
context: MiddlewareContext,
next: MiddlewareNext
) {
if (context.endpoint === 'StubEndpoint') {
//
return new Response('{}');
}
return await next(context);
}