From 4673846635e3c3d85c2c327a4e80e1bb3d172745 Mon Sep 17 00:00:00 2001 From: Greg Wilkins Date: Thu, 24 Jun 2021 15:20:05 +1000 Subject: [PATCH] Compliance modes documentation (#6312) Added doco on compliance modes Signed-off-by: Greg Wilkins Co-authored-by: Simone Bordet --- .../main/asciidoc/operations-guide/index.adoc | 1 + .../modules/module-server.adoc | 97 +++++++++++++++++- .../compliance/server-compliance-cookie.adoc | 35 +++++++ .../compliance/server-compliance-http.adoc | 42 ++++++++ .../compliance/server-compliance-uri.adoc | 52 ++++++++++ .../server/compliance/server-compliance.adoc | 33 +++++++ .../programming-guide/server/server.adoc | 2 + .../docs/programming/server/ServerDocs.java | 67 +++++++++++++ .../jetty/http/ComplianceViolation.java | 39 ++++++++ .../eclipse/jetty/http/CookieCompliance.java | 88 ++++++++++++++++- .../eclipse/jetty/http/HttpCompliance.java | 98 +++++++++++++++++-- .../org/eclipse/jetty/http/UriCompliance.java | 33 ++++--- jetty-server/src/main/config/etc/jetty.xml | 4 +- .../src/main/config/modules/server.mod | 34 ++++--- .../org/eclipse/jetty/server/RequestTest.java | 2 + 15 files changed, 587 insertions(+), 40 deletions(-) create mode 100644 documentation/jetty-documentation/src/main/asciidoc/programming-guide/server/compliance/server-compliance-cookie.adoc create mode 100644 documentation/jetty-documentation/src/main/asciidoc/programming-guide/server/compliance/server-compliance-http.adoc create mode 100644 documentation/jetty-documentation/src/main/asciidoc/programming-guide/server/compliance/server-compliance-uri.adoc create mode 100644 documentation/jetty-documentation/src/main/asciidoc/programming-guide/server/compliance/server-compliance.adoc diff --git a/documentation/jetty-documentation/src/main/asciidoc/operations-guide/index.adoc b/documentation/jetty-documentation/src/main/asciidoc/operations-guide/index.adoc index aaf01516489..a2fe11697af 100644 --- a/documentation/jetty-documentation/src/main/asciidoc/operations-guide/index.adoc +++ b/documentation/jetty-documentation/src/main/asciidoc/operations-guide/index.adoc @@ -27,6 +27,7 @@ include::start/chapter.adoc[] include::modules/chapter.adoc[] include::deploy/chapter.adoc[] include::protocols/chapter.adoc[] +include::compliance/server-compliance.adoc[] include::keystore/chapter.adoc[] include::sessions/chapter.adoc[] include::quickstart/chapter.adoc[] diff --git a/documentation/jetty-documentation/src/main/asciidoc/operations-guide/modules/module-server.adoc b/documentation/jetty-documentation/src/main/asciidoc/operations-guide/modules/module-server.adoc index 16992683a4f..f0ec2850aeb 100644 --- a/documentation/jetty-documentation/src/main/asciidoc/operations-guide/modules/module-server.adoc +++ b/documentation/jetty-documentation/src/main/asciidoc/operations-guide/modules/module-server.adoc @@ -18,15 +18,50 @@ The `server` module provides generic server support, and configures generic HTTP The `server` module depends on the xref:og-module-threadpool[`threadpool` module], the xref:og-module-bytebufferpool[`bytebufferpool` module] and the xref:og-module-logging[`logging` module]. -The module file is `$JETTY_HOME/modules/server.mod`: +[NOTE] +==== +The `server` module configures the shared parameters for generic HTTP handline, but does not enable any specific network protocol. You have to explicitly enable the protocols you want to support by enabling, for example, the xref:og-module-http[`http` module] for clear-text HTTP/1.1 support, or the xref:og-module-http2[`http2` module] for secure HTTP/2 support, etc. + +See also the xref:og-protocols[protocols section] for more information about the supported protocols. +==== + +[[og-module-server-http-config]] +====== HTTP Configuration Properties + +The module properties to configure generic HTTP properties are listed below. Mostly they frequently apply to both HTTP/1 and HTTP/2, but some parameters are version specific: ---- -include::{JETTY_HOME}/modules/server.mod[] +include::{JETTY_HOME}/modules/server.mod[tags=documentation-http-config] ---- Among the configurable properties, the most relevant are: -// TODO: consider extracting the httpConfig and scheduler properties into separate files. +`jetty.httpConfig.headerCacheSize`:: +The header cache is used when parsing HTTP/1 to more efficiently handle fields that are repeated in every request on a connection. If the server does not receive persistent connection or infrequent repeated fields, then there may be a performance gain in reducing the cache size. If large fields are frequently repeated, then a large cache may be beneficial. + +`jetty.httpConfig.delayDispatchUntilContent`:: +It is not uncommon for the network packets containing a request header to arrive before packets that contain the data of any request body. In such cases it may be beneficial for overall performance to delay dispatching the request to be handled until the first data packet arrives, as this may avoid blocking the handling thread. However, if minimum latency for receiving the request without content is important, then this parameter can be set to false. + +`jetty.httpConfig.sendServerVersion`:: +Whether you want to send the `Server` header in every HTTP response: ++ +[source,screen,subs=normal] +---- +HTTP/1.1 200 OK +Content-Length: 0 +Server: Jetty({version}) +---- + +[[og-module-server-config]] +====== Server Configuration Properties + +The module properties to configure the Jetty server are: + +---- +include::{JETTY_HOME}/modules/server.mod[tags=documentation-server-config] +---- + +Among the configurable properties, the most relevant are: `jetty.server.dumpAfterStart`:: Whether to perform a `Server.dump()` operation after the `Server` has started. @@ -40,3 +75,59 @@ See also the xref:og-troubleshooting-dump[Jetty Server Dump] section for more in `jetty.server.stopAtShutdown`:: Whether to call `Server.stop()` through a JVM shutdown hook when the JVM exits. + +[[og-module-server-compliance]] +====== Server Compliance Properties + +The Jetty server strives to keep up with the latest link:https://en.wikipedia.org/wiki/Request_for_Comments[IETF RFC]s 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. +The module properties to configure the Jetty server compliance are: + +---- +include::{JETTY_HOME}/modules/server.mod[tags=documentation-server-compliance] +---- + +Among the configurable properties, the most relevant are: + +`jetty.httpConfig.compliance`:: +Configures the compliance to HTTP specifications. +The value could be: + +* One of the predefined link:{JDURL}/org/eclipse/jetty/http/HttpCompliance.html[`HttpCompliance`] constants, such as `RFC7230` or `RFC2616`. +For example: `jetty.httpConfig.compliance=RFC2616`. +* A comma-separated list of violations to allow or forbid, as specified by the link:{JDURL}/org/eclipse/jetty/http/HttpCompliance.html#from(java.lang.String)[`HttpCompliance.from(String)`] method. +For example, `jetty.httpConfig.compliance=RFC7230,MULTIPLE_CONTENT_LENGTHS` means that the HTTP compliance is that defined by `RFC7230`, but also allows the `HttpCompliance.Violation.MULTIPLE_CONTENT_LENGTHS`, so that requests that have multiple `Content-Length` headers are accepted (they would be rejected when using just `HttpCompliance.RFC7230`). ++ +For more information about `HttpCompliance` see also xref:pg-server-compliance-http[this section]. + +`jetty.httpConfig.uriCompliance`:: +Configures the compliance to URI specifications. +The value could be: + +* One of the predefined link:{JDURL}/org/eclipse/jetty/http/UriCompliance.html[`UriCompliance`] constants, such as `DEFAULT` or `RFC3986`. +For example: `jetty.httpConfig.compliance=RFC3986`. +* A comma-separated list of violations to allow or forbid, as specified by the link:{JDURL}/org/eclipse/jetty/http/UriCompliance.html#from(java.lang.String)[`UriCompliance.from(String)`] method. +For example, `jetty.httpConfig.uriCompliance=RFC3986,-AMBIGUOUS_PATH_SEPARATOR` means that the URI compliance is that defined by `RFC3986`, but also does not allow the `UriCompliance.Violation.AMBIGUOUS_PATH_SEPARATOR`, so that requests that have URIs such as `/foo/bar%2Fbaz` (where `%2F` is the URL-encoded `/` character) are rejected (they would be accepted when using just `UriCompliance.RFC3986`). ++ +For more information about `UriCompliance` see also xref:pg-server-compliance-uri[this section]. + +`jetty.httpConfig.requestCookieCompliance`:: +`jetty.httpConfig.responseCookieCompliance`:: +Configures the compliance to HTTP cookie specifications. +The value could be: + +* One of the predefined link:{JDURL}/org/eclipse/jetty/http/CookieCompliance.html[`CookieCompliance`] constants, such as `RFC6265`. +For example: `jetty.httpConfig.compliance=RFC6265`. +* A comma-separated list of violations to allow or forbid, as specified by the link:{JDURL}/org/eclipse/jetty/http/CookieCompliance.html#from(java.lang.String)[`CookieCompliance.from(String)`] method. +For example, `jetty.httpConfig.requestCookieCompliance=RFC6265,-RESERVED_NAMES_NOT_DOLLAR_PREFIXED` means that the cookie compliance is that defined by `RFC6265`, but also does not allow the `CookieCompliance.Violation.RESERVED_NAMES_NOT_DOLLAR_PREFIXED`, so that requests that have cookie headers such as `Cookie: $foo=bar` are rejected (they would be accepted when using just `CookieCompliance.RFC6265`). ++ +For more information about `CookieCompliance` see also xref:pg-server-compliance-cookie[this section]. + + +[[og-module-scheduler-config]] +====== Server Scheduler Configuration Properties + +The module properties to configure the Jetty server scheduler are: + +---- +include::{JETTY_HOME}/modules/server.mod[tags=documentation-scheduler-config] +---- diff --git a/documentation/jetty-documentation/src/main/asciidoc/programming-guide/server/compliance/server-compliance-cookie.adoc b/documentation/jetty-documentation/src/main/asciidoc/programming-guide/server/compliance/server-compliance-cookie.adoc new file mode 100644 index 00000000000..0c48ed4b4f4 --- /dev/null +++ b/documentation/jetty-documentation/src/main/asciidoc/programming-guide/server/compliance/server-compliance-cookie.adoc @@ -0,0 +1,35 @@ +// +// ======================================================================== +// Copyright (c) 1995-2021 Mort Bay Consulting Pty Ltd and others. +// +// This program and the accompanying materials are made available under the +// terms of the Eclipse Public License v. 2.0 which is available at +// https://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0 +// which is available at https://www.apache.org/licenses/LICENSE-2.0. +// +// SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 +// ======================================================================== +// + +[[pg-server-compliance-cookie]] +==== Cookie Compliance Modes + +The standards for Cookies have varied greatly over time from a non-specified but de-facto standard (implemented by the first browsers), through link:https://tools.ietf.org/html/rfc2965[RFC 2965] and currently to link:https://tools.ietf.org/html/rfc6265[RFC 6265]. + +The link:{JDURL}/org/eclipse/jetty/http/CookieCompliance.Violation.html[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 link:{JDURL}/org/eclipse/jetty/http/CookieCompliance.html[`CookieCompliance`] class, which also defines several named modes that support common deployed sets of violations, with the default being link:{JDURL}/org/eclipse/jetty/http/CookieCompliance.html#RFC6265[`CookieCompliance.RFC6265`]. + +For example: + +[source,java,indent=0] +---- +include::../../{doc_code}/org/eclipse/jetty/docs/programming/server/ServerDocs.java[tags=cookieCompliance] +---- + +If you want to customize the violations that you want to allow, you can create your own mode using the link:{JDURL}/org/eclipse/jetty/http/CookieCompliance.html#from(java.lang.String)[`CookieCompliance.from(String)`] method: + +[source,java,indent=0] +---- +include::../../{doc_code}/org/eclipse/jetty/docs/programming/server/ServerDocs.java[tags=cookieComplianceCustom] +---- diff --git a/documentation/jetty-documentation/src/main/asciidoc/programming-guide/server/compliance/server-compliance-http.adoc b/documentation/jetty-documentation/src/main/asciidoc/programming-guide/server/compliance/server-compliance-http.adoc new file mode 100644 index 00000000000..993f438850c --- /dev/null +++ b/documentation/jetty-documentation/src/main/asciidoc/programming-guide/server/compliance/server-compliance-http.adoc @@ -0,0 +1,42 @@ +// +// ======================================================================== +// Copyright (c) 1995-2021 Mort Bay Consulting Pty Ltd and others. +// +// This program and the accompanying materials are made available under the +// terms of the Eclipse Public License v. 2.0 which is available at +// https://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0 +// which is available at https://www.apache.org/licenses/LICENSE-2.0. +// +// SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 +// ======================================================================== +// + +[[pg-server-compliance-http]] +==== HTTP Compliance Modes + +In 1995, when Jetty was first implemented, there were no RFC specification of HTTP, only a W3C specification for link:https://www.w3.org/Protocols/HTTP/AsImplemented.html[HTTP/0.9], which has since been obsoleted or augmented by: + + * link:https://datatracker.ietf.org/doc/html/rfc1945[RFC 1945] for HTTP/1.0 in 1996 + * link:https://datatracker.ietf.org/doc/html/rfc2068[RFC 2068] for HTTP/1.1 in 1997 + * link:https://datatracker.ietf.org/doc/html/rfc2616[RFC 2616] for HTTP/1.1 bis in 1999 + * link:https://datatracker.ietf.org/doc/html/rfc7230[RFC 7230], link:https://datatracker.ietf.org/doc/html/rfc7231[RFC 7231], link:https://datatracker.ietf.org/doc/html/rfc7232[RFC 7232], link:https://datatracker.ietf.org/doc/html/rfc7233[RFC 7233], link:https://datatracker.ietf.org/doc/html/rfc7234[RFC 7234], link:https://datatracker.ietf.org/doc/html/rfc7235[RFC 7235] again for HTTP/1.1 in 2014 + * link:https://datatracker.ietf.org/doc/html/rfc7540[RFC 7540] for HTTP/2.0 in 2015 + +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 link:{JDURL}/org/eclipse/jetty/http/HttpCompliance.Violation.html[`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 link:{JDURL}/org/eclipse/jetty/http/HttpCompliance.html[`HttpCompliance`] class, which also defines several named modes that support common deployed sets of violations (with the default being link:{JDURL}/org/eclipse/jetty/http/HttpCompliance.html#RFC7230[`HttpCompliance.RFC7230`]). + +For example: + +[source,java,indent=0] +---- +include::../../{doc_code}/org/eclipse/jetty/docs/programming/server/ServerDocs.java[tags=httpCompliance] +---- + +If you want to customize the violations that you want to allow, you can create your own mode using the link:{JDURL}/org/eclipse/jetty/http/HttpCompliance.html#from(java.lang.String)[`HttpCompliance.from(String)`] method: + +[source,java,indent=0] +---- +include::../../{doc_code}/org/eclipse/jetty/docs/programming/server/ServerDocs.java[tags=httpComplianceCustom] +---- diff --git a/documentation/jetty-documentation/src/main/asciidoc/programming-guide/server/compliance/server-compliance-uri.adoc b/documentation/jetty-documentation/src/main/asciidoc/programming-guide/server/compliance/server-compliance-uri.adoc new file mode 100644 index 00000000000..c4f03e641bf --- /dev/null +++ b/documentation/jetty-documentation/src/main/asciidoc/programming-guide/server/compliance/server-compliance-uri.adoc @@ -0,0 +1,52 @@ +// +// ======================================================================== +// Copyright (c) 1995-2021 Mort Bay Consulting Pty Ltd and others. +// +// This program and the accompanying materials are made available under the +// terms of the Eclipse Public License v. 2.0 which is available at +// https://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0 +// which is available at https://www.apache.org/licenses/LICENSE-2.0. +// +// SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 +// ======================================================================== +// + +[[pg-server-compliance-uri]] +==== URI Compliance Modes + +Universal Resource Locators (URLs) where initially formalized in 1994 in link:https://datatracker.ietf.org/doc/html/rfc1738[RFC 1738] and then refined in 1995 with relative URLs by link:https://datatracker.ietf.org/doc/html/rfc1808[RFC 1808]. + +In 1998, URLs were generalized to Universal Resource Identifiers (URIs) by link:https://datatracker.ietf.org/doc/html/rfc2396[RFC 2396], which also introduced features such a link:https://datatracker.ietf.org/doc/html/rfc2396#section-3.3[path parameter]s. + +This was then obsoleted in 2005 by link:https://datatracker.ietf.org/doc/html/rfc3986[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 link:https://datatracker.ietf.org/doc/html/rfc3986[RFC 3986], but are ambiguous when handled by the Servlet APIs: + +* A URI with `..` _and_ path parameters such as `/some/..;/path` is not link:https://datatracker.ietf.org/doc/html/rfc3986#section-5.2[_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 link:https://datatracker.ietf.org/doc/html/rfc3986[RFC 3986] compliance. + +These additional requirements may optionally be violated and are defined by the link:{JDURL}/org/eclipse/jetty/http/UriCompliance.Violation.html[`UriCompliance.Violation`] enumeration. + +These violations are then grouped into modes by the link:{JDURL}/org/eclipse/jetty/http/UriCompliance.html[`UriCompliance`] class, which also defines several named modes that support common deployed sets of violations, with the default being link:{JDURL}/org/eclipse/jetty/http/UriCompliance.html#DEFAULT[`UriCompliance.DEFAULT`]. + +For example: + +[source,java,indent=0] +---- +include::../../{doc_code}/org/eclipse/jetty/docs/programming/server/ServerDocs.java[tags=uriCompliance] +---- + +If you want to customize the violations that you want to allow, you can create your own mode using the link:{JDURL}/org/eclipse/jetty/http/UriCompliance.html#from(java.lang.String)[`UriCompliance.from(String)`] method: + +[source,java,indent=0] +---- +include::../../{doc_code}/org/eclipse/jetty/docs/programming/server/ServerDocs.java[tags=uriComplianceCustom] +---- diff --git a/documentation/jetty-documentation/src/main/asciidoc/programming-guide/server/compliance/server-compliance.adoc b/documentation/jetty-documentation/src/main/asciidoc/programming-guide/server/compliance/server-compliance.adoc new file mode 100644 index 00000000000..9d072330310 --- /dev/null +++ b/documentation/jetty-documentation/src/main/asciidoc/programming-guide/server/compliance/server-compliance.adoc @@ -0,0 +1,33 @@ +// +// ======================================================================== +// Copyright (c) 1995-2021 Mort Bay Consulting Pty Ltd and others. +// +// This program and the accompanying materials are made available under the +// terms of the Eclipse Public License v. 2.0 which is available at +// https://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0 +// which is available at https://www.apache.org/licenses/LICENSE-2.0. +// +// SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 +// ======================================================================== +// + +[[pg-server-compliance]] +=== Server Compliance Modes + +The Jetty server strives to keep up with the latest link:https://en.wikipedia.org/wiki/Request_for_Comments[IETF RFC]s 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: + +* xref:pg-server-compliance-http[HTTP Compliance] +* xref:pg-server-compliance-uri[URI Compliance] +* xref:pg-server-compliance-cookie[Cookie Compliance] + +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 xref:pg-server-compliance-uri[ambiguous URIs]). + +For example, the HTTP RFCs require that request HTTP methods are link:https://datatracker.ietf.org/doc/html/rfc7230#section-3.1.1[case sensitive], however Jetty can allow case-insensitive HTTP methods by including the link:{JDURL}/org/eclipse/jetty/http/HttpCompliance.Violation.html#CASE_INSENSITIVE_METHOD[`HttpCompliance.Violation.CASE_INSENSITIVE_METHOD`] in the link:{JDURL}/org/eclipse/jetty/http/HttpCompliance.html[`HttpCompliance`] set of allowed violations. + +include::server-compliance-http.adoc[] +include::server-compliance-uri.adoc[] +include::server-compliance-cookie.adoc[] diff --git a/documentation/jetty-documentation/src/main/asciidoc/programming-guide/server/server.adoc b/documentation/jetty-documentation/src/main/asciidoc/programming-guide/server/server.adoc index d4a3f592ba2..97e7697e067 100644 --- a/documentation/jetty-documentation/src/main/asciidoc/programming-guide/server/server.adoc +++ b/documentation/jetty-documentation/src/main/asciidoc/programming-guide/server/server.adoc @@ -26,7 +26,9 @@ The Jetty server-side libraries provide: * HTTP support for HTTP/1.0, HTTP/1.1, HTTP/2, clear-text or encrypted, for applications that want to embed Jetty as a generic HTTP server or proxy, via the xref:pg-server-http[HTTP libraries] * HTTP/2 low-level support, for applications that want to explicitly handle low-level HTTP/2 _sessions_, _streams_ and _frames_, via the xref:pg-server-http2[HTTP/2 libraries] * WebSocket support, for applications that want to embed a WebSocket server, via the xref:pg-server-websocket[WebSocket libraries] +* FCGI support, to delegate requests to python or similar scripting languages. +include::compliance/server-compliance.adoc[] include::http/server-http.adoc[] include::http2/server-http2.adoc[] include::sessions/sessions.adoc[] diff --git a/documentation/jetty-documentation/src/main/java/org/eclipse/jetty/docs/programming/server/ServerDocs.java b/documentation/jetty-documentation/src/main/java/org/eclipse/jetty/docs/programming/server/ServerDocs.java index 1a892e1e86d..5c063daf342 100644 --- a/documentation/jetty-documentation/src/main/java/org/eclipse/jetty/docs/programming/server/ServerDocs.java +++ b/documentation/jetty-documentation/src/main/java/org/eclipse/jetty/docs/programming/server/ServerDocs.java @@ -17,12 +17,16 @@ import java.nio.ByteBuffer; import java.util.Map; import java.util.concurrent.Executor; +import org.eclipse.jetty.http.CookieCompliance; +import org.eclipse.jetty.http.HttpCompliance; +import org.eclipse.jetty.http.UriCompliance; import org.eclipse.jetty.io.AbstractConnection; import org.eclipse.jetty.io.Connection; import org.eclipse.jetty.io.EndPoint; import org.eclipse.jetty.server.AbstractConnectionFactory; import org.eclipse.jetty.server.Connector; import org.eclipse.jetty.server.DetectorConnectionFactory; +import org.eclipse.jetty.server.HttpConfiguration; import org.eclipse.jetty.server.HttpConnectionFactory; import org.eclipse.jetty.server.Server; import org.eclipse.jetty.server.ServerConnector; @@ -246,4 +250,67 @@ public class ServerDocs void service(JSONHTTPRequest request, JSONHTTPResponse response, Callback callback); } // end::jsonHttpAPI[] + + public void httpCompliance() + { + // tag::httpCompliance[] + HttpConfiguration httpConfiguration = new HttpConfiguration(); + httpConfiguration.setHttpCompliance(HttpCompliance.RFC7230); + // end::httpCompliance[] + } + + public void httpComplianceCustom() + { + // tag::httpComplianceCustom[] + HttpConfiguration httpConfiguration = new HttpConfiguration(); + + // RFC7230 compliance, but allow Violation.MULTIPLE_CONTENT_LENGTHS. + HttpCompliance customHttpCompliance = HttpCompliance.from("RFC7230,MULTIPLE_CONTENT_LENGTHS"); + + httpConfiguration.setHttpCompliance(customHttpCompliance); + // end::httpComplianceCustom[] + } + + public void uriCompliance() + { + // tag::uriCompliance[] + HttpConfiguration httpConfiguration = new HttpConfiguration(); + httpConfiguration.setUriCompliance(UriCompliance.RFC3986); + // end::uriCompliance[] + } + + public void uriComplianceCustom() + { + // tag::uriComplianceCustom[] + HttpConfiguration httpConfiguration = new HttpConfiguration(); + + // RFC3986 compliance, but enforce Violation.AMBIGUOUS_PATH_SEPARATOR. + UriCompliance customUriCompliance = UriCompliance.from("RFC3986,-AMBIGUOUS_PATH_SEPARATOR"); + + httpConfiguration.setUriCompliance(customUriCompliance); + // end::uriComplianceCustom[] + } + + public void cookieCompliance() + { + // tag::cookieCompliance[] + HttpConfiguration httpConfiguration = new HttpConfiguration(); + httpConfiguration.setRequestCookieCompliance(CookieCompliance.RFC6265); + httpConfiguration.setResponseCookieCompliance(CookieCompliance.RFC6265); + // end::cookieCompliance[] + } + + public void cookieComplianceCustom() + { + // tag::cookieComplianceCustom[] + 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); + + // end::cookieComplianceCustom[] + } } diff --git a/jetty-http/src/main/java/org/eclipse/jetty/http/ComplianceViolation.java b/jetty-http/src/main/java/org/eclipse/jetty/http/ComplianceViolation.java index 152babae13e..25ba48b8309 100644 --- a/jetty-http/src/main/java/org/eclipse/jetty/http/ComplianceViolation.java +++ b/jetty-http/src/main/java/org/eclipse/jetty/http/ComplianceViolation.java @@ -15,30 +15,69 @@ package org.eclipse.jetty.http; import java.util.Set; +/** + * A Compliance Violation represents a requirement of an RFC, specification or Jetty implementation + * that may be allowed to be violated if it is included in a {@link ComplianceViolation.Mode}. + * For example, supporting HTTP/0.9 is no longer a requirement of the current HTTP RFC, so by including + * the {@link HttpCompliance.Violation#HTTP_0_9} in the {@link HttpCompliance} {@link ComplianceViolation.Mode} + * is interpreted as allowing HTTP/0.9 to be supported. + */ public interface ComplianceViolation { + /** + * @return The name of the violation. + */ String getName(); + /** + * @return A URL to the specification that provides more information regarding the requirement that may be violated. + */ String getURL(); + /** + * @return A short description of the violation. + */ String getDescription(); + /** + * @param mode A {@link ComplianceViolation.Mode} to test against + * @return True iff this violations is allowed by the mode. + */ default boolean isAllowedBy(Mode mode) { return mode.allows(this); } + /** + * A Mode is a set of {@link ComplianceViolation}s that are allowed. + */ interface Mode { + /** + * @return The name of the compliance violation mode. + */ String getName(); + /** + * @param violation The {@link ComplianceViolation} to test + * @return true iff the violation is allowed by this mode. + */ boolean allows(ComplianceViolation violation); + /** + * @return The immutable set of all known violations for this mode. + */ Set getKnown(); + /** + * @return The immutable set of violations allowed by this mode. + */ Set getAllowed(); } + /** + * A listener that can be notified of violations. + */ interface Listener { default void onComplianceViolation(Mode mode, ComplianceViolation violation, String details) diff --git a/jetty-http/src/main/java/org/eclipse/jetty/http/CookieCompliance.java b/jetty-http/src/main/java/org/eclipse/jetty/http/CookieCompliance.java index 89510e7cf51..be09f8972a0 100644 --- a/jetty-http/src/main/java/org/eclipse/jetty/http/CookieCompliance.java +++ b/jetty-http/src/main/java/org/eclipse/jetty/http/CookieCompliance.java @@ -18,6 +18,10 @@ import java.util.EnumSet; import java.util.List; import java.util.Objects; import java.util.Set; +import java.util.concurrent.atomic.AtomicInteger; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import static java.util.Collections.unmodifiableSet; import static java.util.EnumSet.allOf; @@ -25,13 +29,22 @@ import static java.util.EnumSet.copyOf; import static java.util.EnumSet.noneOf; /** - * The compliance for Cookie handling. + * The compliance mode for Cookie handling. */ public class CookieCompliance implements ComplianceViolation.Mode { + private static final Logger LOG = LoggerFactory.getLogger(CookieCompliance.class); + public enum Violation implements ComplianceViolation { + /** + * Allow a comma as part of a cookie value + */ COMMA_NOT_VALID_OCTET("https://tools.ietf.org/html/rfc6265#section-4.1.1", "Comma not valid as cookie-octet or separator"), + + /** + * Allow cookies to have $ prefixed reserved parameters + */ RESERVED_NAMES_NOT_DOLLAR_PREFIXED("https://tools.ietf.org/html/rfc6265#section-4.1.1", "Reserved names no longer use '$' prefix"); private final String url; @@ -62,10 +75,18 @@ public class CookieCompliance implements ComplianceViolation.Mode } } + /** + * A CookieCompliance mode that enforces RFC 6265 compliance. + */ public static final CookieCompliance RFC6265 = new CookieCompliance("RFC6265", noneOf(Violation.class)); + + /** + * A CookieCompliance mode that allows RFC 2965 compliance. + */ public static final CookieCompliance RFC2965 = new CookieCompliance("RFC2965", allOf(Violation.class)); private static final List KNOWN_MODES = Arrays.asList(RFC6265, RFC2965); + private static final AtomicInteger __custom = new AtomicInteger(); public static CookieCompliance valueOf(String name) { @@ -77,6 +98,71 @@ public class CookieCompliance implements ComplianceViolation.Mode return null; } + /** + * Create compliance set from string. + *

+ * Format: <BASE>[,[-]<violation>]... + *

+ *

BASE is one of:

+ *
+ *
0
No {@link CookieCompliance.Violation}s
+ *
*
All {@link CookieCompliance.Violation}s
+ *
<name>
The name of a static instance of CookieCompliance (e.g. {@link CookieCompliance#RFC6265}). + *
+ *

+ * The remainder of the list can contain then names of {@link CookieCompliance.Violation}s to include them in the mode, or prefixed + * with a '-' to exclude them from the mode. Examples are: + *

+ *
+ *
{@code 0,RESERVED_NAMES_NOT_DOLLAR_PREFIXED}
Only allow {@link CookieCompliance.Violation#RESERVED_NAMES_NOT_DOLLAR_PREFIXED}
+ *
{@code *,-RESERVED_NAMES_NOT_DOLLAR_PREFIXED}
Allow all violations, except {@link CookieCompliance.Violation#RESERVED_NAMES_NOT_DOLLAR_PREFIXED}
+ *
{@code RFC2965,RESERVED_NAMES_NOT_DOLLAR_PREFIXED}
Same as RFC2965, but allows {@link CookieCompliance.Violation#RESERVED_NAMES_NOT_DOLLAR_PREFIXED}
+ *
+ * + * @param spec A string describing the compliance + * @return the compliance from the string spec + */ + public static CookieCompliance from(String spec) + { + Set violations; + String[] elements = spec.split("\\s*,\\s*"); + switch (elements[0]) + { + case "0": + violations = noneOf(Violation.class); + break; + + case "*": + violations = allOf(Violation.class); + break; + + default: + { + CookieCompliance mode = valueOf(elements[0]); + violations = (mode == null) ? noneOf(Violation.class) : copyOf(mode.getAllowed()); + break; + } + } + + for (int i = 1; i < elements.length; i++) + { + String element = elements[i]; + boolean exclude = element.startsWith("-"); + if (exclude) + element = element.substring(1); + Violation section = Violation.valueOf(element); + if (exclude) + violations.remove(section); + else + violations.add(section); + } + + CookieCompliance compliance = new CookieCompliance("CUSTOM" + __custom.getAndIncrement(), violations); + if (LOG.isDebugEnabled()) + LOG.debug("CookieCompliance from {}->{}", spec, compliance); + return compliance; + } + private final String _name; private final Set _violations; diff --git a/jetty-http/src/main/java/org/eclipse/jetty/http/HttpCompliance.java b/jetty-http/src/main/java/org/eclipse/jetty/http/HttpCompliance.java index 9b2bb8ef3d8..ed17725bbc5 100644 --- a/jetty-http/src/main/java/org/eclipse/jetty/http/HttpCompliance.java +++ b/jetty-http/src/main/java/org/eclipse/jetty/http/HttpCompliance.java @@ -43,13 +43,66 @@ public final class HttpCompliance implements ComplianceViolation.Mode // the relevant section of the RFC is not strictly adhered to. public enum Violation implements ComplianceViolation { + /** + * The HTTP RFC(s) require that field names are case-insensitive, so for example the fields "{@code Content-Type: text/xml}" + * and "{@code content-type: text/xml}" are considered equivalent. Jetty has been optimized to take advantage of this by + * looking up field names in a case insensitive cache and will by default provide the standard capitalisation of a field + * name rather than create a new string with the actual capitalisation received. However, some applications have been + * written to expect a specific capitalisation of field, so deployments of such applications must include this violation + * in their {@link HttpCompliance} mode to prevent Jetty altering the case of the fields received. Jetty itself will still + * match and handle fields names insensitively and this violation only affects how the names are reported to the application. + * There is a small performance and garbage impact of using this mode. + */ CASE_SENSITIVE_FIELD_NAME("https://tools.ietf.org/html/rfc7230#section-3.2", "Field name is case-insensitive"), + + /** + * The HTTP RFC(s) require that method names are case sensitive, so that "{@code Get}" and "{@code GET}" are considered + * different methods. Jetty releases prior to 9.4 used a case insensitive cache to match method names, thus this requirement + * was violated. Deployments which wish to retain this legacy violation can include this violation in the + * {@link HttpCompliance} mode. + */ CASE_INSENSITIVE_METHOD("https://tools.ietf.org/html/rfc7230#section-3.1.1", "Method is case-sensitive"), + + /** + * Since RFC 7230, the expectation that HTTP/0.9 is supported has been removed from the specification. If a deployment + * wished to accept HTTP/0.9 requests, then it can include this violation in it's {@link HttpCompliance} mode. + */ HTTP_0_9("https://tools.ietf.org/html/rfc7230#appendix-A.2", "HTTP/0.9 not supported"), + + /** + * Since RFC 7230, the HTTP protocol no longer supports + * line folding, which allows a field value to be provided over several lines. Deployments that wish to receive folder + * field values may include this violation in their {@link HttpCompliance} mode. + */ MULTILINE_FIELD_VALUE("https://tools.ietf.org/html/rfc7230#section-3.2.4", "Line Folding not supported"), - MULTIPLE_CONTENT_LENGTHS("https://tools.ietf.org/html/rfc7230#section-3.3.1", "Multiple Content-Lengths"), + + /** + * Since RFC 7230, the HTTP protocol has required that + * a request is invalid if it contains multiple {@code Content-Length} fields or values. The request may be treated + * as invalid even if the multiple values are the same. A deployment may include this violation to allow multiple + * {@code Content-Length} values to be received, but only if they are identical. + */ + MULTIPLE_CONTENT_LENGTHS("https://tools.ietf.org/html/rfc7230#section-3.3.2", "Multiple Content-Lengths"), + + /** + * Since RFC 7230, the HTTP protocol has required that + * a request is invalid if it contains both a {@code Transfer-Encoding} field and {@code Content-Length} field. + * A deployment may include this violation to allow both fields to be in a received request. + */ TRANSFER_ENCODING_WITH_CONTENT_LENGTH("https://tools.ietf.org/html/rfc7230#section-3.3.1", "Transfer-Encoding and Content-Length"), + + /** + * Since RFC 7230, the HTTP protocol has required that + * a request header field has no white space after the field name and before the ':'. + * A deployment may include this violation to allow such fields to be in a received request. + */ WHITESPACE_AFTER_FIELD_NAME("https://tools.ietf.org/html/rfc7230#section-3.2.4", "Whitespace not allowed after field name"), + + /** + * Prior to RFC 7230, the HTTP protocol allowed a header + * line of a single token with neither a colon nor value following, to be interpreted as a field name with no value. + * A deployment may include this violation to allow such fields to be in a received request. + */ NO_COLON_AFTER_FIELD_NAME("https://tools.ietf.org/html/rfc7230#section-3.2", "Fields must have a Colon"); private final String url; @@ -80,21 +133,51 @@ public final class HttpCompliance implements ComplianceViolation.Mode } } + /** + * The request attribute which may be set to record any allowed HTTP violations. + */ public static final String VIOLATIONS_ATTR = "org.eclipse.jetty.http.compliance.violations"; + /** + * The HttpCompliance mode that supports RFC 7230 + * with no known violations. + */ public static final HttpCompliance RFC7230 = new HttpCompliance("RFC7230", noneOf(Violation.class)); + + /** + * The HttpCompliance mode that supports RFC 7230 + * with only the violations that differ from {@link #RFC7230}. + */ public static final HttpCompliance RFC2616 = new HttpCompliance("RFC2616", of(Violation.HTTP_0_9, Violation.MULTILINE_FIELD_VALUE)); + + /** + * A legacy HttpCompliance mode that allows all violations except case-insensitive methods. + */ public static final HttpCompliance LEGACY = new HttpCompliance("LEGACY", complementOf(of(Violation.CASE_INSENSITIVE_METHOD))); + + /** + * A legacy HttpCompliance mode that supports {@link #RFC2616}, but that also allows: case-insensitive methods; + * colons after field names; {@code Transfer-Encoding} with {@code Content-Length} fields; and multiple {@code Content-Length} values. + */ public static final HttpCompliance RFC2616_LEGACY = RFC2616.with("RFC2616_LEGACY", Violation.CASE_INSENSITIVE_METHOD, Violation.NO_COLON_AFTER_FIELD_NAME, Violation.TRANSFER_ENCODING_WITH_CONTENT_LENGTH, Violation.MULTIPLE_CONTENT_LENGTHS); + + /** + * A legacy HttpCompliance mode that supports {@link #RFC7230}, but with case-insensitive methods allowed. + */ public static final HttpCompliance RFC7230_LEGACY = RFC7230.with("RFC7230_LEGACY", Violation.CASE_INSENSITIVE_METHOD); private static final List KNOWN_MODES = Arrays.asList(RFC7230, RFC2616, LEGACY, RFC2616_LEGACY, RFC7230_LEGACY); private static final AtomicInteger __custom = new AtomicInteger(); + /** + * Get a known compliance mode by name. + * @param name The name of a known {@link HttpCompliance} mode. + * @return The mode matching the name. + */ public static HttpCompliance valueOf(String name) { for (HttpCompliance compliance : KNOWN_MODES) @@ -107,7 +190,7 @@ public final class HttpCompliance implements ComplianceViolation.Mode } /** - * Create compliance set from string. + * Create compliance mode from a String description. *

* Format: *

@@ -121,11 +204,11 @@ public final class HttpCompliance implements ComplianceViolation.Mode * *

* The remainder of the list can contain then names of {@link Violation}s to include them in the mode, or prefixed - * with a '-' to exclude thm from the mode. + * with a '-' to exclude them from the mode. *

* - * @param spec A string in the format of a comma separated list starting with one of the following strings: - * @return the compliance from the string spec + * @param spec A string describing the compliance + * @return the HttpCompliance instance derived from the string description */ public static HttpCompliance from(String spec) { @@ -186,11 +269,6 @@ public final class HttpCompliance implements ComplianceViolation.Mode return _name; } - /** - * Get the set of {@link Violation}s allowed by this compliance mode. - * - * @return The immutable set of {@link Violation}s allowed by this compliance mode. - */ @Override public Set getAllowed() { diff --git a/jetty-http/src/main/java/org/eclipse/jetty/http/UriCompliance.java b/jetty-http/src/main/java/org/eclipse/jetty/http/UriCompliance.java index 15120cefd74..f9d0504283a 100644 --- a/jetty-http/src/main/java/org/eclipse/jetty/http/UriCompliance.java +++ b/jetty-http/src/main/java/org/eclipse/jetty/http/UriCompliance.java @@ -40,7 +40,8 @@ public final class UriCompliance implements ComplianceViolation.Mode /** * These are URI compliance "violations", which may be allowed by the compliance mode. These are actual - * violations of the RFC, as they represent additional requirements in excess of the strict compliance of rfc3986. + * violations of the RFC, as they represent additional requirements in excess of the strict compliance of + * RFC 3986. * A compliance mode that contains one or more of these Violations, allows request to violate the corresponding * additional requirement. */ @@ -104,10 +105,9 @@ public final class UriCompliance implements ComplianceViolation.Mode } /** - * The default compliance mode that extends RFC3986 compliance with additional violations to avoid most ambiguous URIs. - * This mode does allow {@link Violation#AMBIGUOUS_PATH_SEPARATOR}, but disallows - * {@link Violation#AMBIGUOUS_PATH_PARAMETER}, {@link Violation#AMBIGUOUS_PATH_SEGMENT} and {@link Violation#AMBIGUOUS_PATH_ENCODING}. - * Ambiguous paths are not allowed by {@link Violation#NON_CANONICAL_AMBIGUOUS_PATHS}. + * The default compliance mode that extends RFC3986 compliance with + * additional violations to avoid most ambiguous URIs. + * This mode does allow {@link Violation#AMBIGUOUS_PATH_SEPARATOR}, but disallows all out {@link Violation}s. */ public static final UriCompliance DEFAULT = new UriCompliance("DEFAULT", of(Violation.AMBIGUOUS_PATH_SEPARATOR)); @@ -124,11 +124,18 @@ public final class UriCompliance implements ComplianceViolation.Mode Violation.UTF16_ENCODINGS)); /** - * Compliance mode that exactly follows RFC3986, including allowing all additional ambiguous URI Violations, + * Compliance mode that exactly follows RFC3986, + * including allowing all additional ambiguous URI Violations, * except {@link Violation#NON_CANONICAL_AMBIGUOUS_PATHS}, thus ambiguous paths are canonicalized for safety. */ public static final UriCompliance RFC3986 = new UriCompliance("RFC3986", complementOf(of(Violation.NON_CANONICAL_AMBIGUOUS_PATHS))); + /** + * Compliance mode that follows RFC3986 + * plus it does not allow any ambiguous URI {@link Violation}s. + */ + public static final UriCompliance RFC3986_UNAMBIGUOUS = new UriCompliance("RFC3986_UNAMBIGUOUS", noneOf(Violation.class)); + /** * Compliance mode that allows all URI Violations, including allowing ambiguous paths in non canonicalized form. */ @@ -181,20 +188,20 @@ public final class UriCompliance implements ComplianceViolation.Mode *
*
0
No {@link Violation}s
*
*
All {@link Violation}s
- *
<name>
The name of a static instance of {@link UriCompliance} (e.g. {@link UriCompliance#RFC3986}). + *
<name>
The name of a static instance of UriCompliance (e.g. {@link UriCompliance#RFC3986}). *
*

* The remainder of the list can contain then names of {@link Violation}s to include them in the mode, or prefixed - * with a '-' to exclude thm from the mode. Examples are: + * with a '-' to exclude them from the mode. Examples are: *

*
- *
0,AMBIGUOUS_PATH_PARAMETER
Only allow {@link Violation#AMBIGUOUS_PATH_PARAMETER}
- *
*,-AMBIGUOUS_PATH_PARAMETER
Only all except {@link Violation#AMBIGUOUS_PATH_PARAMETER}
- *
RFC3986,AMBIGUOUS_PATH_PARAMETER
Same as RFC3986 plus {@link Violation#AMBIGUOUS_PATH_PARAMETER}
+ *
{@code 0,AMBIGUOUS_PATH_PARAMETER}
Only allow {@link Violation#AMBIGUOUS_PATH_PARAMETER}
+ *
{@code *,-AMBIGUOUS_PATH_PARAMETER}
Only all except {@link Violation#AMBIGUOUS_PATH_PARAMETER}
+ *
{@code RFC3986,AMBIGUOUS_PATH_PARAMETER}
Same as RFC3986 plus {@link Violation#AMBIGUOUS_PATH_PARAMETER}
*
* - * @param spec A string in the format of a comma separated list starting with one of the following strings: - * @return the compliance from the string spec + * @param spec A string describing the compliance + * @return the UriCompliance instance derived from the string description */ public static UriCompliance from(String spec) { diff --git a/jetty-server/src/main/config/etc/jetty.xml b/jetty-server/src/main/config/etc/jetty.xml index 42dcefc69ad..b2d16df274c 100644 --- a/jetty-server/src/main/config/etc/jetty.xml +++ b/jetty-server/src/main/config/etc/jetty.xml @@ -76,8 +76,8 @@ - - + + diff --git a/jetty-server/src/main/config/modules/server.mod b/jetty-server/src/main/config/modules/server.mod index 8c5a301578c..cc4ee187cca 100644 --- a/jetty-server/src/main/config/modules/server.mod +++ b/jetty-server/src/main/config/modules/server.mod @@ -25,6 +25,7 @@ lib/jetty-io-${jetty.version}.jar etc/jetty.xml [ini-template] +# tag::documentation-http-config[] ### Common HTTP configuration ## Scheme to use to build URIs for secure redirects # jetty.httpConfig.secureScheme=https @@ -59,10 +60,19 @@ etc/jetty.xml ## Maximum number of error dispatches to prevent looping # jetty.httpConfig.maxErrorDispatches=10 +## Relative Redirect Locations allowed +# jetty.httpConfig.relativeRedirectAllowed=false + +## Whether to use direct ByteBuffers for reading or writing +# jetty.httpConfig.useInputDirectByteBuffers=true +# jetty.httpConfig.useOutputDirectByteBuffers=true +# end::documentation-http-config[] + +# tag::documentation-server-compliance[] ## HTTP Compliance: RFC7230, RFC7230_LEGACY, RFC2616, RFC2616_LEGACY, LEGACY # jetty.httpConfig.compliance=RFC7230 -## URI Compliance: DEFAULT, LEGACY, RFC3986, UNSAFE +## URI Compliance: DEFAULT, LEGACY, RFC3986, RFC3986_UNAMBIGUOUS, UNSAFE # jetty.httpConfig.uriCompliance=DEFAULT ## Cookie compliance mode for parsing request Cookie headers: RFC2965, RFC6265 @@ -70,14 +80,9 @@ etc/jetty.xml ## Cookie compliance mode for generating response Set-Cookie: RFC2965, RFC6265 # jetty.httpConfig.responseCookieCompliance=RFC6265 +# end::documentation-server-compliance[] -## Relative Redirect Locations allowed -# jetty.httpConfig.relativeRedirectAllowed=false - -## Whether to use direct ByteBuffers for reading or writing -# jetty.httpConfig.useInputDirectByteBuffers=true -# jetty.httpConfig.useOutputDirectByteBuffers=true - +# tag::documentation-server-config[] ### Server configuration ## Whether ctrl+c on the console gracefully stops the Jetty server # jetty.server.stopAtShutdown=true @@ -90,9 +95,16 @@ etc/jetty.xml ## Dump the state of the Jetty server, components, and webapps before shutdown # jetty.server.dumpBeforeStop=false +# end::documentation-server-config[] -## Scheduler Configuration +# tag::documentation-scheduler-config[] +### Server Scheduler Configuration +## The scheduler thread name, defaults to "Scheduler-{hashCode()}" if blank. # jetty.scheduler.name= -# jetty.scheduler.deamon=false -# jetty.scheduler.threads=-1 +## Whether the server scheduler threads are daemon. +# jetty.scheduler.daemon=false + +## The number of server scheduler threads. +# jetty.scheduler.threads=1 +# end::documentation-scheduler-config[] diff --git a/jetty-server/src/test/java/org/eclipse/jetty/server/RequestTest.java b/jetty-server/src/test/java/org/eclipse/jetty/server/RequestTest.java index e0ba04fa6b7..e31f303438d 100644 --- a/jetty-server/src/test/java/org/eclipse/jetty/server/RequestTest.java +++ b/jetty-server/src/test/java/org/eclipse/jetty/server/RequestTest.java @@ -1750,6 +1750,8 @@ public class RequestTest "\r\n"; _connector.getBean(HttpConnectionFactory.class).getHttpConfiguration().setUriCompliance(UriCompliance.DEFAULT); assertThat(_connector.getResponse(request), startsWith("HTTP/1.1 400")); + _connector.getBean(HttpConnectionFactory.class).getHttpConfiguration().setUriCompliance(UriCompliance.RFC3986_UNAMBIGUOUS); + assertThat(_connector.getResponse(request), startsWith("HTTP/1.1 400")); _connector.getBean(HttpConnectionFactory.class).getHttpConfiguration().setUriCompliance(UriCompliance.LEGACY); assertThat(_connector.getResponse(request), startsWith("HTTP/1.1 200")); _connector.getBean(HttpConnectionFactory.class).getHttpConfiguration().setUriCompliance(UriCompliance.RFC3986);