scala - Akka HTTP 异步指令
问题描述
在处理一系列合理路由之前,我想在基于 Akka HTTP 的 Web 服务器中实现异步会话令牌控制。
在我的实现理念中,我将有一个执行身份验证的方法,如下所示:
def performAuthentication(sessionToken: String): Future[Result]
whereResult
将是一个包含身份验证结果的案例类。为了执行身份验证,我想编写一个可以放在合理路由之前的指令,如下所示:
def authenticate: Directive1[SessionToken] = optionalHeaderValueByName("session-token").flatMap {
case Some(sessionToken) if (...) => provide(SessionToken(sessionToken))
case _ => complete(StatusCodes.Unauthorized)
}
用SessionResult
一个案例类包装我将提供给后续路由的 sessionToken。代替暂停点,我被迫等待Promise
结果,因为如果我实现该onComplete ... Success ... Failure
模式,如下所示:
onComplete(this.performAuthentication(sessionToken)) {
case Success(value) if (value.isAuthenticated) => provide(SessionToken(sessionToken))
case Failure(ex) => failWith(ex)
case _ => complete(StatusCodes.Unauthorized)
}
编译器警告我provide
并complete
返回两种不同的类型......这是正确的。
我的问题是:有没有办法编写一个Directive
也可以提供一些价值的异步,可以放在正常的路由定义中?
解决方案
我认为您可以创建这样的指令
type Token = String
def checkRequest(f: HttpRequest => Future[Token])(implicit ec: ExecutionContext): Directive1[Token] =
Directive { inner => ctx =>
val futureToken = f(ctx.request)
futureToken.flatMap(tkn => inner(Tuple1(tkn))(ctx))
}
您可以通过为其提供一个执行身份验证的函数来创建此指令。如果您也想处理拒绝,Token
可能是Either[ErrorAuth, Token]