Skip to content

Commit 485c095

Browse files
authored
FELIX-6707 : Fix uriComplianceMode
* Fix uriComplianceMode When making code review changes, an error was made in using the enum. This pr fixes it. Will add a unit test to guard behavior. * Add unit tests to assert org.eclipse.jetty.UriComplianceMode works * Assert response
1 parent 2eb711b commit 485c095

File tree

3 files changed

+205
-5
lines changed

3 files changed

+205
-5
lines changed

http/jetty12/src/main/java/org/apache/felix/http/jetty/internal/JettyService.java

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,10 @@
1616
*/
1717
package org.apache.felix.http.jetty.internal;
1818

19+
import static org.eclipse.jetty.http.UriCompliance.LEGACY;
20+
import static org.eclipse.jetty.http.UriCompliance.UNAMBIGUOUS;
21+
import static org.eclipse.jetty.http.UriCompliance.UNSAFE;
22+
1923
import java.net.Inet4Address;
2024
import java.net.Inet6Address;
2125
import java.net.InetAddress;
@@ -677,15 +681,14 @@ private void configureHttpConnectionFactory(HttpConnectionFactory connFactory)
677681
config.setRequestHeaderSize(this.config.getHeaderSize());
678682
config.setResponseHeaderSize(this.config.getHeaderSize());
679683
config.setOutputBufferSize(this.config.getResponseBufferSize());
680-
684+
681685
String uriComplianceMode = this.config.getProperty(JettyConfig.FELIX_JETTY_URI_COMPLIANCE_MODE, null);
682686
if (uriComplianceMode != null) {
683687
try {
684-
config.setUriCompliance(UriCompliance.valueOf(uriComplianceMode));
688+
UriCompliance compliance = UriCompliance.valueOf(uriComplianceMode);
689+
config.setUriCompliance(compliance);
685690

686-
if (UriCompliance.LEGACY.equals(uriComplianceMode)
687-
|| UriCompliance.UNSAFE.equals(uriComplianceMode)
688-
|| UriCompliance.UNAMBIGUOUS.equals(uriComplianceMode)) {
691+
if (LEGACY.equals(compliance) || UNSAFE.equals(compliance) || UNAMBIGUOUS.equals(compliance)) {
689692
// See https://github.com/jetty/jetty.project/issues/11448#issuecomment-1969206031
690693
this.server.getContainedBeans(ServletHandler.class)
691694
.forEach(handler -> handler.setDecodeAmbiguousURIs(true));
Lines changed: 114 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,114 @@
1+
/*
2+
* Licensed to the Apache Software Foundation (ASF) under one or more
3+
* contributor license agreements. See the NOTICE file distributed with
4+
* this work for additional information regarding copyright ownership.
5+
* The ASF licenses this file to You under the Apache License, Version 2.0
6+
* (the "License"); you may not use this file except in compliance with
7+
* the License. You may obtain a copy of the License at
8+
*
9+
* http://www.apache.org/licenses/LICENSE-2.0
10+
*
11+
* Unless required by applicable law or agreed to in writing, software
12+
* distributed under the License is distributed on an "AS IS" BASIS,
13+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
* See the License for the specific language governing permissions and
15+
* limitations under the License.
16+
*/
17+
package org.apache.felix.http.jetty.it;
18+
19+
import static org.junit.Assert.assertEquals;
20+
import static org.junit.Assert.assertNotNull;
21+
import static org.ops4j.pax.exam.CoreOptions.mavenBundle;
22+
import static org.ops4j.pax.exam.cm.ConfigurationAdminOptions.newConfiguration;
23+
24+
import java.io.IOException;
25+
import java.net.URI;
26+
import java.util.Hashtable;
27+
import java.util.Map;
28+
29+
import javax.inject.Inject;
30+
import jakarta.servlet.Servlet;
31+
import jakarta.servlet.http.HttpServlet;
32+
import jakarta.servlet.http.HttpServletRequest;
33+
import jakarta.servlet.http.HttpServletResponse;
34+
35+
import org.eclipse.jetty.client.ContentResponse;
36+
import org.eclipse.jetty.client.HttpClient;
37+
import org.eclipse.jetty.client.transport.HttpClientTransportOverHTTP;
38+
import org.junit.Before;
39+
import org.junit.Test;
40+
import org.junit.runner.RunWith;
41+
import org.ops4j.pax.exam.Option;
42+
import org.ops4j.pax.exam.junit.PaxExam;
43+
import org.ops4j.pax.exam.spi.reactors.ExamReactorStrategy;
44+
import org.ops4j.pax.exam.spi.reactors.PerClass;
45+
import org.osgi.framework.BundleContext;
46+
import org.osgi.service.http.HttpService;
47+
import org.osgi.service.servlet.whiteboard.HttpWhiteboardConstants;
48+
@RunWith(PaxExam.class)
49+
@ExamReactorStrategy(PerClass.class)
50+
public class JettyUriComplianceModeDefaultIT extends AbstractJettyTestSupport {
51+
52+
@Inject
53+
protected BundleContext bundleContext;
54+
55+
@Override
56+
protected Option[] additionalOptions() throws IOException {
57+
String jettyVersion = System.getProperty("jetty.version", "12.0.8");
58+
return new Option[] {
59+
spifly(),
60+
61+
// bundles for the server side
62+
mavenBundle().groupId("org.eclipse.jetty.ee10").artifactId("jetty-ee10-webapp").version(jettyVersion),
63+
mavenBundle().groupId("org.eclipse.jetty.ee10").artifactId("jetty-ee10-servlet").version(jettyVersion),
64+
mavenBundle().groupId("org.eclipse.jetty").artifactId("jetty-xml").version(jettyVersion),
65+
66+
// additional bundles for the client side
67+
mavenBundle().groupId("org.eclipse.jetty").artifactId("jetty-alpn-client").version(jettyVersion),
68+
mavenBundle().groupId("org.eclipse.jetty").artifactId("jetty-client").version(jettyVersion)
69+
};
70+
}
71+
72+
@Override
73+
protected Option felixHttpConfig(int httpPort) {
74+
return newConfiguration("org.apache.felix.http")
75+
.put("org.osgi.service.http.port", httpPort)
76+
.asOption();
77+
}
78+
79+
@Before
80+
public void setup(){
81+
assertNotNull(bundleContext);
82+
bundleContext.registerService(Servlet.class, new UriComplianceEndpoint(), new Hashtable<>(Map.of(
83+
HttpWhiteboardConstants.HTTP_WHITEBOARD_SERVLET_PATTERN, "/*"
84+
)));
85+
}
86+
87+
@Test
88+
public void testUriCompliance() throws Exception {
89+
HttpClientTransportOverHTTP transport = new HttpClientTransportOverHTTP();
90+
HttpClient httpClient = new HttpClient(transport);
91+
httpClient.start();
92+
93+
Object value = bundleContext.getServiceReference(HttpService.class).getProperty("org.osgi.service.http.port");
94+
int httpPort = Integer.parseInt((String) value);
95+
96+
URI destUriWorking = new URI(String.format("http://localhost:%d/endpoint/working", httpPort));
97+
URI destUriAmbigousPath = new URI("http://localhost:" + httpPort + "/endpoint/ambigousPathitem_0_http%3A%2F%2Fwww.test.com%2F0.html/abc");
98+
99+
ContentResponse response = httpClient.GET(destUriWorking);
100+
assertEquals(200, response.getStatus());
101+
assertEquals("OK", response.getContentAsString());
102+
103+
// blocked with HTTP 400 by default
104+
assertEquals(400, httpClient.GET(destUriAmbigousPath).getStatus());
105+
}
106+
107+
static final class UriComplianceEndpoint extends HttpServlet {
108+
@Override
109+
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException {
110+
resp.setStatus(200);
111+
resp.getWriter().write("OK");
112+
}
113+
}
114+
}
Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
/*
2+
* Licensed to the Apache Software Foundation (ASF) under one or more
3+
* contributor license agreements. See the NOTICE file distributed with
4+
* this work for additional information regarding copyright ownership.
5+
* The ASF licenses this file to You under the Apache License, Version 2.0
6+
* (the "License"); you may not use this file except in compliance with
7+
* the License. You may obtain a copy of the License at
8+
*
9+
* http://www.apache.org/licenses/LICENSE-2.0
10+
*
11+
* Unless required by applicable law or agreed to in writing, software
12+
* distributed under the License is distributed on an "AS IS" BASIS,
13+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
* See the License for the specific language governing permissions and
15+
* limitations under the License.
16+
*/
17+
package org.apache.felix.http.jetty.it;
18+
19+
import static org.eclipse.jetty.http.UriCompliance.LEGACY;
20+
import static org.junit.Assert.assertEquals;
21+
import static org.junit.Assert.assertNotNull;
22+
import static org.ops4j.pax.exam.CoreOptions.mavenBundle;
23+
import static org.ops4j.pax.exam.cm.ConfigurationAdminOptions.newConfiguration;
24+
25+
import java.io.IOException;
26+
import java.net.URI;
27+
import java.util.Hashtable;
28+
import java.util.Map;
29+
30+
import javax.inject.Inject;
31+
import jakarta.servlet.Servlet;
32+
import jakarta.servlet.http.HttpServlet;
33+
import jakarta.servlet.http.HttpServletRequest;
34+
import jakarta.servlet.http.HttpServletResponse;
35+
36+
import org.eclipse.jetty.client.ContentResponse;
37+
import org.eclipse.jetty.client.HttpClient;
38+
import org.eclipse.jetty.client.transport.HttpClientTransportOverHTTP;
39+
import org.eclipse.jetty.http.UriCompliance;
40+
import org.junit.Test;
41+
import org.junit.runner.RunWith;
42+
import org.ops4j.pax.exam.Option;
43+
import org.ops4j.pax.exam.junit.PaxExam;
44+
import org.ops4j.pax.exam.spi.reactors.ExamReactorStrategy;
45+
import org.ops4j.pax.exam.spi.reactors.PerClass;
46+
import org.osgi.framework.BundleContext;
47+
import org.osgi.service.http.HttpService;
48+
import org.osgi.service.servlet.whiteboard.HttpWhiteboardConstants;
49+
50+
@RunWith(PaxExam.class)
51+
@ExamReactorStrategy(PerClass.class)
52+
public class JettyUriComplianceModeLegacyIT extends JettyUriComplianceModeDefaultIT {
53+
54+
@Override
55+
protected Option felixHttpConfig(int httpPort) {
56+
return newConfiguration("org.apache.felix.http")
57+
.put("org.osgi.service.http.port", httpPort)
58+
.put("org.eclipse.jetty.UriComplianceMode", LEGACY.getName())
59+
.asOption();
60+
}
61+
62+
@Test
63+
public void testUriCompliance() throws Exception {
64+
HttpClientTransportOverHTTP transport = new HttpClientTransportOverHTTP();
65+
HttpClient httpClient = new HttpClient(transport);
66+
httpClient.start();
67+
68+
Object value = bundleContext.getServiceReference(HttpService.class).getProperty("org.osgi.service.http.port");
69+
int httpPort = Integer.parseInt((String) value);
70+
71+
URI destUriWorking = new URI(String.format("http://localhost:%d/endpoint/working", httpPort));
72+
URI destUriAmbigousPath = new URI("http://localhost:" + httpPort + "/endpoint/ambigousPathitem_0_http%3A%2F%2Fwww.test.com%2F0.html/abc");
73+
74+
ContentResponse response = httpClient.GET(destUriWorking);
75+
assertEquals(200, response.getStatus());
76+
assertEquals("OK", response.getContentAsString());
77+
78+
// no longer blocked due to LEGACY compliance mode
79+
ContentResponse response2 = httpClient.GET(destUriAmbigousPath);
80+
assertEquals(200, response2.getStatus());
81+
assertEquals("OK", response2.getContentAsString());
82+
}
83+
}

0 commit comments

Comments
 (0)