Skip to content

Commit

Permalink
Add GAE services to route validation closures' scope.
Browse files Browse the repository at this point in the history
Conflicts:
	core/src/main/groovyx/gaelyk/routes/Route.groovy
  • Loading branch information
erdi authored and glaforge committed Nov 25, 2012
1 parent 00659c4 commit e73a767
Show file tree
Hide file tree
Showing 5 changed files with 70 additions and 8 deletions.
11 changes: 8 additions & 3 deletions core/src/main/groovyx/gaelyk/routes/Route.groovy
Expand Up @@ -18,6 +18,7 @@ package groovyx.gaelyk.routes
import java.util.regex.Matcher
import java.util.regex.Pattern
import javax.servlet.http.HttpServletRequest
import groovyx.gaelyk.GaelykBindingEnhancer

/**
* Representation of a route URL mapping.
Expand Down Expand Up @@ -148,10 +149,14 @@ class Route {
def clonedValidator = this.validator.clone()

// adds the request to the variables available for validation
def variablesAndRequest = variableMap.clone()
variablesAndRequest.request = request
def binding = new Binding()
GaelykBindingEnhancer.bind(binding)
def validatorDelegate = binding.variables

clonedValidator.delegate = variablesAndRequest
validatorDelegate += variableMap.clone()
validatorDelegate.request = request

clonedValidator.delegate = validatorDelegate
clonedValidator.resolveStrategy = Closure.DELEGATE_ONLY

boolean validated = false
Expand Down
35 changes: 33 additions & 2 deletions core/src/test/groovyx/gaelyk/routes/RoutesFilterTest.groovy
Expand Up @@ -22,7 +22,7 @@ import javax.servlet.ServletRequest
import javax.servlet.ServletResponse

/**
*
*
* @author Guillaume Laforge
*/
class RoutesFilterTest extends GroovyTestCase {
Expand Down Expand Up @@ -193,7 +193,7 @@ class RoutesFilterTest extends GroovyTestCase {
] as RequestDispatcher

def attributes = [:]

def request = [
getRequestURI: { -> "/somewhere" },
getQueryString: { -> "" },
Expand All @@ -216,4 +216,35 @@ class RoutesFilterTest extends GroovyTestCase {
assert attributes[RoutesFilter.ORIGINAL_URI] == "/somewhere"
}

void testValidatedRoute() {
def forwarded = false
def dispatched = ""

def dispatcher = [
forward: { ServletRequest req, ServletResponse resp -> forwarded = true }
] as RequestDispatcher

def attributes = [:]

def request = [
getRequestURI: {-> "/validate" },
getQueryString: {-> "" },
getMethod: {-> "GET" },
getRequestDispatcher: { String s -> dispatched = s; return dispatcher },
setAttribute: { String name, val -> attributes[name] = val },
getAttribute: { String name -> attributes[name] },
getServletPath: {-> '' },
getPathInfo: {-> '/validate' }
] as HttpServletRequest

def response = [:] as HttpServletResponse

def chain = [:] as FilterChain

filter.doFilter(request, response, chain)

assert forwarded
assert dispatched == "/validate.gtpl"
assert attributes[RoutesFilter.ORIGINAL_URI] == "/validate"
}
}
16 changes: 15 additions & 1 deletion core/src/test/groovyx/gaelyk/routes/RoutesTest.groovy
Expand Up @@ -16,6 +16,8 @@
package groovyx.gaelyk.routes

import static groovyx.gaelyk.TestUtil.request as r
import com.google.appengine.tools.development.testing.LocalServiceTestHelper
import com.google.appengine.tools.development.testing.LocalUserServiceTestConfig

/**
* Tests for the routing support.
Expand All @@ -24,7 +26,19 @@ import static groovyx.gaelyk.TestUtil.request as r
*/
class RoutesTest extends GroovyTestCase {

/** Tests the variable extraction logic */
LocalServiceTestHelper helper = new LocalServiceTestHelper(new LocalUserServiceTestConfig())

protected void setUp() {
super.setUp()
helper.setUp()
}

protected void tearDown() {
super.tearDown()
helper.tearDown()
}

/** Tests the variable extraction logic */
void testRoutesParameterExtraction() {
def inputOutputExpected = [
"/": [],
Expand Down
4 changes: 3 additions & 1 deletion core/src/test/groovyx/gaelyk/routes/routes.sample
Expand Up @@ -4,4 +4,6 @@ all "/ignore", ignore: true

get "/redirect", redirect: "/elsewhere.gtpl"

get "/@cust/home", forward: "/customer.groovy?cust=@cust", namespace: { cust }
get "/@cust/home", forward: "/customer.groovy?cust=@cust", namespace: { cust }

get "/validate", forward: "/validate.gtpl", validate: { users in com.google.appengine.api.users.UserService }
12 changes: 11 additions & 1 deletion website/war/WEB-INF/pages/tutorial/flexibleUrlRouting.gtpl
Expand Up @@ -316,7 +316,7 @@ but you can use boolean logic that you want, like <code>year.isNumber()</code>,
</blockquote>
<p>
In addition to the path variables, you also have access to the <code>request</code> from within the validation closure.
In addition to the path variables, you also have access to the <code>request</code> as well as all GAE services from within the validation closure.
For example, if you wanted to check that a particular attribute is present in the request,
like checking a user is registered to access a message board, you could do:
</p>
Expand All @@ -327,6 +327,16 @@ like checking a user is registered to access a message board, you could do:
validate: { request.registered == true }
</pre>
<p>
Another example would be to verify if the current user is an admin before allowing the route to kick in. The GAE services are available under the same variable names as in groovlets.
</p>
<pre class="brush:groovy">
get "/only-admin",
forward: "/secured.groovy",
validate: { users.isUserAdmin() }
</pre>
<a name="capability-routing"></a>
<h2>Capability-aware routing</h2>
Expand Down

0 comments on commit e73a767

Please sign in to comment.