[undertow-dev] Rewrites and predicates

Stuart Douglas sdouglas at redhat.com
Mon Jul 8 18:20:10 EDT 2013


Hi everyone,

I recently added support for rewrites and redirects, and I would like some feedback on the syntax / implementation. It is actually quite a general mechanism that can be used for lots of things. There are actually a few parts to it that I will explain below.

Exchange attributes

Exchange attributes provide a general way of referencing some information from the exchange. Some examples:

%U or %{REQUEST_URL} - The request URL
%m or %{METHOD} - The request method
%{o,Content-Type} - The outgoing (response) content type header
%{i,Content-Type} - The incoming (request) header

These are intended to be re-usable in any place that requires dynamic specification of attributes (e.g. in the access log you can use exchange attributes to specify the log format). They are also extensible, you can add additional attributes via a service loader approach. 

Predicates

Predicates provide a simple way of making a true/false decision  based on an exchange. Many handlers have a requirement that they be applied conditionally, and predicates provide a general way to specify a condition. Predicates can be created programatically (they are just java classes that implement the Predicate interface), however there is also a simple language for specifying a predicate. I will give some examples below:

regex['/resources/*.\.css'] - regular expression match of the relative URL

regex[pattern='text/.*', value='%{i,Content-Type}, full-match=true] - Matches requests with a text/.* content type

equals[{'%{i,Content-Type}', 'text/xml'}] - Matches if the content type header is text/xml

contains[search='MSIE', value='%{i,User-Agent}'] and path-suffix['.js'] - User agent contains MSIE and request URL ends with .js

regex['/resources/(*.)\.css'] and equals[{'$1', 'myCssFile'}] - regex match, with a reference to match group 1 later in the expression

These predicates are also extensible, and they use the exchange attributes mentioned above meaning that they can be used to reference any part of the exchange. These should give users enough flexibility to match requests based on any criteria they can think up. 

Handler builders

We also support a way of specifying handlers, using similar language to predicates. Some examples:

rewrite['/myfile.html'] - performs a rewrite

set['%{o,Content-Type}', 'text/xhtml'] - sets a header (this can be used to set any exchange attribute)

redirect[/myfile.html] - performs a redirect

Now that we have all the pieces the actual config goes in a file called undertow-handlers.conf. Its basic syntax is predicate -> handler. An example file could look like below:

regex['(.*).css'] -> rewrite['${1}.xcss']
path-template['/foo/{bar}'] -> set[attribute='%{q,SomeHeader}', value='${bar}']

basically the rules are matched in order, and if it matches the handler on the right is executed. The handler on the right can also use context information from the match, such as regex match groups or path template segments. 

I think this should be sufficient in order to enable arbitrarily complex configs. The use of attributes and predicates should also mean that this config is consistent across everything we provide, even in other areas (e.g. the access log handler uses exchange attributes, so the basic syntax is the same).

Does anyone have any thoughts on this config?

Stuart





   


More information about the undertow-dev mailing list