Interceptor Chain(拦截器链)
Interceptor Chain在应用开发中是一个很常见的设计模式,Fusion提供了HttpInterceptor
接口来支持拦截器链模式。
Scala是一门面向对象和函数式编程相融合的一门语言,在函数式编程中可通过函数的嵌套和各种高级处理来实现拦截器链的功能。
应用拦截器链
trait HttpInterceptor {
def filter(handler: HttpHandler): HttpHandler
}
def applyHttpInterceptorChain(httpHandler: HttpHandler, filters: Iterable[HttpInterceptor]): HttpHandler = {
val duce: HttpHandler = filters.foldLeft(httpHandler) {
(h, filter) =>
// interceptor.filter(handler)
// val result = interceptor.filter(h)
// req => result(req).getOrElse(h(req))
req =>
filter.filter(h).apply(req)
}
duce
}
在applyHttpInterceptorChain
函数中,对拦截器链filters
应用foldLeft
函数,即可非常优雅的应用每一个拦截器。
拦截器示例
拦截器示例 1:trace
class TraceHttpInterceptor(system: classic.ActorSystem) extends HttpInterceptor {
import system.dispatcher
override def interceptor(route: Route): Route = { ctx =>
val req = ctx.request
val traceHeader = RawHeader("trace-id", ObjectId.get().toHexString)
val headers = traceHeader +: req.headers
val request = req.copy(headers = headers)
route(ctx.withRequest(request)).map {
case RouteResult.Complete(response) => RouteResult.Complete(toTrace(response, traceHeader))
case a @ RouteResult.Rejected(_) => a
}
}
private def toTrace(response: HttpResponse, traceHeader: RawHeader): HttpResponse = {
val headers = traceHeader +: response.headers
response.copy(headers = headers)
}
}
TraceHttpInterceptor
实现了给接收到的HTTP请求添加 trace id 的功能,这在微服务中监控调用链非常有用。
拦截器示例 2:不做任务处理
class NothingHttpInterceptor extends HttpInterceptor {
override def interceptor(route: Route): Route = { ctx =>
route(ctx)
}
}
直接返回handler
,并不对HTTP请求过程做任务处理,就像 NothingHttpIntercepter
那样。你可以加入判断逻辑,
拦截器示例 3:终止调用链
某个拦截器想终止调用链的执行,在转换函数中抛出一个异常即可:
class TerminationHttpInterceptor extends HttpInterceptor {
override def filter(handler: HttpHandler): HttpHandler = { req =>
//handler(req).flatMap(resp => Future.failed(HttpResponseException(resp)))
// handler(req).map(resp => throw HttpResponseException(resp))
throw HttpResponseException(HttpResponse(StatusCodes.InternalServerError))
}
}
2.0.6