エクストラクタを使用してスプレー ディレクティブを作成するのが好きです。私のプロジェクトの単純化された例:
def loggedInUser: Directive[Option[User] :: HNil] = headerValue {
case Cookie(cookies) => cookies.find(_.name === usrCookie) ∘ extractUserFromCookie
case _ => None
} | reject(NoUserLoggedInRejection)
def authOpt(usrOpt: Option[User], usr: String): Directive0 =
authorize(usrOpt.filter(_.login ≠ usr).isEmpty)
次に、ルーティング ファイルでエクストラクタを使用できます。
pathPrefix("path") {
loggedInUser { user =>
authOpt(user, Clients.client) {
path("path") {
get {
complete {
html.page() // i'm using Twirl as a fe engine
}
}
}
}
}
ユーザーがログインしていない場合は、個別に処理される拒否をスローします。
implicit val customRejectionHandlers = RejectionHandler {
case NoUserLoggedInRejection :: _ =>
ctx => ctx.redirect("/auth", StatusCodes.SeeOther)
}
セキュリティの例の場合、それは最善ではありませんが、十分に明確だと思います
追加した
headerValue
コメントからのディレクティブの例:
// Lets define a extractor for the Host header from the request
val hostExtractor: HttpHeader => Option[String] = {
case Host(host, port) => Some(host)
case _ => None
}
// Then some path
val route = {
path("somePath") {
post {
headerValue(hostExtractor) { host =>
complete(host)
}
}
}
}
そのようなディレクティブのほとんどはextract
、 type: の関数を取り、RequestContext ⇒ T
を返すディレクティブを介して実装されますT
。たとえば、次の方法headerValue
でも実装されますextract
。
extract(_.request.headers.mapFind(protectedF)).flatMap {
case Some(Right(a)) ⇒ provide(a)
case Some(Left(rejection)) ⇒ reject(rejection)
case None ⇒ reject
}