Predicates and Exchange attributes are an Undertow component which allow you to manipulate your HTTP request and even make complex decisions on it, without hardcoding this into an Undertow Handler.
You can configure Predicates and Exchange attributes through a set of expression filters. The expressions you can use can also be combined with boolean operators which make them quite powerful. Let’s see some examples:
The most basic example expression we will learn is the RequestDumping which allows you to dump your HTTP request. To configure a RequestDumping handler as an expression filter, you need at first create a new expression filter. The following CLI command will do it:
/subsystem=undertow/configuration=filter/expression-filter=requestDump:add(expression="dump-request")
Next, you can enable the expression Filter in the Undertow Web Server:
/subsystem=undertow/server=default-server/host=default-host/filter-ref=requestDump:add
The result of it, will be a trace of the Request/Response in your server logs:
HTTP Request --------------------------------------------- URI=/api/v1/pods characterEncoding=null contentLength=-1 contentType=null header=Accept-Encoding=gzip header=User-Agent=kube-scheduler/v1.0.6 (linux/amd64) kubernetes/388061f header=Host=127.0.0.1:8080 locale=[] method=GET parameter=fieldSelector=spec.nodeName!= protocol=HTTP/1.1 queryString=fieldSelector=spec.nodeName%21%3D remoteAddr=localhost/127.0.0.1:45674 remoteHost=localhost scheme=http host=127.0.0.1:8080 serverPort=8080 HTTP Response --------------------------------------------- contentLength=74 contentType=text/html header=Connection=keep-alive header=X-Powered-By=Undertow/1 header=Server=WildFly/10 header=Content-Length=74 header=Content-Type=text/html header=Date=Sat, 01 Oct 2016 07:05:43 GMT
Quite powerful, however most of the times you would be interested to apply a filter at application level. This will limit the scope of the handler to only that specific application. In order to do that, you just need to add your filters into a file WEB-INF/undertow-handlers.conf.
To configure the RequestDumping handler in WEB-INF/undertow-handlers.conf to log all requests and corresponding responses for this application, add the following expression to WEB-INF/undertow-handlers.conf:
Let’s try it: start from a default Undertow configuration and create a simple Web application which contains into the file WEB-INF/undertow-handlers.conf the following content:
dump-request
When you try to access your application, you will see that you have achieved the same result in the server logs.
Advanced filters
The list of available filter expression is well described in the Undertow docs at: http://undertow.io/undertow-docs/undertow-docs-1.3.0/predicates-attributes-handlers.html
Let’s see another example: how to set an attribute in your HTTP Header:
header(header=a, value='x')
The above will set the value “x” in the header field named “a”.
Another example: how to perform an URL rewrite to another location: from page1.jsp to page2.jsp
path(/page1.jsp) -> rewrite(/page2.jsp)
Use the reverse proxy to send all requests to /context1 to a different backend server:
path-prefix('/context1') -> reverse-proxy({'http://backupserver.com'})
How to define an ACL so that requests to 127.0.0.1 are allowed whilst requests to 192.168.10.1 are denied:
ip-access-control[default-allow=true, acl={'127.0.0.1 allow', '192.168.10.1 deny'}]
To make more powerful your filters, predicates can be combined using the boolean operators ‘and’, ‘or’ and not. For example:
not method(GET)
Even in a more complex way:
method(POST) and path-prefix("/path1")
You can as well check path templates against an expression:
path-template(value="/user/{username}/*") and equals(%u, ${username})
And even Regular expression to verify the Request
regex(pattern="/user/(.*?)./.*", value=%U, full-match=true) and equals(%u, ${1})