3

Я пытаюсь создать приложение с несколькими арендаторами, используя Play Framework 2.2, и столкнулся с проблемой. Я хочу установить ключ сеанса в глобальном onRouteRequest (или onRequest на Java), который идентифицирует идентификатор сайта для домена, который запрашивает пользователь. В буквальном смысле десятки других фреймворков этот тип вещей безболезнен (например, Django), но я узнаю, что объект сеанса в Play, по-видимому, неизменен.Play Framework Multi-Tenant Filter

Итак, прямо сейчас, у меня есть что-то вроде этого:

override def onRouteRequest(request: RequestHeader): Option[Handler] = { 
    if (request.session.get("site").isEmpty){ 
     val id = models.Site.getSiteUIDFromURL(request.host.toLowerCase()).toString() 
     if (!id.isEmpty){ 
     //what goes here to set the session? 
     }else{ 
     //not found - redirect to a general notFound page 
     } 
    } 
    super.onRouteRequest(request) 
    } 

И, хотя это не самый эффективный способ использования поиска в базе данных, он работает для тестирования прямо сейчас. Мне нужно установить ключ сеанса в глобальном, но я полностью потерял его, как это сделать. Если есть какие-то лучшие методы, я все уши (возможно, обертываю мои контроллеры?).

Я открыт для примеров решений в Java или Scala.

ответ

6

Думайте о действиях в игре как о вызовах функций, входной сигнал является запросом, результатом является результат. Если вы хотите изменить результат обернутого вызова функции, вы должны сначала вызвать эту функцию, а затем применить свое изменение. Добавление ключа в сеанс изменяет результат, поскольку сеанс отправляется клиенту в файл cookie сеанса. В приведенном выше коде вы пытаетесь выполнить изменение, прежде чем у вас будет результат для изменения, т. Е. До того, как вы вызовете super.onRouteRequest.

Если вам не нужно изменять маршрутизацию вообще, то не делайте этого в onRouteRequest, делайте это в фильтре, намного проще там. Но, предполагая, что вам нужно изменить маршрутизацию, вам необходимо применить фильтр к возвращенному обработчику. Это то, что она может выглядеть следующим образом:

override def onRouteRequest(request: RequestHeader): Option[Handler] = { 
    val maybeSite: Option[String] = request.session.get("site").orElse { 
    // Let's just assume that getSiteUIDFromUrl returns Option[String], always use Option if you're returning values that might not exist. 
    models.Site.getSiteUIDFromURL(request.host.toLowerCase()) 
    } 

    maybeSite.flatMap { site => 
    super.onRouteRequest(request).map { 
     case e: EssentialAction => EssentialAction { req => 
     e(req).map(_.withSession("site" -> site)) 
     } 
     case other => other 
    } 
    } 
} 

Проверьте исходный код для CSRFFilter увидеть примеры того, как добавить вещи на сессии в фильтре.

+0

Это замечательно, спасибо. Я попробую. До сих пор я просто закрывал свои контроллеры, используя композицию действий, которая устанавливает значение сеанса. Фильтры кажутся очень мощными - я просто хочу, чтобы на нем было больше документации. Еще раз спасибо. –