這裏的問題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推斷Object,因爲它們不同。 –