加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 综合聚焦 > 服务器 > 安全 > 正文

scala – 如何在PlayFramework中从截取的请求将变量传递给Action

发布时间:2020-12-16 18:48:15 所属栏目:安全 来源:网络整理
导读:我通过覆盖GlobalSettings的onRouteRequest方法来拦截对我的播放应用程序的所有请求.现在,我需要从这里向调度的动作发送一些数据,这样我就不会在所有动作中执行所有这些计算.如何设置我传递给超级onRouteRequest方法的请求(play.api.mvc.RequestHeader)对象
我通过覆盖GlobalSettings的onRouteRequest方法来拦截对我的播放应用程序的所有请求.现在,我需要从这里向调度的动作发送一些数据,这样我就不会在所有动作中执行所有这些计算.如何设置我传递给超级onRouteRequest方法的请求(play.api.mvc.RequestHeader)对象的属性?

解决方法

根据您的需要,我不会使用onRouteRequest工作(至少优雅).

但是,让我们尝试使用专用结构来拦截.

以下是拦截请求,计算一些通用内容并将其传递给Action的方法

首先,这里是一个Interceptor对象,它有一个方法拦截和一个方便的方法用户名:

object Interceptor {

  def intercept[A,B](f: RequestHeader => Option[B],e: RequestHeader => Result)(action: B => Action[A]): Action[(Action[A],A)] = {

    val bodyParser = BodyParser {
      request =>
        f(request) map {
          b =>
            val innerAction = action(b)
            innerAction.parser(request).mapDone {
              body => body.right.map(innerBody => (innerAction,innerBody))
            }
        } getOrElse {
          Done(Left(e(request)),Input.Empty)
        }
    }

    Action(bodyParser) {
      request =>
        val (innerAction,innerBody) = request.body
        innerAction(request.map(_ => innerBody))
    }
  }

  def username[A](check: RequestHeader => Option[String]): ((String) => Action[A]) => Action[(Action[A],A)] = intercept(check,r => Results.Unauthorized("not logged in"))

}

如您所见,worker函数拦截使您有机会根据请求内容计算某些内容. B类型的哪个计算结果可能会失败(选项),在这种情况下,处理程序会告诉您该怎么做.

定义了要计算的内容之后,您可以使用一个带有B并给出Action [A]的函数来定义您的动作.

username方法只是一个简单的预定义拦截器,它可以让我们定义如何检索登录的用户名,只是为了说明.

现在,我们可以在Controller中使用它们

//index is defined for both GET and POST in routes,but fails on POST
  //  thanks to the interceptor that checks at first the used method
  //  the case mustn't be handled in the Action definition
  def index = Interceptor.intercept(
    /*check the method*/
    request => if (request.method == "GET") Some(request.method) else None,/*not a GET => bad request*/
    request => BadRequest(request.method + " not allowed")

  ) { /*the computation result*/method => Action {
      Ok("The method : " + method)
    }
  }

  //this controller retrieve the username in the session and renders it in a OK response
  def secured = Interceptor.username(r => r.session.get("username")) { username => Action {
      Ok("You're logged in as " + username)
    }
  }

  //this enables you to logged in => store in session
  def login(u:String) = Action { request => {
      Ok("Logged in as " + u) withSession(("username" -> u))
    }
  }

现在,如果你有一个通用计算,你可以创建你的预配置拦截器(这里我使用一个案例类,但只是定义一个部分应用拦截器的函数就足够了)

case class Intercept[B] (f: RequestHeader => Option[B],e: RequestHeader => Result) {

    def apply[A](action: B => Action[A]) = Interceptor.intercept[A,B](f,e)(action)

  }


  val getInterceptor = Intercept[String](
    request => if (request.method == "GET") Some(request.method) else None,request => BadRequest(request.method + " not allowed")
  )


  def index2 = getInterceptor { method => Action {
      Ok("Da method : " + method)
    }
  }

与评论相关的编辑:

根据你的评论,这里是你如何使用拦截器(注意我已经模拟了主机检索和检查)

使用hosted和anotherHosted,您将能够测试此工作流程:

> / hosted / false?host = myhost => 404,因为最初myhost没有被缓存,我向被检查的模型提供了false
> / hosted / true?host = myhost =>不在缓存中但它会添加它,然后没有404
> / hosted / anotherHosted / false?host = myhost =>在缓存中,因为它是托管=>没有404
> / hosted / anotherHosted / false?host = notMyhost => 404

这是代码

def getHost(request:RequestHeader) = request.queryString.get("host").get.head
def checkHost(host:String,b: Boolean) = b

val checkHosted = (b: Boolean) => Intercept[String](
  request => {
    val host = getHost(request)
    Cache.getAs[String](host) match {
      case x@Some(_) => x
      case None => if (checkHost(host,b)) {
        Cache.set(host,host)
        Some(host)
      } else None
    }

  },request => NotFound(getHost(request) + "not hosted")
)

def hosted(b:String) = checkHosted(b.toBoolean) {
  host => Action {
    Ok("this host is ok : " + host)
  }
}
def anotherHosted(b:String) = checkHosted(b.toBoolean) {
  host => Action {
    Ok("this host is ok : " + host)
  }
}

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读