Проблема в том, что 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
Посмотрите на типы, возвращаемые каждым блоком кода. Scala указывает объект, потому что они разные. –