diff --git a/http/README.md b/http/README.md index be402ef77a..875fcce940 100644 --- a/http/README.md +++ b/http/README.md @@ -413,6 +413,7 @@ properties can be used (some legacy property names still exist but are not docum | `org.eclipse.jetty.servlet.SessionDomain` | Domain to set on the session cookie. The default is `null`. | | `org.eclipse.jetty.servlet.SessionPath` | The path to set on the session cookie. The default is the configured session context path ("/"). | | `org.eclipse.jetty.servlet.MaxAge` | The maximum age value to set on the cookie. The default is "-1". | +| `org.eclipse.jetty.UriComplianceMode` | The URI compliance mode to set. The default is [DEFAULT](https://eclipse.dev/jetty/javadoc/jetty-12/org/eclipse/jetty/http/UriCompliance.html#DEFAULT). See [documentation](https://eclipse.dev/jetty/documentation/jetty-12/programming-guide/index.html#pg-server-compliance-uri.) and [possible modes](https://github.com/jetty/jetty.project/blob/jetty-12.0.x/jetty-core/jetty-http/src/main/java/org/eclipse/jetty/http/UriCompliance.java#L186C107-L186C113). | | `org.apache.felix.proxy.load.balancer.connection.enable` | Set this to `true` when running Felix HTTP behind a (offloading) proxy or load balancer which rewrites the requests. The default is `false`. | | `org.apache.felix.http.runtime.init.` | Properties starting with this prefix are added as service registration properties to the HttpServiceRuntime service. The prefix is removed for the property name. | | `org.apache.felix.jetty.gziphandler.enable` | Whether the server should use a server-wide gzip handler. Default is false. | diff --git a/http/jetty12/src/main/java/org/apache/felix/http/jetty/internal/ConfigMetaTypeProvider.java b/http/jetty12/src/main/java/org/apache/felix/http/jetty/internal/ConfigMetaTypeProvider.java index 03bd3cf02f..917e334132 100644 --- a/http/jetty12/src/main/java/org/apache/felix/http/jetty/internal/ConfigMetaTypeProvider.java +++ b/http/jetty12/src/main/java/org/apache/felix/http/jetty/internal/ConfigMetaTypeProvider.java @@ -284,6 +284,12 @@ public ObjectClassDefinition getObjectClassDefinition( String id, String locale false, bundle.getBundleContext().getProperty(JettyConfig.FELIX_JETTY_SESSION_COOKIE_SECURE))); + adList.add(new AttributeDefinitionImpl(JettyConfig.FELIX_JETTY_URI_COMPLIANCE_MODE, + "Jetty URI compliance mode", + "Jetty URI compliance mode (if not set, Jetty will configure a default)", + null, + bundle.getBundleContext().getProperty(JettyConfig.FELIX_JETTY_URI_COMPLIANCE_MODE))); + adList.add(new AttributeDefinitionImpl(JettyConfig.FELIX_JETTY_SERVLET_SESSION_ID_PATH_PARAMETER_NAME, "Session Id path parameter", "Defaults to jsessionid. If set to null or \"none\" no URL rewriting will be done.", diff --git a/http/jetty12/src/main/java/org/apache/felix/http/jetty/internal/JettyConfig.java b/http/jetty12/src/main/java/org/apache/felix/http/jetty/internal/JettyConfig.java index ef336ea61c..05e6c7f941 100644 --- a/http/jetty12/src/main/java/org/apache/felix/http/jetty/internal/JettyConfig.java +++ b/http/jetty12/src/main/java/org/apache/felix/http/jetty/internal/JettyConfig.java @@ -166,6 +166,9 @@ public final class JettyConfig /** Felix specific property to configure session max age */ public static final String FELIX_JETTY_SERVLET_SESSION_MAX_AGE = "org.eclipse.jetty.servlet.MaxAge"; + /** Felix specific property to configure the uri compliance mode (https://eclipse.dev/jetty/documentation/jetty-12/programming-guide/index.html#pg-server-compliance-uri) */ + public static final String FELIX_JETTY_URI_COMPLIANCE_MODE = "org.eclipse.jetty.UriComplianceMode"; + /** Felix specific property to configure session scavenging interval in Seconds */ public static final String FELIX_JETTY_SESSION_SCAVENGING_INTERVAL = "org.eclipse.jetty.servlet.SessionScavengingInterval"; diff --git a/http/jetty12/src/main/java/org/apache/felix/http/jetty/internal/JettyService.java b/http/jetty12/src/main/java/org/apache/felix/http/jetty/internal/JettyService.java index 2d993fcb65..f75a6af3d8 100644 --- a/http/jetty12/src/main/java/org/apache/felix/http/jetty/internal/JettyService.java +++ b/http/jetty12/src/main/java/org/apache/felix/http/jetty/internal/JettyService.java @@ -34,7 +34,9 @@ import org.eclipse.jetty.ee10.servlet.ServletContextHandler; import org.eclipse.jetty.ee10.servlet.ServletHolder; import org.eclipse.jetty.ee10.servlet.SessionHandler; +import org.eclipse.jetty.ee10.servlet.ServletHandler; import org.eclipse.jetty.http.HttpVersion; +import org.eclipse.jetty.http.UriCompliance; import org.eclipse.jetty.http2.server.HTTP2ServerConnectionFactory; import org.eclipse.jetty.io.ConnectionStatistics; import org.eclipse.jetty.security.HashLoginService; @@ -251,9 +253,9 @@ private void initializeJetty() throws Exception loginService.setUserStore(new UserStore()); this.server.addBean(loginService); - ServletContextHandler context = new ServletContextHandler(this.config.getContextPath(), + ServletContextHandler context = new ServletContextHandler(this.config.getContextPath(), ServletContextHandler.SESSIONS); - + this.parent = new ContextHandlerCollection(context); configureSessionManager(context); @@ -564,6 +566,23 @@ private void configureHttpConnectionFactory(HttpConnectionFactory connFactory) config.setResponseHeaderSize(this.config.getHeaderSize()); config.setOutputBufferSize(this.config.getResponseBufferSize()); + String uriComplianceMode = this.config.getProperty(JettyConfig.FELIX_JETTY_URI_COMPLIANCE_MODE, null); + if (uriComplianceMode != null) { + try { + config.setUriCompliance(UriCompliance.valueOf(uriComplianceMode)); + + if (UriCompliance.LEGACY.equals(uriComplianceMode) + || UriCompliance.UNSAFE.equals(uriComplianceMode) + || UriCompliance.UNAMBIGUOUS.equals(uriComplianceMode)) { + // See https://github.com/jetty/jetty.project/issues/11448#issuecomment-1969206031 + this.server.getContainedBeans(ServletHandler.class) + .forEach(handler -> handler.setDecodeAmbiguousURIs(true)); + } + } catch (IllegalArgumentException e) { + SystemLogger.LOGGER.warn("Invalid URI compliance mode: {}", uriComplianceMode); + } + } + // HTTP/1.1 requires Date header if possible (it is) config.setSendDateHeader(true); config.setSendServerVersion(this.config.isSendServerHeader());