I currently have a directive that I'm using to secure resources in an Akka HTTP app, like so:
def authenticate: Directive1[Login] =
optionalHeaderValueByName("Authorization") flatMap {
val accessToken = authz.split(' ').last
case Some(authz) =>
LoggedInUser findByAccessToken accessToken match {
case Some(user) => provide(user)
case None => reject(AuthorizationFailedRejection)
}
case None => reject(AuthorizationFailedRejection)
}
where LoggedInUser.findByAccessToken()
makes a blocking query against a database, I would like to switch this for an asynchronous ask
to an actor which which can provide the same data, I'm OK with passing in the ActorRef
as a parameter to the directive but I cannot work out how to handle the Future
that the ask returns.
None of the Directive1
examples that come with Akka HTTP seem to do this (at least I could;t find any) although there are examples of directives returning Route
which do.
Is what I want to do even possible? Is a possible approach to create a StandardRoute
subclass with a field for the user credentials and return that somehow?
A “Directive” is a small building block used for creating arbitrarily complex route structures. Akka HTTP already pre-defines a large number of directives and you can easily construct your own: Basics. Structure.
The grand-child will be supervised by the child; the supervisor strategy for this relationship can also be configured using a DSL element (supervision directives are part of the Act trait):
The IBM® HTTP Server for i is configured using directives. A directive is used to define an attribute of the HTTP Server or how the HTTP Server operates. For example, the Listen directive defines what port the HTTP Server should wait on to handle incoming requests.
The entity method will either pass the value to the inner route or map the exception to a Rejection . The entity directive works in conjunction with as and akka. http. scaladsl. unmarshalling to convert some serialized “wire format” value into a higher-level object structure.
Yes, it is possible. As far as I understand you need something like this:
def authenticate: Directive1[Login] = {
def findByAccessToken(accessToken:String): Future[Option[Login]] = ???
optionalHeaderValueByName("Authorization").flatMap {
case Some(authz) =>
val accessToken = authz.split(' ').last
onSuccess(findByAccessToken(accessToken)).flatMap {
case Some(user) => provide(user)
case None => reject(AuthorizationFailedRejection)
}
case None => reject(AuthorizationFailedRejection)
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With