Мне нравится писать директивы по распылению с экстракторами. Упрощенный пример одного из моих проектов:
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
}
}
}
}
}
Если пользователь не вошел в систему, то он выдает отказ которым обрабатывается seperatly:
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
директивы, которая принимает функцию типа: 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
}
+1. хороший информация. У меня вопрос, потому что я не так хорош в аэрозоле. Что я должен использовать как 'headerValue' (что это значит)? – boburShox
@boburShox, когда вы получаете новый запрос, 'headerValue' помогает вам извлечь значение из некоторого заголовка, если он существует, он принимает некоторую функцию, например,« partialFunction »для извлечения стиля шаблона:' { case HttpHeader (lowerCaseName , значение) ⇒ Некоторые (значение) case _ ⇒ None } '. И с этой функцией, если такой заголовок существует, возвращает вам необязательное значение. – 4lex1v