首页 > 解决方案 > 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)
}

编译器警告我providecomplete返回两种不同的类型......这是正确的。

我的问题是:有没有办法编写一个Directive也可以提供一些价值的异步,可以放在正常的路由定义中?

标签: scalapromiseakka-http

解决方案


我认为您可以创建这样的指令

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]


推荐阅读