Akka HTTP异步指令

时间:2018-05-14 17:13:33

标签: scala promise akka-http

我希望在处理一系列合理路由之前,在基于Akka HTTP的Web服务器中实现异步会话令牌控制。

在我的实现思路中,我将有一个方法执行如下所示的身份验证:

def performAuthentication(sessionToken: String): Future[Result]

其中Result是包含身份验证结果的案例类。为了执行身份验证,我想写一个可以放在合理路由之前的指令,如下所示:

def authenticate: Directive1[SessionToken] = optionalHeaderValueByName("session-token").flatMap {
    case Some(sessionToken) if (...) => provide(SessionToken(sessionToken))
    case _ => complete(StatusCodes.Unauthorized)
}

SessionResult一个case类包装sessionToken,我将提供给subsequents路由。取代暂停点,我被迫等待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,它也可以提供一些值,可以放在正常的路由定义中?

1 个答案:

答案 0 :(得分:0)

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

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]