Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions http/itest/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@
<properties>
<felix.java.version>17</felix.java.version>
<http.servlet.api.version>6.1.0</http.servlet.api.version>
<http.jetty.version>2.0.1-SNAPSHOT</http.jetty.version>
<http.jetty.version>2.0.3-SNAPSHOT</http.jetty.version>
<http.jetty.id>org.apache.felix.http.jetty12</http.jetty.id>
<pax.exam.version>4.13.3</pax.exam.version>
<pax.url.aether.version>2.6.14</pax.url.aether.version>
Expand All @@ -45,7 +45,7 @@
<properties>
<felix.java.version>11</felix.java.version>
<http.servlet.api.version>6.1.0</http.servlet.api.version>
<http.jetty.version>5.2.3-SNAPSHOT</http.jetty.version>
<http.jetty.version>5.2.5-SNAPSHOT</http.jetty.version>
<http.jetty.id>org.apache.felix.http.jetty</http.jetty.id>
</properties>
</profile>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -788,6 +788,11 @@ private void configureHttpConnectionFactory(HttpConnectionFactory connFactory)
try {
UriCompliance compliance = UriCompliance.valueOf(uriComplianceMode);
config.setUriCompliance(compliance);
// Apply the same compliance to redirect URIs (Location header). Since Jetty 12.1
// this defaults to UriCompliance.DEFAULT_REDIRECT, which - like the request URI
// default - rejects ambiguous encodings such as %2F. Differentiating the two makes
// no sense: if a deployment opts into a compliance mode it should apply end-to-end.
config.setRedirectUriCompliance(compliance);

if (LEGACY.equals(compliance) || UNSAFE.equals(compliance) || UNAMBIGUOUS.equals(compliance)) {
// See https://github.com/jetty/jetty.project/issues/11448#issuecomment-1969206031
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -115,9 +115,32 @@ public void testUriCompliance() throws Exception {
}
}

@Test
public void testRedirectUriCompliance() throws Exception {
try (HttpClient httpClient = new HttpClient()) {
httpClient.setFollowRedirects(false);
httpClient.start();
Object value = bundleContext.getServiceReference(HttpService.class).getProperty("org.osgi.service.http.port");
int httpPort = Integer.parseInt((String) value);

URI destUriRedirect = new URI(String.format("http://localhost:%d/endpoint/redirect", httpPort));

// The endpoint issues a redirect whose Location contains an ambiguous %2F.
// With the default redirect compliance (DEFAULT_REDIRECT) this is rejected,
// surfacing as an internal server error rather than a 302.
ContentResponse response = httpClient.GET(destUriRedirect);
assertEquals(500, response.getStatus());
}
}

static final class UriComplianceEndpoint extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException {
if (req.getRequestURI().contains("redirect")) {
// Location deliberately contains an ambiguous encoded separator (%2F)
resp.sendRedirect("/endpoint/redirected%2Ftarget");
return;
}
resp.setStatus(200);
resp.getWriter().write("OK");
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -64,4 +64,23 @@ public void testUriCompliance() throws Exception {
assertEquals("OK", response2.getContentAsString());
}
}

@Test
@Override
public void testRedirectUriCompliance() throws Exception {
try (HttpClient httpClient = new HttpClient()) {
httpClient.setFollowRedirects(false);
httpClient.start();
Object value = bundleContext.getServiceReference(HttpService.class).getProperty("org.osgi.service.http.port");
int httpPort = Integer.parseInt((String) value);

URI destUriRedirect = new URI(String.format("http://localhost:%d/endpoint/redirect", httpPort));

// With LEGACY compliance the ambiguous %2F in the Location header is allowed,
// so the redirect is emitted normally instead of being rejected.
ContentResponse response = httpClient.GET(destUriRedirect);
assertEquals(302, response.getStatus());
assertEquals("/endpoint/redirected%2Ftarget", response.getHeaders().get("Location"));
}
}
}
Loading