Server Compliance Modes

The Jetty server strives to keep up with the latest IETF RFCs for compliance with internet specifications, which are periodically updated.

When possible, Jetty will support backwards compatibility by providing compliance modes that can be configured to allow violations of the current specifications that may have been allowed in obsoleted specifications.

There are compliance modes provided for:

Compliance modes can be configured to allow violations from the RFC requirements, or in some cases to allow additional behaviors that Jetty has implemented in excess of the RFC (for example, to allow ambiguous URIs).

For example, the HTTP RFCs require that request HTTP methods are case sensitive, however Jetty can allow case-insensitive HTTP methods by including the HttpCompliance.Violation.CASE_INSENSITIVE_METHOD in the HttpCompliance set of allowed violations.

HTTP Compliance Modes

In 1995, when Jetty was first implemented, there were no RFC specification of HTTP, only a W3C specification for HTTP/0.9, which has since been obsoleted or augmented by:

In addition to these evolving requirements, some earlier version of Jetty did not completely or strictly implement the RFC at the time (for example, case-insensitive HTTP methods). Therefore, upgrading to a newer Jetty version may cause runtime behavior differences that may break your applications.

The HttpCompliance.Violation enumeration defines the RFC requirements that may be optionally enforced by Jetty, to support legacy deployments. These possible violations are grouped into modes by the HttpCompliance class, which also defines several named modes that support common deployed sets of violations (with the default being HttpCompliance.RFC7230).

For example:

HttpConfiguration httpConfiguration = new HttpConfiguration();
httpConfiguration.setHttpCompliance(HttpCompliance.RFC7230);

If you want to customize the violations that you want to allow, you can create your own mode using the HttpCompliance.from(String) method:

HttpConfiguration httpConfiguration = new HttpConfiguration();

// RFC7230 compliance, but allow Violation.MULTIPLE_CONTENT_LENGTHS.
HttpCompliance customHttpCompliance = HttpCompliance.from("RFC7230,MULTIPLE_CONTENT_LENGTHS");

httpConfiguration.setHttpCompliance(customHttpCompliance);

URI Compliance Modes

Universal Resource Locators (URLs) where initially formalized in 1994 in RFC 1738 and then refined in 1995 with relative URLs by RFC 1808.

In 1998, URLs were generalized to Universal Resource Identifiers (URIs) by RFC 2396, which also introduced features such a path parameters.

This was then obsoleted in 2005 by RFC 3986 which removed the definition for path parameters.

Unfortunately by this stage the existence and use of such parameters had already been codified in the Servlet specification. For example, the relative URI /foo/bar;JSESSIONID=a8b38cd02b1c would define the path parameter JSESSIONID for the path segment bar, but the most recent RFC does not specify a formal definition of what this relative URI actually means.

The current situation is that there may be URIs that are entirely valid for RFC 3986, but are ambiguous when handled by the Servlet APIs:

  • A URI with .. and path parameters such as /some/..;/path is not resolved by RFC 3986, since the resolution process only applies to the exact segment .., not to ..;. However, once the path parameters are removed by the Servlet APIs, the resulting /some/../path can easily be resolved to /path, rather than be treated as a path that has ..; as a segment.

  • A URI such as /some/%2e%2e/path is not resolved by RFC 3986, yet when URL-decoded by the Servlet APIs will result in /some/../path which can easily be resolved to /path, rather than be treated as a path that has .. as a segment.

  • A URI with empty segments like /some//../path may be correctly resolved to /some/path (the .. removes the previous empty segment) by the Servlet APIs. However, if the URI raw path is passed to some other APIs (for example, file system APIs) it can be interpreted as /path because the empty segment // is discarded and treated as /, and the .. thus removes the /some segment.

In order to avoid ambiguous URIs, Jetty imposes additional URI requirements in excess of what is required by RFC 3986 compliance.

These additional requirements may optionally be violated and are defined by the UriCompliance.Violation enumeration.

These violations are then grouped into modes by the UriCompliance class, which also defines several named modes that support common deployed sets of violations, with the default being UriCompliance.DEFAULT.

For example:

HttpConfiguration httpConfiguration = new HttpConfiguration();
httpConfiguration.setUriCompliance(UriCompliance.RFC3986);

If you want to customize the violations that you want to allow, you can create your own mode using the UriCompliance.from(String) method:

HttpConfiguration httpConfiguration = new HttpConfiguration();

// RFC3986 compliance, but enforce Violation.AMBIGUOUS_PATH_SEPARATOR.
UriCompliance customUriCompliance = UriCompliance.from("RFC3986,-AMBIGUOUS_PATH_SEPARATOR");

httpConfiguration.setUriCompliance(customUriCompliance);

Servlet URI Compliance Modes

Even if the server has been configured (as above) to allow ambiguous URIs to be received, individual Servlet contexts may not allow such ambiguous URIs to be returned via some specific methods.

Specifically the HttpServletRequest methods: getServletPath() and getPathInfo(), may throw IllegalArgumentException for such URIs.

The intention is for safer methods, such as getRequestURI to be used instead.

If necessary, the ServletHandler can be configured to allow ambiguous URIs from all methods with setDecodeAmbiguousURIs(boolean).

The standards for Cookies have varied greatly over time from a non-specified but de-facto standard (implemented by the first browsers), through RFC 2965 and currently to RFC 6265.

The CookieCompliance.Violation enumeration defines the RFC requirements that may be optionally enforced by Jetty when parsing the Cookie HTTP header in requests and when generating the Set-Cookie HTTP header in responses.

These violations are then grouped into modes by the CookieCompliance class, which also defines several named modes that support common deployed sets of violations, with the default being CookieCompliance.RFC6265.

For example:

HttpConfiguration httpConfiguration = new HttpConfiguration();
httpConfiguration.setRequestCookieCompliance(CookieCompliance.RFC6265);
httpConfiguration.setResponseCookieCompliance(CookieCompliance.RFC6265);

If you want to customize the violations that you want to allow, you can create your own mode using the CookieCompliance.from(String) method:

HttpConfiguration httpConfiguration = new HttpConfiguration();

// RFC6265 compliance, but enforce Violation.RESERVED_NAMES_NOT_DOLLAR_PREFIXED.
CookieCompliance customUriCompliance = CookieCompliance.from("RFC6265,-RESERVED_NAMES_NOT_DOLLAR_PREFIXED");
httpConfiguration.setRequestCookieCompliance(customUriCompliance);

httpConfiguration.setResponseCookieCompliance(CookieCompliance.RFC6265);