Skip to Content
🎉 gRPCity 3.0 is released. Read more →
文档高级功能Server Middleware

Server Middleware

服务端中间件在每次入站 RPC 前后包一层。思路与 客户端中间件 相同,区别在上下文:这里你可以读取入站 metadata、修改响应、附加 trailing metadata,或把抛出的错误转成 status。

洋葱模型

gRPCity 服务端同样使用 Koa 风格的洋葱模型中间件:每个函数自己决定何时调 next()next() 之前与之后的代码把下层逻辑包在中间。

a → b → c 顺序注册三个中间件,调用轨迹如下:

enter a enter b enter c rpc-method() exit c exit b exit a

用法

gRPCity server 提供了server.use()的方法用于添加中间件。

当前版本只有 async unaryasync stream 的方法支持中间件,streamcallback 暂不支持。

使用方法如下:

const server = await loader.initServer() // 逐个添加 server.use(f1) server.use(f2) server.use(f3) // 传入多个参数添加 server.use(f1, f2, f3) // 使用数组添加 server.use([f1, f2, f3])

添加中间件的使用位置在initServer()之后,在listen()之前。

上下文

const middleware = async (ctx, next) => { console.log(ctx) await next() console.log(ctx) }

第一个打印的上下文,可以看到包含了 pathmethodrequestmetadatapeer,这些都是进行服务器处理之前获取的,可以对其进行修改。 其中method包含了调用的类型和请求的metadataoptions参数。

Terminal
{ path: '/helloworld.Greeter/SayGreet', method: { requestStream: false, responseStream: false }, request: { name: 'greeter' }, metadata: Metadata { internalRepr: Map(3) { 'x-client-hostname' => [Array], 'x-service-path' => [Array], 'user-agent' => [Array] }, options: {} }, peer: '127.0.0.1:64929' }

第二个打印上下文,额外response,是执行后添加的,可以修改,最终响应的是修改好的结果。

Terminal
{ path: '/helloworld.Greeter/SayGreet', method: { requestStream: false, responseStream: false }, request: { name: 'greeter' }, metadata: Metadata { internalRepr: Map(3) { 'x-client-hostname' => [Array], 'x-service-path' => [Array], 'user-agent' => [Array] }, options: {} }, peer: '127.0.0.1:64929', response: { message: 'hello greeter by Greeter', count: 1 } }

例子

log.js
const log = async (ctx, next) => { const startTime = Date.now() await next() const responseTimeMs = Date.now() - startTime console.log({ path: ctx.path, peer: ctx.peer, request: ctx.request, responseTimeMs }) } export default log

添加中间件

server.js
import log from './log.js' // other... server.use(log)

至此,我们完成了服务端中间件的编写与使用。

Last updated on