Skip to content

Commit

Permalink
Enable percent encoding servlet context path and servlet path
Browse files Browse the repository at this point in the history
Signed-off-by: jansupol <jan.supol@oracle.com>
  • Loading branch information
jansupol authored and senivam committed Jan 18, 2022
1 parent 4106350 commit 2703ee5
Show file tree
Hide file tree
Showing 8 changed files with 405 additions and 12 deletions.
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2012, 2019 Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2012, 2022 Oracle and/or its affiliates. All rights reserved.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0, which is available at
Expand Down Expand Up @@ -288,16 +288,8 @@ protected void service(final HttpServletRequest request, final HttpServletRespon
* We need to work around this and not use getPathInfo
* for the decodedPath.
*/
final String decodedBasePath = request.getContextPath() + servletPath + "/";

final String encodedBasePath = UriComponent.encode(decodedBasePath,
UriComponent.Type.PATH);

if (!decodedBasePath.equals(encodedBasePath)) {
setResponseForInvalidUri(response, new ProcessingException("The servlet context path and/or the "
+ "servlet path contain characters that are percent encoded"));
return;
}
final String encodedBasePath = UriComponent.contextualEncode(
request.getContextPath() + servletPath, UriComponent.Type.PATH) + "/";

final URI baseUri;
final URI requestUri;
Expand Down
@@ -0,0 +1,155 @@
/*
* Copyright (c) 2022 Oracle and/or its affiliates. All rights reserved.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0, which is available at
* http://www.eclipse.org/legal/epl-2.0.
*
* This Source Code may also be made available under the following Secondary
* Licenses when the conditions for such availability set forth in the
* Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
* version 2 with the GNU Classpath Exception, which is available at
* https://www.gnu.org/software/classpath/license.html.
*
* SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
*/

package org.glassfish.jersey.servlet.internal;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.glassfish.jersey.internal.util.collection.Value;
import org.glassfish.jersey.internal.util.collection.Values;
import org.glassfish.jersey.servlet.ServletContainer;
import org.junit.Assert;
import org.junit.Test;

import java.io.IOException;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.net.URI;

/**
* Context encoding test. See Jersey-4949.
*/
public class ContextPathEncodingTest {
private static final String PATH = "A%20B";
private static final String CONTEXT = "c%20ntext";

@Test
public void contextEncodingTest() throws ServletException, IOException {
// In jetty maven plugin, context is set by
//<configuration>
// <scan>10</scan>
// <webApp>
// <contextPath>/c ntext</contextPath>
// </webApp>
//</configuration>

//Servlet path is not encoded, context is encoded
final ServletRequestValues servletRequestValues = new ServletRequestValues(
"/" + CONTEXT,
"",
"/" + CONTEXT + "/" + PATH
);
final EncodingTestServletContainer testServletContainer = new EncodingTestServletContainer(
"/" + CONTEXT + "/",
"/" + CONTEXT + "/" + PATH
);
EncodingTestData testData = new EncodingTestData(servletRequestValues, testServletContainer);

testData.test();
}

@Test
public void servletPathEncodingTest() throws ServletException, IOException {
//Servlet path is not encoded, context is encoded
final ServletRequestValues servletRequestValues = new ServletRequestValues(
"/",
"A B",
"/" + PATH + "/" + PATH
);
final EncodingTestServletContainer testServletContainer = new EncodingTestServletContainer(
"/" + PATH + "/",
"/" + PATH + "/" + PATH
);
EncodingTestData testData = new EncodingTestData(servletRequestValues, testServletContainer);

testData.test();
}

static class EncodingTestData {
final ServletRequestValues servletRequestValues;
final EncodingTestServletContainer encodingTestServletContainer;
final HttpServletRequest httpServletRequest;

EncodingTestData(ServletRequestValues servletRequestValues, EncodingTestServletContainer encodingTestServletContainer) {
this.servletRequestValues = servletRequestValues;
this.encodingTestServletContainer = encodingTestServletContainer;
this.httpServletRequest = (HttpServletRequest) Proxy.newProxyInstance(getClass().getClassLoader(),
new Class[]{HttpServletRequest.class}, new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
return servletRequestValues.handle(method.getName());
}
});
}

public void test() throws ServletException, IOException {
encodingTestServletContainer.service(httpServletRequest, (HttpServletResponse) null);
}

}

static class ServletRequestValues {
final String servletPath;
final String requestUri;
final String contextPath;

ServletRequestValues(String contextPath, String servletPath, String requestUri) {
this.servletPath = servletPath;
this.requestUri = requestUri;
this.contextPath = contextPath;
}

Object handle(String name) {
switch (name) {
case "getServletPath":
return servletPath;
case "getRequestURI":
return requestUri;
case "getRequestURL":
return new StringBuffer(requestUri);
case "getContextPath":
return contextPath;
default:
return null;
}
}
}

static class EncodingTestServletContainer extends ServletContainer {
final String baseUri;
final String requestUri;

EncodingTestServletContainer(String baseUri, String requestUri) {
this.baseUri = baseUri;
this.requestUri = requestUri;
}

@Override
public Value<Integer> service(URI baseUri, URI requestUri, HttpServletRequest request, HttpServletResponse response) {
Assert.assertEquals(this.baseUri, baseUri.toASCIIString());
Assert.assertEquals(this.requestUri, requestUri.toASCIIString());
return Values.of(0);
}

//Update visibility
public void service(final HttpServletRequest request, final HttpServletResponse response)
throws ServletException, IOException {
super.service(request, response);
}
};
}
75 changes: 75 additions & 0 deletions tests/integration/jersey-4949/pom.xml
@@ -0,0 +1,75 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
Copyright (c) 2022 Oracle and/or its affiliates. All rights reserved.
This program and the accompanying materials are made available under the
terms of the Eclipse Public License v. 2.0, which is available at
http://www.eclipse.org/legal/epl-2.0.
This Source Code may also be made available under the following Secondary
Licenses when the conditions for such availability set forth in the
Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
version 2 with the GNU Classpath Exception, which is available at
https://www.gnu.org/software/classpath/license.html.
SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
-->

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>

<parent>
<groupId>org.glassfish.jersey.tests.integration</groupId>
<artifactId>project</artifactId>
<version>2.36-SNAPSHOT</version>
</parent>

<artifactId>jersey-4949</artifactId>
<packaging>war</packaging>
<name>jersey-tests-integration-jersey-4949</name>

<description>Servlet integration test - JERSEY-4949 - Encoded Jetty Path</description>

<dependencies>
<dependency>
<groupId>org.glassfish.jersey.containers</groupId>
<artifactId>jersey-container-servlet-core</artifactId>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.test-framework.providers</groupId>
<artifactId>jersey-test-framework-provider-external</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.test-framework.providers</groupId>
<artifactId>jersey-test-framework-provider-grizzly2</artifactId>
<scope>test</scope>
</dependency>
</dependencies>

<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-failsafe-plugin</artifactId>
</plugin>
<plugin>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-maven-plugin</artifactId>
<configuration>
<scan>10</scan>
<webApp>
<contextPath>/c ntext</contextPath>
</webApp>
</configuration>
</plugin>
</plugins>
</build>

</project>
@@ -0,0 +1,41 @@
/*
* Copyright (c) 2022 Oracle and/or its affiliates. All rights reserved.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0, which is available at
* http://www.eclipse.org/legal/epl-2.0.
*
* This Source Code may also be made available under the following Secondary
* Licenses when the conditions for such availability set forth in the
* Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
* version 2 with the GNU Classpath Exception, which is available at
* https://www.gnu.org/software/classpath/license.html.
*
* SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
*/

package org.glassfish.jersey.tests.integration.jersey4949;

import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.UriInfo;

/**
* Test resource.
*/
@Path("/")
public class Issue4949Resource {
public static final String PATH = "0.0.2%20-%20Market%20Data%20Import";
@GET
@Path(PATH)
public String get(@Context UriInfo uriInfo) {
return uriInfo.getRequestUri().toASCIIString();
}

@GET
@Path("echo")
public String echo(@Context UriInfo uriInfo) {
return uriInfo.getRequestUri().toASCIIString();
}
}
@@ -0,0 +1,29 @@
/*
* Copyright (c) 2022 Oracle and/or its affiliates. All rights reserved.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0, which is available at
* http://www.eclipse.org/legal/epl-2.0.
*
* This Source Code may also be made available under the following Secondary
* Licenses when the conditions for such availability set forth in the
* Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
* version 2 with the GNU Classpath Exception, which is available at
* https://www.gnu.org/software/classpath/license.html.
*
* SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
*/

package org.glassfish.jersey.tests.integration.jersey4949;

import org.glassfish.jersey.server.ResourceConfig;

/**
* JAX-RS application for the JERSEY-4949 reproducer test.
*/
public class Jersey4949 extends ResourceConfig {

public Jersey4949() {
register(Issue4949Resource.class);
}
}
35 changes: 35 additions & 0 deletions tests/integration/jersey-4949/src/main/webapp/WEB-INF/web.xml
@@ -0,0 +1,35 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
Copyright (c) 2022 Oracle and/or its affiliates. All rights reserved.
This program and the accompanying materials are made available under the
terms of the Eclipse Public License v. 2.0, which is available at
http://www.eclipse.org/legal/epl-2.0.
This Source Code may also be made available under the following Secondary
Licenses when the conditions for such availability set forth in the
Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
version 2 with the GNU Classpath Exception, which is available at
https://www.gnu.org/software/classpath/license.html.
SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
-->

<web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
<servlet>
<servlet-name>jersey4949Servlet</servlet-name>
<servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>
<init-param>
<param-name>javax.ws.rs.Application</param-name>
<param-value>org.glassfish.jersey.tests.integration.jersey4949.Jersey4949</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>jersey4949Servlet</servlet-name>
<url-pattern>/A B/*</url-pattern>
</servlet-mapping>
</web-app>

0 comments on commit 2703ee5

Please sign in to comment.