Scala: How to get the result of a Future -


i've method returns future this...

def istokenexpired(token: string): future[boolean] = {   ... } 

... , i've method invokes istokenexpired returns boolean this:

def isexpired(token: string): boolean = {   var result = true   istokenexpired(token).oncomplete {     case success(r) => result = r     case failure(_) => result = true   }   result } 

is there better way write isexpired method?

edit

as requested eecolor, let me provide more details. play application i've implemented authorization mechanism based on json web token (jwt). claims contained in jwt except expiration time, stored in mongodb collection. here below summary of how token class looks like:

class token {   ...    def id: string = { ... }   def issuetime: localdatetime = { ... }   def issuer: string = { ... }   ...   def isvalid: boolean = { ... }   def isexpired: boolean = { /* uses reactivemongo access mongodb  */ } } 

as can see, jwt properties self-contained except expiration info. method isexpired uses reactivemongo, returns future. make things more complex, use jwt in customized action this:

class securedaction[t <: controller] private(private val methodname: string)   extends actionbuilder[apirequest] {    ...    def invokeblock[a](request: request[a], block: (apirequest[a]) => future[simpleresult]) = {{     request.headers.get(headernames.authorization) match {       case some(header) => s"""$authtype (.*)""".r.unapplyseq(header).map(_.head.trim)       case _ => none     }} match {       case some(tokenstring) => {         val token = token(tokenstring)          if (!token.isvalid) {           logger.warn(s"request ${request.uri} not authorized: token ${token.id} has been tampered")           future.successful(unauthorized(autherrors.authenticationviolated(token.subject)(request).asjson))         } else if (token.isexpired) {           logger.debug(s"request ${request.uri} not authorized: token ${token.id} has expired")           future.successful(unauthorized(autherrors.authenticationexpired(token.subject)(request).asjson))         } else if (!isauthorized(token)) {           logger.info(s"request ${request.uri} not authorized: required claims not defined account ${token.subject}")           future.successful(forbidden(autherrors.requestnotauthorized(token.subject)(request).asjson))         } else {           logger.debug(s"request ${request.uri} authorized account ${token.subject}")           block(new apirequest(token, request))         }       }       case _ => {         logger.debug(s"request ${request.uri} not authenticated")         future.successful(unauthorized(           autherrors.requestnotauthenticated()(request).asjson         ).withheaders(headernames.www_authenticate -> authtype))       }     }   } 

as can see, need return future[play.mvc.results.result], not future[boolean]as return isexpired if used future.map. point?

the function wrote not work think. (likely) first return true , later set result variable.

normally this:

istokenexpired(token).map { result =>    // stuff } 

in framework play map future http response , give play future[simpleresult]. play knows how handle future results.

in general it's recommended not wait future complete in production code, work values in future , let framework using handle result.

in tests might come in handy wait result, can this:

await.result(somefuture, 5.seconds) 

edit

i extract construction of token end future[token]. allows me more compose things. allows me create code has better architecture , easier test.

i break down code more smaller methods, example below gives idea of direction take.

class tokenservice(connection: mongoconnection) {    def tokenfor(tokenstring: string): future[token] = ??? }  class securedaction(tokenservice: tokenservice) extends    actionbuilder[apirequest] {    import play.api.libs.concurrent.execution.implicits._    def invokeblock[a](request: request[a], block: (apirequest[a]) => future[simpleresult]) =     extracttokenfrom(request) match {       case some(tokenstring) => {          tokenservice.tokenfor(tokenstring) flatmap {           case token if (!token.isvalid) =>             logger.warn(s"request ${request.uri} not authorized: token ${token.id} has been tampered")             future.successful(unauthorized(autherrors.authenticationviolated(token.subject)(request).asjson))           case token if (token.isexpired) =>             logger.debug(s"request ${request.uri} not authorized: token ${token.id} has expired")             future.successful(unauthorized(autherrors.authenticationexpired(token.subject)(request).asjson))           case token if (!token.isauthorized) =>             logger.info(s"request ${request.uri} not authorized: required claims not defined account ${token.subject}")             future.successful(forbidden(autherrors.requestnotauthorized(token.subject)(request).asjson))           case token =>             logger.debug(s"request ${request.uri} authorized account ${token.subject}")             block(new apirequest(token, request))         }       }       case _ =>         logger.debug(s"request ${request.uri} not authenticated")         future.successful(unauthorized(           autherrors.requestnotauthenticated()(request).asjson).withheaders(headernames.www_authenticate -> authtype))     }    val authtype = "myauthtype"   val tokenheader = s"""$authtype (.*)""".r    def extracttokenfrom(request: requestheader) = {     val authorizationheader = request.headers.get(headernames.authorization)     authorizationheader flatmap {       case tokenheader(token) => some(token.trim)       case _ => none     }   } } 

Comments

Popular posts from this blog

PHPMotion implementation - URL based videos (Hosted on separate location) -

javascript - Using Windows Media Player as video fallback for video tag -

c# - Unity IoC Lifetime per HttpRequest for UserStore -