Chapter 15. Configuring the Web Server (Undertow)
15.1. Undertow Subsystem Overview
In JBoss EAP 8.0, the undertow
subsystem takes the place of the web
subsystem from JBoss EAP 6.
The undertow
subsystem allows you to configure the web server and servlet container settings. It implements the Jakarta Servlet 4.0 Specification as well as websockets. It also supports HTTP upgrade and using high performance non-blocking handlers in servlet deployments. The undertow
subsystem also has the ability to act as a high performance reverse proxy which supports mod_cluster.
Within the undertow
subsystem, there are five main components to configure:
While JBoss EAP does offer the ability to update the configuration for each of these components, the default configuration is suitable for most use cases and provides reasonable performance settings.
Default Undertow Subsystem Configuration
<subsystem xmlns="{UndertowSubsystemNamespace}" default-server="default-server" default-virtual-host="default-host" default-servlet-container="default" default-security-domain="other"> <buffer-cache name="default"/> <server name="default-server"> <http-listener name="default" socket-binding="http" redirect-socket="https" enable-http2="true"/> <https-listener name="https" socket-binding="https" security-realm="ApplicationRealm" enable-http2="true"/> <host name="default-host" alias="localhost"> <location name="/" handler="welcome-content"/> <http-invoker security-realm="ApplicationRealm"/> </host> </server> <servlet-container name="default"> <jsp-config/> <websockets/> </servlet-container> <handlers> <file name="welcome-content" path="${jboss.home.dir}/welcome-content"/> </handlers> </subsystem>
The undertow
subsystem also relies on the io
subsystem to provide XNIO workers and buffer pools. The io
subsystem is configured separately and provides a default configuration which should give optimal performance in most cases.
Compared to the web
subsystem in JBoss EAP 6, the undertow
subsystem in JBoss EAP 7 has different default behaviors of HTTP methods.
Using Elytron with Undertow Subsystem
As a web application is deployed, the name of the security domain required by that application will be identified. This will either be from within the deployment or if the deployment does not have a security domain, the default-security-domain
as defined on the undertow
subsystem will be assumed. By default it is assumed that the security domain maps to a PicketBox
defined in the legacy security subsystem. However, an application-security-domain
resource can be added to the undertow
subsystem which maps from the name of the security domain required by the application to the appropriate Elytron configuration.
Example: Adding a Mapping.
/subsystem=undertow/application-security-domain=ApplicationDomain:add(security-domain=ApplicationDomain)
The addition of mapping is successful if the result is:
<subsystem xmlns="{UndertowSubsystemNamespace}" ... default-security-domain="other"> ... <application-security-domains> <application-security-domain name="ApplicationDomain" security-domain="ApplicationDomain"/> </application-security-domains> ... </subsystem>
- If the deployment was already deployed at this point, the application server should be reloaded for the application security domain mapping to take effect.
- In current web service-Elytron integration, the name of the security domain specified to secure a web service endpoint and the Elytron security domain name must be the same.
This simple form is suitable where a deployment is using the standard HTTP mechanism as defined within the Servlet specification like BASIC
, CLIENT_CERT
, DIGEST
, FORM
. Here, the authentication will be performed against the ApplicationDomain
security domain. This form is also suitable where an application is not using any authentication mechanism and instead is using programmatic authentication or is trying to obtain the SecurityDomain
associated with the deployment and use it directly.
Example: Advanced Form of the Mapping:
/subsystem=undertow/application-security-domain=MyAppSecurity:add(http-authentication-factory=application-http-authentication)
The advanced mapping is successful if the result is:
<subsystem xmlns="{UndertowSubsystemNamespace}" ... default-security-domain="other"> ... <application-security-domains> <application-security-domain name="MyAppSecurity" http-authentication-factory="application-http-authentication"/> </application-security-domains> ... </subsystem>
In this form of the configuration, instead of referencing a security domain, an http-authentication-factory
is referenced. This is the factory that will be used to obtain the instances of the authentication mechanisms and is in turn associated with the security domain.
You should reference an http-authentication-factory
attribute when using custom HTTP authentication mechanisms or where additional configuration must be defined for mechanisms such as principal transformers, credential factories, and mechanism realms. It is also better to reference an http-authentication-factory
attribute when using mechanisms other than the four described in the Servlet
specification.
When the advanced form of mapping is used, another configuration option is available, override-deployment-config
. The referenced http-authentication-factory
can return a complete set of authentication mechanisms. By default, these are filtered to just match the mechanisms requested by the application. If this option is set to true
, then the mechanisms offered by the factory will override the mechanisms requested by the application.
The application-security-domain
resource also has one additional option enable-jacc
. If this is set to true
, Java Authorization Contract for Containers will be enabled for any deployments matching this mapping.
Runtime Information
Where an application-security-domain
mapping is in use, it can be useful to double check that deployments did match against it as expected. If the resource is read with include-runtime=true
, the deployments that are associated with the mapping will also be shown as:
/subsystem=undertow/application-security-domain=MyAppSecurity:read-resource(include-runtime=true) { "outcome" => "success", "result" => { "enable-jacc" => false, "http-authentication-factory" => undefined, "override-deployment-config" => false, "referencing-deployments" => ["simple-webapp.war"], "security-domain" => "ApplicationDomain", "setting" => undefined } }
In this output, the referencing-deployments
attribute shows that the deployment simple-webapp.war
has been deployed using the mapping.
15.2. Configuring Buffer Caches
The buffer cache is used to cache static resources. JBoss EAP enables multiple caches to be configured and referenced by deployments, allowing different deployments to use different cache sizes. Buffers are allocated in regions and are a fixed size. The total amount of space used can be calculated by multiplying the buffer size by the number of buffers per region by the maximum number of regions. The default size of a buffer cache is 10MB.
JBoss EAP provides a single cache by default:
Default Undertow Subsystem Configuration
<subsystem xmlns="{UndertowSubsystemNamespace}" default-server="default-server" default-virtual-host="default-host" default-servlet-container="default" default-security-domain="other"> <buffer-cache name="default"/> ... </subsystem>
Updating an Existing Buffer Cache
To update an existing buffer cache:
/subsystem=undertow/buffer-cache=default/:write-attribute(name=buffer-size,value=2048)
reload
Creating a New Buffer Cache
To create a new buffer cache:
/subsystem=undertow/buffer-cache=new-buffer:add
Deleting a Buffer Cache
To delete a buffer cache:
/subsystem=undertow/buffer-cache=new-buffer:remove
reload
For a full list of the attributes available for configuring buffer caches, please see the Undertow Subsystem Attributes section.
15.3. Configuring Byte Buffer Pools
Undertow byte buffer pools are used to allocate pooled NIO ByteBuffer
instances. All listeners have a byte buffer pool and you can use different buffer pools and workers for each listener. Byte buffer pools can be shared between different server instances.
These buffers are used for IO operations, and the buffer size has a big impact on application performance. For most servers, the ideal size is usually 16k.
Updating an Existing Byte Buffer Pool
To update an existing byte buffer pool:
/subsystem=undertow/byte-buffer-pool=myByteBufferPool:write-attribute(name=buffer-size,value=1024)
reload
Creating a Byte Buffer Pool
To create a new byte buffer pool:
/subsystem=undertow/byte-buffer-pool=newByteBufferPool:add
Deleting a Byte Buffer Pool
To delete a byte buffer pool:
/subsystem=undertow/byte-buffer-pool=newByteBufferPool:remove
reload
For a full list of the attributes available for configuring byte buffer pools, see the Byte Buffer Pool Attributes reference.
15.4. Configuring a Server
A server represents an instance of Undertow and consists of several elements:
- host
- http-listener
- https-listener
- ajp-listener
The host element provides a virtual host configuration, while the three listeners provide connections of that type to the Undertow instance.
The default behavior of the server is to queue requests while the server is starting. You can change the default behavior using the queue-requests-on-start
attribute on the host. If this attribute is set to true
, which is the default, then requests that arrive when the server is starting will be held until the server is ready. If this attribute is set to false
, then requests that arrive before the server has completely started will be rejected with the default response code.
Regardless of the attribute value, request processing does not start until the server is completely started.
You can configure the queue-requests-on-start
attribute using the management console by navigating to Configuration
Multiple servers can be configured, allowing deployments and servers to be completely isolated. This can be useful in certain scenarios such as multi-tenant environments.
JBoss EAP provides a server by default:
Default Undertow Subsystem Configuration
<subsystem xmlns="{UndertowSubsystemNamespace}" default-server="default-server" default-virtual-host="default-host" default-servlet-container="default" default-security-domain="other"> <buffer-cache name="default"/> <server name="default-server"> <http-listener name="default" socket-binding="http" redirect-socket="https" enable-http2="true"/> <https-listener name="https" socket-binding="https" security-realm="ApplicationRealm" enable-http2="true"/> <host name="default-host" alias="localhost"> <location name="/" handler="welcome-content"/> <http-invoker security-realm="ApplicationRealm"/> </host> </server> ... </subsystem>
The following examples show how to configure a server using the management CLI. You can also configure a server using the management console by navigating to Configuration
Updating an Existing Server
To update an existing server:
/subsystem=undertow/server=default-server:write-attribute(name=default-host,value=default-host)
reload
Creating a New Server
To create a new server:
/subsystem=undertow/server=new-server:add
reload
Deleting a Server
To delete a server:
/subsystem=undertow/server=new-server:remove
reload
For a full list of the attributes available for configuring servers, see the Undertow Subsystem Attributes section.
15.4.1. Access Logging
You can configure access logging on each host you define.
Two access logging options are available: standard access logging and console access logging.
Note that the additional processing required for access logging can affect system performance.
15.4.1.1. Standard Access Logging
Standard access logging writes log entries to a log file.
By default, the log file is stored in the directory standalone/log/access_log.log.
To enable standard access logging, add the access-log setting to the host for which you want to capture access log data. The following CLI command illustrates the configuration on the default host in the default JBoss EAP server:
/subsystem=undertow/server=default-server/host=default-host/setting=access-log:add
You must reload the server after enabling standard access logging.
By default, the access log record includes the following data:
- Remote host name
- Remote logical user name (always -)
- Remote user that was authenticated
- The date and time of the request, in Common Log Format
- The first line of the request
- The HTTP status code of the response
- The number of bytes sent, excluding HTTP headers
This set of data is defined as the common pattern. Another pattern, combined, is also available. In addition to the data logged in the common pattern, the combined pattern includes the referer and user agent from the incoming header.
You can change the data logged using the pattern
attribute. The following CLI command illustrates updating the pattern
attribute to use the combined pattern:
/subsystem=undertow/server=default-server/host=default-host/setting=access-log:write-attribute(name=pattern,value="combined"
You must reload the server after updating the pattern attribute.
Pattern | Description |
---|---|
%a | Remote IP address |
%A | Local IP address |
%b |
Bytes sent, excluding HTTP headers or |
%B | Bytes sent, excluding HTTP headers |
%h | Remote host name |
%H | Request protocol |
%l |
Remote logical username from |
%m | Request method |
%p | Local port |
%q |
Query string (excluding the |
%r | First line of the request |
%s | HTTP status code of the response |
%t | Date and time, in Common Log Format format |
%u | Remote user that was authenticated |
%U | Requested URL path |
%v | Local server name |
%D | Time taken to process the request, in milliseconds |
%T | Time taken to process the request, in seconds |
%I | Current Request thread name (can compare later with stack traces) |
common |
|
combined |
|
You can also write information from the cookie, the incoming header and response header, or the session. The syntax is modeled after the Apache syntax:
-
%{i,xxx}
for incoming headers -
%{o,xxx}
for outgoing response headers -
%{c,xxx}
for a specific cookie -
%{r,xxx}
wherexxx
is an attribute in theServletRequest
-
%{s,xxx}
wherexxx
is an attribute in theHttpSession
Additional configuration options are available for this log. For more information see "access-log Attributes" in the appendix.
15.4.1.2. Console Access Logging
Console access logging writes data to stdout as structured as JSON data.
Each access log record is a single line of data. You can capture this data for processing by log aggregation systems.
To configure console access logging, add the console-access-log setting to the host for which you want to capture access log data. The following CLI command illustrates the configuration on the default host in the default JBoss EAP server:
/subsystem=undertow/server=default-server/host=default-host/setting=console-access-log:add
By default, the console access log record includes the following data:
Log data field name | Description |
---|---|
eventSource | The source of the event in the request |
hostName | The JBoss EAP host that processed the request |
bytesSent | The number of bytes the JBoss EAP server sent in response to the request |
dateTime | The date and time that the request was processed by the JBoss EAP server |
remoteHost | The IP address of the machine where the request originated |
remoteUser | The user name associated with the remote request |
requestLine | The request submitted |
responseCode | The HTTP response code returned by the JBoss EAP server |
Default properties are always included in the log output. You can use the attributes
attribute to change the labels of the default log data, and in some cases to change the data configuration. You can also use the attributes
attribute to add additional log data to the output.
Log data field name | Description | Format |
---|---|---|
authentication-type | The authentication type used to authenticate the user associated with the request. Default label: authenticationType Use the key option to change the label for this property. | authentication-type{} authentication-type={key="authType"} |
bytes-sent | The number of bytes returned for the request, excluding HTTP headers. Default label: bytesSent Use the key option to change the label for this property. | bytes-sent={} bytes-sent={key="sent-bytes"} |
date-time | The date and time that the request was received and processed. Default label: dateTime Use the key option to change the label for this property. Use the date-format to define the pattern used to format the date-time record. The pattern must be a Java SimpleDateFormatter pattern. Use the time-zone option to specify the time zone used to format the date and/or time data if the date-format option is defined. This value must be a valid java.util.TimeZone. | date-time={key="<keyname>", date-format="<date-time format>"} date-time={key="@timestamp", date-format="yyyy-MM-dd’T’HH:mm:ssSSS"} |
host-and-port | The host and port queried by the request. Default label: hostAndPort Use the key option to change the label for this property. | host-and-port{} host-and-port={key="port-host"} |
local-ip | The IP address of the local connection. Use the key option to change the label for this property. Default label: localIp Use the key option to change the label for this property. | local-ip{} local-ip{key=”localIP”} |
local-port | The port of the local connection. Default label: localPort Use the key option to change the label for this property. | local-port{} local-port{key=”LocalPort”} |
local-server-name | The name of the local server that processed the request. Default label: localServerName Use the key option to change the label for this property. | local-server-name {} local-server-name {key=LocalServerName} |
path-parameter | One or more path or URI parameters included in the request. The names property is a comma-separated list of names used to resolve the exchange values. Use the key-prefix property to make the keys unique. If the key-prefix is specified, the prefix is prepended to the name of each path parameter in the output. | path-parameter{names={store,section}} path-parameter{names={store,section}, key-prefix=”my-”} |
predicate | The name of the predicate context. The names property is a comma-separated list of names used to resolve the exchange values. Use the key-prefix property to make the keys unique. If the key-prefix is specified, the prefix is prepended to the name of each path parameter in the output. | predicate{names={store,section}} predicate{names={store,section}, key-prefix=”my-”} |
query-parameter | One or query parameters included in the request. The names property is a comma-separated list of names used to resolve the exchange values. Use the key-prefix property to make the keys unique. If the key-prefix is specified, the prefix is prepended to the name of each path parameter in the output. | query-parameter{names={store,section}} query-parameter{names={store,section}, key-prefix=”my-”} |
query-string | The query string of the request. Default label: queryString Use the key option to change the label for this property. Use the include-question-mark property to specify whether the query string should include the question mark. By default, the question mark is not included. | query-string{} query-string{key=”QueryString”, include-question-mark=”true”} |
relative-path | The relative path of the request. Default label: relativePath Use the key option to change the label for this property. | relative-path{} relative-path{key=”RelativePath”} |
remote-host | The remote host name. Default label: remoteHost Use the key option to change the label for this property. | remote-host{} remote-host{key=”RemoteHost”} |
remote-ip | The remote IP address. Default label: remoteIp Use the key options to change the label for this property. Use the obfuscated property to obfuscate the IP address in the output log record. The default value is false. | remote-ip{} remote-ip{key=”RemoteIP”, obfuscated=”true”} |
remote-user | Remote user that was authenticated. Default label: remoteUser Use the key options to change the label for this property. | remote-user{} remote-user{key=”RemoteUser”} |
request-header | The name of a request header. The key for the structured data is the name of the header; the value is the value of the named header. The names property is a comma-separated list of names used to resolve the exchange values. Use the key-prefix property to make the keys unique. If the key-prefix is specified, the prefix is prepended to the name of the request headers in the log output. | request-header{names={store,section}} request-header{names={store,section}, key-prefix=”my-”} |
request-line | The request line. Default label: requestLine Use the key option to change the label for this property. | request-line{} request-line{key=”Request-Line”} |
request-method | The request method. Default label: requestMethod Use the key option to change the label for this property. | request-method{} request-method{key=”RequestMethod”} |
request-path | The relative path for the request. Default label: requestPath Use the key option to change the label for this property. | request-path{} request-path{key=”RequestPath”} |
request-protocol | The protocol for the request. Default label: requestProtocol Use the key option to change the label for this property. | request-protocol{} request-protocol{key=”RequestProtocol”} |
request-scheme | The URI scheme of the request. Default label: requestScheme Use the key option to change the label for this property. | request-scheme{} request-scheme{key=”RequestScheme”} |
request-url | The original request URI. Includes host name, protocol, and so forth, if specified by the client. Default label: requestUrl Use the key option to change the label for this property. | request-url{} request-url{key=”RequestURL”} |
resolved-path | The resolved path. Default Label: resolvedPath Use the key option to change the label for this property. | resolved-path{} resolved-path{key=”ResolvedPath”} |
response-code | The response code. Default label: responseCode Use the key option to change the label for this property. | response-code{} response-code{key=”ResponseCode”} |
response-header | The name of a response header. The key for the structured data is the name of the header; the value is the value of the named header. The names property is a comma-separated list of names used to resolve the exchange values. Use the key-prefix property to make the keys unique. If the key-prefix is specified, the prefix is prepended to the name of the request headers in the log output. | response-header{names={store,section}} response-header{names={store,section}, key-prefix=”my-”} |
response-reason-phrase | The text reason for the response code. Default label: responseReasonPhrase Use the key option to change the label for this property. | response-reason-phrase{} response-reason-phrase{key=”ResponseReasonPhrase”} |
response-time | The time used to process the request. Default label: responseTime Use the key option to change the label for this property. The default time unit is MILLISECONDS. Available time units include: * NANOSECONDS * MICROSECONDS * MILLISECONDS * SECONDS | response-time{} response-time{key=”ResponseTime”, time-unit=SECONDS} |
secure-exchange | Indicates whether the exchange was secure. Default label: secureExchange Use the key option to change the label for this property. | secure-exchange{} secure-exchange{key=”SecureExchange”} |
ssl-cipher | The SSL cipher for the request. Default label: sslCipher Use the key option to change the label for this property. | ssl-cipher{} ssl-cipher{key=”SSLCipher”} |
ssl-client-cert | The SSL client certificate for the request. Default label: sslClientCert Use the key option to change the label for this property. | ssl-client-cert{} ssl-client-cert{key=”SSLClientCert”} |
ssl-session-id | The SSL session id of the request. Default label: sslSessionId Use the key option to change the label for this property. | ssl-session-id{} stored-response |
The stored response to the request. Default label: storedResponse Use the key option to change the label for this property. | stored-response{} stored-response{key=”StoredResponse”} | thread-name |
The thread name of the current thread. Default label: threadName Use the key option to change the label for this property. | thread-name{} thread-name{key=”ThreadName”} | transport-protocol |
You can use the metadata
attribute to configure additional arbitrary data to include in the access log record. The value of the metadata
attribute is a set of key:value pairs that defines the data to include in the access log record. The value in a pair can be a management model expression. Management model expressions are resolved when the server is started or reloaded. Key-value pairs are comma-separated.
The following CLI command demonstrates an example of a complex console log configuration, including additional log data, customization of log data, and additional metadata:
/subsystem=undertow/server=default-server/host=default-host/setting=console-access-log:add(metadata={"@version"="1", "qualifiedHostName"=${jboss.qualified.host.name:unknown}}, attributes={bytes-sent={}, date-time={key="@timestamp", date-format="yyyy-MM-dd'T'HH:mm:ssSSS"}, remote-host={}, request-line={}, response-header={key-prefix="responseHeader", names=["Content-Type"]}, response-code={}, remote-user={}})
The resulting access log record would resemble the following additional JSON data (Note: the example output below is formatted for readability; in an actual record, all data would be output as a single line):
{ "eventSource":"web-access", "hostName":"default-host", "@version":"1", "qualifiedHostName":"localhost.localdomain", "bytesSent":1504, "@timestamp":"2019-05-02T11:57:37123", "remoteHost":"127.0.0.1", "remoteUser":null, "requestLine":"GET / HTTP/2.0", "responseCode":200, "responseHeaderContent-Type":"text/html" }
The following command illustrates updates to the log data after activating the console access log:
/subsystem=undertow/server=default-server/host=default-host/setting=console-access-log:write-attribute(name=attributes,value={bytes-sent={}, date-time={key="@timestamp", date-format="yyyy-MM-dd'T'HH:mm:ssSSS"}, remote-host={}, request-line={}, response-header={key-prefix="responseHeader", names=["Content-Type"]}, response-code={}, remote-user={}})
The following command illustrates updates to the custom metadata after activating the console access log:
/subsystem=undertow/server=default-server/host=default-host/setting=console-access-log:write-attribute(name=metadata,value={"@version"="1", "qualifiedHostName"=${jboss.qualified.host.name:unknown}})
15.5. Configuring a Servlet Container
A servlet container provides all servlet, Jakarta Server Pages and websocket-related configuration, including session-related configuration. While most servers will only need a single servlet container, it is possible to configure multiple servlet containers by adding an additional servlet-container
element. Having multiple servlet containers enables behavior such as allowing multiple deployments to be deployed to the same context path on different virtual hosts.
Much of the configuration provided in by servlet container can be individually overridden by deployed applications using their web.xml
file.
JBoss EAP provides a servlet container by default:
Default Undertow Subsystem Configuration
<subsystem xmlns="{UndertowSubsystemNamespace}"> <buffer-cache name="default"/> <server name="default-server"> ... </server> <servlet-container name="default"> <jsp-config/> <websockets/> </servlet-container> ... </subsystem>
The following examples show how to configure a servlet container using the management CLI. You can also configure a servlet container using the management console by navigating to Configuration
Updating an Existing Servlet Container
To update an existing servlet container:
/subsystem=undertow/servlet-container=default:write-attribute(name=ignore-flush,value=true)
reload
Creating a New Servlet Container
To create a new servlet container:
/subsystem=undertow/servlet-container=new-servlet-container:add
reload
Deleting a Servlet Container
To delete a servlet container:
/subsystem=undertow/servlet-container=new-servlet-container:remove
reload
For a full list of the attributes available for configuring servlet containers, see the Undertow Subsystem Attributes section.
15.6. Configuring a Servlet Extension
Servlet extensions allow you to hook into the servlet deployment process and modify aspects of a servlet deployment. This can be useful in cases where you need to add additional authentication mechanisms to a deployment or use native Undertow handlers as part of a servlet deployment.
To create a custom servlet extension, it is necessary to implement the io.undertow.servlet.ServletExtension
interface and then add the name of your implementation class to the META-INF/services/io.undertow.servlet.ServletExtension
file in the deployment. You also need to include the compiled class file of the ServletExtension
implementation. When Undertow deploys the servlet, it loads all the services from the deployments
class loader and then invokes their handleDeployment
methods.
An Undertow DeploymentInfo
structure, which contains a complete and mutable description of the deployment, is passed to this method. You can modify this structure to change any aspect of the deployment.
The DeploymentInfo
structure is the same structure that is used by the embedded API, so in effect a ServletExtension
has the same amount of flexibility that you have when using Undertow in embedded mode.
15.7. Configuring Handlers
JBoss EAP allows for two types of handlers to be configured:
- file handlers
- reverse-proxy handlers
File handlers serve static files. Each file handler must be attached to a location in a virtual host. Reverse-proxy handlers allow JBoss EAP to serve as a high performance reverse-proxy.
JBoss EAP provides a file handler by default:
Default Undertow Subsystem Configuration
<subsystem xmlns="{UndertowSubsystemNamespace}" default-server="default-server" default-virtual-host="default-host" default-servlet-container="default" default-security-domain="other"> <buffer-cache name="default"/> <server name="default-server"> ... </server> <servlet-container name="default"> ... </servlet-container> <handlers> <file name="welcome-content" path="${jboss.home.dir}/welcome-content"/> </handlers> </subsystem>
Using WebDAV for Static Resources
Previous versions of JBoss EAP allowed for using WebDAV with the web
subsystem, by way of the WebdavServlet
, to host static resources and enable additional HTTP methods for accessing and manipulating those files. In JBoss EAP 8.0, the undertow
subsystem does provide a mechanism for serving static files using a file handler, but the undertow
subsystem does not support WebDAV. If you want to use WebDAV with JBoss EAP 8.0, you can write a custom WebDAV servlet.
Updating an Existing File Handler
To update an existing file handler:
/subsystem=undertow/configuration=handler/file=welcome-content:write-attribute(name=case-sensitive,value=true)
reload
Creating a New File Handler
To create a new file handler:
/subsystem=undertow/configuration=handler/file=new-file-handler:add(path="${jboss.home.dir}/welcome-content")
If you set a file handler’s path
directly to a file instead of a directory, any location
elements that reference that file handler must not end with a forward slash (/
). Otherwise, the server will return a 404 - Not Found
response.
Deleting a File Handler
To delete a file handler
/subsystem=undertow/configuration=handler/file=new-file-handler:remove
reload
For a full list of the attributes available for configuring handlers, see the Undertow Subsystem Attributes section.
15.8. Configuring Filters
A filter enables some aspect of a request to be modified and can use predicates to control when a filter executes. Some common use cases for filters include setting headers or doing GZIP compression.
A filter is functionally equivalent to a global valve used in JBoss EAP 6.
The following types of filters can be defined:
- custom-filter
- error-page
- expression-filter
- gzip
- mod-cluster
- request-limit
- response-header
- rewrite
The following examples show how to configure a filter using the management CLI. You can also configure a filter using the management console by navigating to Configuration
Updating an Existing Filter
To update an existing filter:
/subsystem=undertow/configuration=filter/response-header=myHeader:write-attribute(name=header-value,value="JBoss-EAP")
reload
Creating a New Filter
To create a new filter:
/subsystem=undertow/configuration=filter/response-header=new-response-header:add(header-name=new-response-header,header-value="My Value")
Deleting a Filter
To delete a filter:
/subsystem=undertow/configuration=filter/response-header=new-response-header:remove
reload
For a full list of the attributes available for configuring filters, see the Undertow Subsystem Attributes section.
15.8.1. Configuring the buffer-request Handler
A request from the client or the browser consists of two parts: the header and the body. In a typical situation, the header and the body are sent to JBoss EAP without any delays in between. However, if the header is sent first and then after few seconds, the body is sent, there is a delay sending the complete request. This scenario creates a thread in JBoss EAP to show as waiting
to execute the complete request.
The delay caused in sending the header and the body of the request can be corrected using the buffer-request
handler. The buffer-request
handler attempts to consume the request from a non-blocking IO thread before allocating it to a worker thread. When no buffer-request
handler is added, the thread allocation to the worker thread happens directly. However, when the buffer-request
handler is added, the handler attempts to read the amount of data that it can buffer in a non-blocking manner using the IO thread before allocating it to the worker thread.
You can use the following management CLI commands to configure the buffer-request
handler:
/subsystem=undertow/configuration=filter/expression-filter=buf:add(expression="buffer-request(buffers=1)") /subsystem=undertow/server=default-server/host=default-host/filter-ref=buf:add
There is a limit to the size of the buffer requests that can be processed. This limit is determined by a combination of the buffer size and the total number of buffers, as shown in the equation below.
Total_size = num_buffers × buffer_size
In the equation above:
-
Total_size
is the size of data that will be buffered before the request is dispatched to a worker thread. -
num_buffers
is the number of buffers. The number of buffers is set by thebuffers
parameter on the handler. -
buffer_size
is the size of each buffer. The buffer size is set in theio
subsystem, and is 16KB by default per request.
Avoid configuring very large buffer requests, or else you might run out of memory.
15.8.2. Configuring the SameSite
attribute
Use the SameSite
attribute to define the accessibility of a cookie, whether the cookie is accessible within the same site. This attribute prevents the cross-site forgery attacks because browsers do not send the cookie with cross-site requests.
You can configure the SameSite
attribute for cookies with SameSiteCookieHandler
in the undertow
subsystem. With this configuration, you do not need to change your application code.
The following table includes the detail of SameSiteCookieHandler
parameters:
Parameter Name | Presence | Description |
---|---|---|
| Optional |
This parameter adds a |
| Optional |
This parameter indicates if the |
| Optional |
This parameter accepts a regex pattern for the cookie name. If this parameter is not specified, the attribute |
| Optional |
This parameter verifies if client applications are incompatible with the
If you use this default value and set the
To prevent issues with incompatible clients, this parameter skips setting the |
| Mandatory |
This parameter specifies the
To improve security against cross-site request forgery attacks, some browsers set the default |
SameSiteCookieHandler
adds the attribute SameSite=<specified-mode>
to the cookies that match cookie-pattern
or to all cookies when cookie-pattern
is not specified. The attribute SameSite=<specified-mode>
includes a user-replaced variable, that is, <specified-mode>
. The cookie-pattern
is matched according to the value set in case-sensitive
.
Before configuring the SameSite
attribute for any browser, consider the following points:
-
Review the application to identify whether the cookies require the
SameSite
attribute, and those cookies need to be secured. -
Setting the
SameSite
attribute mode toNone
for all cookies makes the application more susceptible to attacks.
Procedure to configure SameSiteCookieHandler by using expression-filter
For configuring SameSiteCookieHandler
on the server by using expression-filter
, perform the following steps:
Create a new
expression-filter
with theSameSiteCookieHandler
by using the following command:/subsystem=undertow/configuration=filter/expression-filter=addSameSiteLax:add(expression="path-prefix('/mypathprefix') -> samesite-cookie(Lax)")
Enable the
expression-filter
in theundertow
web server by using the following command:/subsystem=undertow/server=default-server/host=default-host/filter-ref=addSameSiteLax:add
Procedure to configure SameSiteCookieHandler by adding a configuration file
For configuring SameSiteCookieHandler
in your application by adding the undertow-handlers.conf
file, perform the following steps:
-
Add an
undertow-handlers.conf
file to your WAR’s WEB-INF directory. In the
undertow-handlers.conf
file, add the following command with a specificSameSiteCookieHandler
parameter:samesite-cookie(mode=<mode>)
The valid values for the
mode
parameter areStrict
,Lax
orNone
. Using the above command, you can also configure otherSameSiteCookieHandler
parameters, such ascookie-pattern
,case-sensitive
,enable-client-checker
, oradd-secure-for-none
.
15.9. Configure the Default Welcome Web Application
JBoss EAP includes a default Welcome
application, which displays at the root context on port 8080
by default.
There is a default server preconfigured in Undertow that serves up the welcome content.
Default Undertow Subsystem Configuration
<subsystem xmlns="{UndertowSubsystemNamespace}" default-server="default-server" default-virtual-host="default-host" default-servlet-container="default" default-security-domain="other"> ... <server name="default-server"> <http-listener name="default" socket-binding="http" redirect-socket="https" enable-http2="true"/> <https-listener name="https" socket-binding="https" security-realm="ApplicationRealm" enable-http2="true"/> <host name="default-host" alias="localhost"> <location name="/" handler="welcome-content"/> <http-invoker security-realm="ApplicationRealm"/> </host> </server> ... <handlers> <file name="welcome-content" path="${jboss.home.dir}/welcome-content"/> </handlers> </subsystem>
The default server, default-server
, has a default host, default-host
, configured. The default host is configured to handle requests to the server’s root, using the <location>
element, with the welcome-content
file handler. The welcome-content
handler serves up the content in the location specified in the path
property.
This default Welcome
application can be replaced with your own web application. This can be configured in one of two ways:
You can also disable the welcome content.
Change the welcome-content File Handler
Modify the existing
welcome-content
file handler’s path to point to the new deployment./subsystem=undertow/configuration=handler/file=welcome-content:write-attribute(name=path,value="/path/to/content")
NoteAlternatively, you could create a different file handler to be used by the server’s root.
/subsystem=undertow/configuration=handler/file=NEW_FILE_HANDLER:add(path="/path/to/content") /subsystem=undertow/server=default-server/host=default-host/location=\/:write-attribute(name=handler,value=NEW_FILE_HANDLER)
Reload the server for the changes to take effect.
reload
Change the default-web-module
Map a deployed web application to the server’s root.
/subsystem=undertow/server=default-server/host=default-host:write-attribute(name=default-web-module,value=hello.war)
Reload the server for the changes to take effect.
reload
Disable the Default Welcome Web Application
Disable the welcome application by removing the
location
entry/
for thedefault-host
./subsystem=undertow/server=default-server/host=default-host/location=\/:remove
Reload the server for the changes to take effect.
reload
15.10. Configuring HTTPS
For information on configuring HTTPS for web applications, see Configure One-way and Two-way SSL/TLS for Applications in How to Configure Server Security.
For information on configuring HTTPS for use with the JBoss EAP management interfaces, see How to Secure the Management Interfaces in How to Configure Server Security.
15.11. Configuring HTTP Session Timeout
The HTTP session timeout defines the period of inactive time needed to declare an HTTP session invalid. For example, a user accesses an application deployed to JBoss EAP which creates an HTTP session. If that user then attempts to access that application again after the HTTP session timeout, the original HTTP session will be invalidated and the user will be forced to create a new HTTP session. This may result in the loss of unpersisted data or the user having to reauthenticate.
The HTTP session timeout is configured in an application’s web.xml
file, but a default HTTP session timeout can be specified within JBoss EAP. The server’s timeout value will apply to all deployed applications, but an application’s web.xml
will override the server’s value.
The server value is specified in the default-session-timeout
property which is found in the servlet-container
section of the undertow
subsystem. The value of default-session-timeout
is specified in minutes and the default is 30
.
Configuring the Default Session Timeout
To configure the default-session-timeout
:
/subsystem=undertow/servlet-container=default:write-attribute(name=default-session-timeout, value=60)
reload
15.12. Configuring HTTP-Only Session Management Cookies
Session management cookies can be accessed by both HTTP APIs and non-HTTP APIs such as JavaScript. JBoss EAP offers the ability to send the HttpOnly
header as part of the Set-Cookie
response header to the client, usually a browser. In supported browsers, enabling this header tells the browser that it should prevent accessing session management cookies through non-HTTP APIs. Restricting session management cookies to only HTTP APIs can help to mitigate the threat of session cookie theft via cross-site scripting attacks. To enable this behavior, the http-only
attribute should be set to true
.
Using the HttpOnly
header does not actually prevent cross-site scripting attacks by itself, it merely notifies the browser. The browser must also support HttpOnly
for this behavior to take affect.
Using the http-only
attribute only applies the restriction to session management cookies and not other browser cookies.
The http-only
attribute is set in two places in the undertow
subsystem:
- In the servlet container as a session cookie setting
- In the host section of the server as a single sign-on property
Configuring host-only
for the Servlet Container Session Cookie
To configure the host-only
property for the servlet container session cookie:
/subsystem=undertow/servlet-container=default/setting=session-cookie:add
/subsystem=undertow/servlet-container=default/setting=session-cookie:write-attribute(name=http-only,value=true)
reload
Configuring host-only
for the Host Single Sign-On
To configure the host-only
property for the host single sign-on:
/subsystem=undertow/server=default-server/host=default-host/setting=single-sign-on:add
/subsystem=undertow/server=default-server/host=default-host/setting=single-sign-on:write-attribute(name=http-only,value=true)
reload
15.13. Configuring HTTP/2
Undertow allows for the use of the HTTP/2 standard, which reduces latency by compressing headers and multiplexing many streams over the same TCP connection. It also provides the ability for a server to push resources to the client before it has requested them, leading to faster page loads.
Be aware that HTTP/2 only works with clients and browsers that also support the HTTP/2 standard.
Most modern browsers enforce HTTP/2 over a secured TLS connection, known as h2
and may not support HTTP/2 over plain HTTP, known as h2c
. It is still possible to configure JBoss EAP to use HTTP/2 with h2c
, in other words, without using HTTPS and only using plain HTTP with HTTP upgrade. In that case, you can simply enable HTTP/2 in the HTTP listener Undertow:
/subsystem=undertow/server=default-server/http-listener=default:write-attribute(name=enable-http2,value=true)
To configure Undertow to use HTTP/2, enable the HTTPS listener in Undertow to use HTTP/2 by setting the enable-http2
attribute to true
:
/subsystem=undertow/server=default-server/https-listener=https:write-attribute(name=enable-http2,value=true)
For more information on the HTTPS listener and configuring Undertow to use HTTPS for web applications, see Configure One-way and Two-way SSL/TLS for Applications in How to Configure Server Security.
In order to utilize HTTP/2 with the elytron
subsystem, you will need to ensure that the configured ssl-context
in the https-listener
of the Undertow is configured as modifiable. This can be achieved by setting the wrap
attribute of the appropriate server-ssl-context
to false
. By default, the wrap
attribute is set to false
. This is required by Undertow to make modifications in the ssl-context
about the ALPN. If the provided ssl-context
is not writable, ALPN cannot be used and the connection falls back to HTTP/1.1.
ALPN support when using HTTP/2
When using HTTP/2 over a secured TLS connection, a TLS stack that supports ALPN TLS protocol extension is required. Obtaining this stack varies based on the installed JDK.
- When using Java 8, the ALPN implementation is introduced directly into JBoss EAP with dependencies on Java internals. Therefore, this ALPN implementation only works with Oracle and OpenJDK. It does not work with IBM Java. Red Hat strongly recommends that you utilize ALPN TLS protocol extension support from the OpenSSL provider in JBoss EAP, with OpenSSL libraries that implement ALPN capability. Using the ALPN TLS protocol extension support from the OpenSSL provider should result in better performance.
- As of Java 9, the JDK supports ALPN natively; however, using the ALPN TLS protocol extension support from the OpenSSL provider should also result in better performance when using Java 9 or later.
Instructions for installing OpenSSL, to obtain the ALPN TLS protocol extension support, are available in Install OpenSSL from JBoss Core Services. The standard system OpenSSL is supported on Red Hat Enterprise Linux 8 and no additional JBoss Core Services OpenSSL is required.
Once OpenSSL has been installed, follow the instructions in Configure JBoss EAP to Use OpenSSL.
Verify HTTP/2 is Being Used
To verify that Undertow is using HTTP/2, you will need to inspect the headers coming from Undertow. Navigate to your JBoss EAP instance using https, for example https://localhost:8443, and use your browser’s developer tools to inspect the headers. Some browsers, for example Google Chrome, will show HTTP/2 pseudo headers, such as :path
, :authority
, :method
and :scheme
, when using HTTP/2. Other browsers, for example Firefox and Safari, will report the status or version of the header as HTTP/2.0
.
15.14. Configuring a RequestDumping Handler
The RequestDumping
handler, io.undertow.server.handlers.RequestDumpingHandler
, logs the details of a request and corresponding response objects handled by Undertow within JBoss EAP.
While this handler can be useful for debugging, it may also log sensitive information. Please keep this in mind when enabling this handler.
The RequestDumping
handler replaces the RequestDumperValve
from JBoss EAP 6.
You can configure a RequestDumping
handler at either at the server level directly in JBoss EAP or within an individual application.
15.14.1. Configuring a RequestDumping Handler on the Server
A RequestDumping
handler should be configured as an expression filter. To configure a RequestDumping
handler as an expression filter, you need to do the following:
Create a new Expression Filter with the RequestDumping
Handler
/subsystem=undertow/configuration=filter/expression-filter=requestDumperExpression:add(expression="dump-request")
Enable the Expression Filter in the Undertow Web Server
/subsystem=undertow/server=default-server/host=default-host/filter-ref=requestDumperExpression:add
All requests and corresponding responses handled by the Undertow web server will be logged when enabling the RequestDumping
handler as a expression filter in this manner.
Configuring a RequestDumping Handler for Specific URLs
In addition to logging all requests, you can also use an expression filter to only log requests and corresponding responses for specific URLs. This can be accomplished using a predicate in your expression such as path
, path-prefix
, or path-suffix
. For example, if you want to log all requests and corresponding responses to /myApplication/test
, you can use the expression "path(/myApplication/test) -> dump-request"
instead of the expression "dump-request"
when creating your expression filter. This will only direct requests with a path exactly matching /myApplication/test
to the RequestDumping
handler.
15.14.2. Configuring a RequestDumping Handler within an Application
In addition to configuring a RequestDumping
handler at the server, you can also configure it within individual applications. This will limit the scope of the handler to only that specific application. A RequestDumping
handler should be configured in 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
:
Example: WEB-INF/undertow-handlers.conf
dump-request
To configure the RequestDumping
handler in WEB-INF/undertow-handlers.conf
to only log requests and corresponding responses to specific URLs within this application, you can use a predicate in your expression such as path
, path-prefix
, or path-suffix
. For example, to log all requests and corresponding responses to test
in your application, the following expression with the path
predicate could be used:
Example: WEB-INF/undertow-handlers.conf
path(/test) -> dump-request
When using the predicates such as path
, path-prefix
, or path-suffix
in expressions defined in the application’s WEB-INF/undertow-handlers.conf
, the value used will be relative to the context root of the application. For example, if the application’s context root is myApplication
with an expression path(/test) -> dump-request
configured in WEB-INF/undertow-handlers.conf
, it will only log requests and corresponding responses to /myApplication/test
.
15.15. Configuring Cookie Security
You can use the secure-cookie
handler to enhance the security of cookies that are created over a connection between a server and a client. In this case, if the connection over which the cookie is set is marked as secure, the cookie will have its secure
attribute set to true
.
You can secure the connection by configuring a listener or by using HTTPS. You configure the secure-cookie
handler by defining an expression-filter
in the undertow
subsystem. For more information, see Configuring Filters.
When the secure-cookie
handler is in use, cookies that are set over a secure connection will be implicitly set as secure and will never be sent over an unsecure connection.
15.16. Tuning the Undertow Subsystem
For tips on optimizing performance for the undertow
subsystem, see the Undertow Subsystem Tuning section of the Performance tuning for JBoss EAP.