需要对象:play.api.mvc.Result 错误
Object required: play.api.mvc.Result error
我想用这个
来保护我的应用程序
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
怎么了?
问题是 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
我想用这个
来保护我的应用程序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
怎么了?
问题是 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