开发者

Scala: Generate a block that conditionally runs another block

开发者 https://www.devze.com 2023-03-19 09:11 出处:网络
In the Circumflex framework, you can map an URL to a block like this: get(\"/foo\") = { \"hello, world!\"

In the Circumflex framework, you can map an URL to a block like this:

get("/foo") = {
    "hello, world!"
}

which, when browsing to /foo, will show the given string as 开发者_如何转开发expected. Now, to write a complete web application, you almost always need some form of authentication and authorisation. I'm trying to write some kind of wrapper for the above construct, so I can write this:

get("/foo") = requireLogin {
    "hello, world!"
}

The requireLogin method would then check if the user is logged in, and if yes, execute the given block. If not, however, it should do a redirect to the login page.

Now I somehow can't get the syntax right (i'm still a Scala newbie). How would you do this in a generic fashion?


Try something like this:

def executeMaybe[A](work: => A): Option[A] =
  if (util.Random.nextBoolean)
    Some(work)
  else
    None

This executes the passed code with probability 0.5, returning Some(<result delivered by work>), or returns None is the other cases. You can call it either like this:

val v = executeMaybe(42)

or with block notation:

val v = executeMaybe {
  // do some work
  // provide return value
}

The trick is to use a by-name parameter, signalled by the => symbol. Read more e.g. here: http://daily-scala.blogspot.com/2009/12/by-name-parameter-to-function.html


The way I asked it, Jean-Philippe's answer is correct. But here's some information specific to Circumflex:

In the Circumflex RequestRouter, the following can be used to implement the required method:

def requireLogin (f: => RouteResponse ): RouteResponse = {
    if(loggedIn) {
        return f
    }
    else {
        return sendRedirect("/login")
    }
}

The reason behind this was getting clear with the hint from Jean-Philippe's answer, and once I remembered that the following call isn't an assignment of a block to some internal data, but is mapped to another method call instead.

So, the call

get("/") = {...}

is actually mapped to this:

get.update("/", {...})

The block is passed in as a By-Name parameter, so the return value of requireLogin must be the same - which, for Circumflex, is RouteResponse, and not a function.


You also can use j2ee container authentication with <login-config> and <security-constraint> stuff inside web.xml

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号