Redirect filter

Gretty version 1.1.7+ implements new feature: redirect filter, driven by groovy DSL.
You can configure and use the redirect filter within any web-application,
even if you deploy web-application as a WAR file to arbitrary servlet container (without Gretty).

you can (but you don’t have to) add dependency compile 'org.akhikhl.gretty:gretty-filter:$grettyVersion' to your project -
this library implements redirect filter. Even if you don’t add it explicitly, Gretty will do it for you automatically,
as soon as it discovers redirect filter in "web.xml".

Configuration DSL

Redirect filter supports the following groovy-based DSL for "filter.groovy":

/**
* Adds new filter to filter chain.
* Must be called in the top scope of "filter.groovy" script.
* options - contains one or more filter criteria.
* closure - represents filter handler, which is invoked only when all criteria are fulfilled.
*/
void filter(Map options, Closure closure)
/**
* Redirects current HTTP request to the specified destination.
* Must be called only within closure of filter function.
* destination - can be URI, URIBuilder or String.
*/
void redirect(destination)
/**
* Forwards current HTTP request to the specified destination.
* Must be called only within closure of filter function.
* destination - can be URI, URIBuilder or String.
*/
void forward(destination)

"options" represents filter criteria, that are implicitly combined with AND operator.
For example, if you put the following into options:

filter relPath: '/path', scheme: 'http', {
// ...
}

then program will check for relative path being equal to '/path' AND for scheme being equal to 'http'.
Only when both comparisons are successful, then the closure will be called.

"options" supports two types of values: strings and regular expressions.
Strings are compared as they are, while regular expressions are matched via =~ operator.
The result of match is passed as map parameter to the closure. Example:

filter relPath: ~'/path/(*.)', query: ~'x=(.*)', { matches ->
// if we get here, then matches.relPath[0][1] will contain first capture group for relPath regex,
// while matches.query[0][1] will contain first capture group for query regex.
}