2015-12-08 6 views
0

Я хочу, чтобы обеспечить мое приложение с этимТребуется объект: ошибка play.api.mvc.Result

def Secured[A](username: String, password: String)(action: Action[A]) = Action(action.parser) { 
request => request.headers.get("Authorization").flatMap { authorization => 
    authorization.split(" ").drop(1).headOption.filter { 
     encoded => new String(org.apache.commons.codec.binary.Base64.decodeBase64(encoded.getBytes)).split(":").toList match { 
     case u :: p :: Nil if u == username && password == p => true 
     case _ => false 
     } 
    }.map(_ => action(request)) }.getOrElse { 
    Unauthorized.withHeaders("WWW-Authenticate" -> """Basic realm="Secured"""") } } 

Но в getOrElse части, я получаю следующее сообщение об ошибке:

type mismatch; found : Object required: play.api.mvc.Result

Что неправильно?

+1

Посмотрите на типы, возвращаемые каждым блоком кода. Scala указывает объект, потому что они разные. –

ответ

2

Проблема в том, что action(request) возвращает Future[Result] не только Result. Таким образом, тип всего выражения до getOrElse равен Option[Future[Result]], и он ожидает Future[Result] в качестве параметра getOrElse.

Таким образом, на первом вы можете обернуть Unauthorized.withHeaders вещь в Future.successfull(...)

Следующая вещь, что результатом всего выражения, то есть Future[Result] и это не правильный тип аргумента для Action.apply(bodyParser)(...), но есть Action.async метод, который мог бы справиться с этим.

Так весь исправленный блок с исправлениями минимальным типа \ рефакторинга

import org.apache.commons.codec.binary.Base64 

def secured[A](username: String, password: String)(action: Action[A]) = 
    Action.async(action.parser) { 
    request => request.headers.get("Authorization").flatMap { authorization => 
     authorization.split(" ").drop(1).headOption.filter { encoded => 
     val bytes = Base64.decodeBase64(encoded.getBytes) 
     new String(bytes).split(":").toList match { 
      case u :: p :: Nil if u == username && password == p => true 
      case _ => false 
     } 
     }.map(_ => action(request)) 
    }.getOrElse { 
     Future.successful(
     Unauthorized.withHeaders(
      "WWW-Authenticate" -> """Basic realm="Secured"""")) 
    } 
    } 

Дальнейшие инъекции сахара может привести к еще более читаемым версии:

import org.apache.commons.codec.binary.Base64 

def secured[A](username: String, password: String)(action: Action[A]) = 
    Action.async(action.parser) { request => 
    val result = for { 
     authorization <- request.headers.get("Authorization") 
     Array(_, encoded, _*) <- Some(authorization.split(" ")) 
     bytes = Base64.decodeBase64(encoded.getBytes) 
     credentials = new String(bytes).split(":").toList 
     List(`username`, `password`) <- Some(credentials) 
    } yield action(request) 

    result.getOrElse { 
     Future.successful(
     Unauthorized.withHeaders(
      "WWW-Authenticate" -> """Basic realm="Secured"""")) 
    } 
    } 

Обратите внимание, что распаковка в левой части <- преобразуется в filter с match

Смежные вопросы