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
5 changes: 5 additions & 0 deletions CHANGES.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
# Version 2.1 (unreleased)

Servlet API 6.0.0 is now the minimum servlet API officially supported.
Version 5 should on a "best effort" basis.

\#259: The SameSite attribute in cookies is now preserved.

# Version 2.0 released on 2023-06-28

\#231: Added support of preserveCookiePath configuration parameter. It allows to keep cookie path unchanged in Set-Cookie server response header.
Expand Down
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,8 @@ See [CHANGES.md](CHANGES.md) for a history of changes.
Build & Installation
------------

**Java version:** The minimum Java version is 11.

Simply build the jar using "mvn package" at the command line.
The jar is built to "target/smiley-http-proxy-servlet-VERSION.jar".
You don't have to build the jar if you aren't modifying the code, since released
Expand Down
8 changes: 4 additions & 4 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@
<dependency>
<groupId>jakarta.servlet</groupId>
<artifactId>jakarta.servlet-api</artifactId>
<version>5.0.0</version>
<version>6.0.0</version><!-- 5.0 should work with caveats -->
<scope>provided</scope>
</dependency>

Expand Down Expand Up @@ -103,9 +103,9 @@
</dependency>

<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-servlet</artifactId>
<version>11.0.15</version>
<groupId>org.apache.tomcat.embed</groupId>
<artifactId>tomcat-embed-core</artifactId>
<version>10.1.54</version>
<scope>test</scope>
</dependency>
</dependencies>
Expand Down
18 changes: 18 additions & 0 deletions src/main/java/org/mitre/dsmiley/httpproxy/ProxyServlet.java
Original file line number Diff line number Diff line change
Expand Up @@ -582,10 +582,28 @@ protected void copyProxyCookie(HttpServletRequest servletRequest,
HttpServletResponse servletResponse, String headerValue) {
for (HttpCookie cookie : HttpCookie.parse(headerValue)) {
Cookie servletCookie = createProxyCookie(servletRequest, cookie);
String sameSite = parseSameSite(headerValue);
if (sameSite != null) {
try {
servletCookie.setAttribute("SameSite", sameSite); // Servlet 6.0+
} catch (NoSuchMethodError ignored) {
// SameSite not preserved on older versions (e.g. Servlet 5.0)
}
}
servletResponse.addCookie(servletCookie);
}
}

private static String parseSameSite(String headerValue) {
for (String part : headerValue.split(";")) {
String trimmed = part.trim();
if (trimmed.regionMatches(true, 0, "SameSite=", 0, 9)) {
return trimmed.substring(9).trim();
}
}
return null;
}

/**
* Creates a proxy cookie from the original cookie.
*
Expand Down
54 changes: 28 additions & 26 deletions src/test/java/org/mitre/dsmiley/httpproxy/AcceptEncodingTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -26,39 +26,39 @@
import java.nio.charset.StandardCharsets;
import java.util.Arrays;
import java.util.HashSet;
import org.apache.catalina.Context;
import org.apache.catalina.Wrapper;
import org.apache.catalina.startup.Tomcat;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.eclipse.jetty.server.Handler;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.ServerConnector;
import org.eclipse.jetty.servlet.ServletHandler;
import org.eclipse.jetty.servlet.ServletHolder;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;

public class AcceptEncodingTest {

private Server server;
private ServletHandler servletHandler;
private Tomcat tomcat;
private Context ctx;
private int serverPort;

@Before
public void setUp() throws Exception {
server = new Server(0);
servletHandler = new ServletHandler();
Handler serverHandler = servletHandler;
server.setHandler(serverHandler);
server.start();

serverPort = ((ServerConnector) server.getConnectors()[0]).getLocalPort();
tomcat = new Tomcat();
tomcat.setPort(0);
String tempDir = System.getProperty("java.io.tmpdir");
tomcat.setBaseDir( tempDir );
tomcat.getConnector();
ctx = tomcat.addContext("", tempDir );
tomcat.start();
serverPort = tomcat.getConnector().getLocalPort();
}

@After
public void tearDown() throws Exception {
server.stop();
tomcat.stop();
tomcat.destroy();
serverPort = -1;
}

Expand All @@ -78,23 +78,25 @@ public void testHandlingAcceptEncodingHeader() throws Exception {
of the client needs to be passed through as is.
*/

ServletHolder servletHolder = servletHandler.addServletWithMapping(ProxyServlet.class, "/acceptEncodingProxyHandleCompression/*");
servletHolder.setInitParameter(ProxyServlet.P_LOG, "true");
servletHolder.setInitParameter(ProxyServlet.P_TARGET_URI, String.format("http://localhost:%d/acceptEncoding/", serverPort));
servletHolder.setInitParameter(ProxyServlet.P_HANDLECOMPRESSION, Boolean.TRUE.toString());
Wrapper w1 = Tomcat.addServlet(ctx, "proxy1", ProxyServlet.class.getName());
w1.addInitParameter(ProxyServlet.P_LOG, "true");
w1.addInitParameter(ProxyServlet.P_TARGET_URI, String.format("http://localhost:%d/acceptEncoding/", serverPort));
w1.addInitParameter(ProxyServlet.P_HANDLECOMPRESSION, Boolean.TRUE.toString());
ctx.addServletMappingDecoded("/acceptEncodingProxyHandleCompression/*", "proxy1");

ServletHolder servletHolder2 = servletHandler.addServletWithMapping(ProxyServlet.class, "/acceptEncodingProxy/*");
servletHolder2.setInitParameter(ProxyServlet.P_LOG, "true");
servletHolder2.setInitParameter(ProxyServlet.P_TARGET_URI, String.format("http://localhost:%d/acceptEncoding/", serverPort));
servletHolder2.setInitParameter(ProxyServlet.P_HANDLECOMPRESSION, Boolean.FALSE.toString());
Wrapper w2 = Tomcat.addServlet(ctx, "proxy2", ProxyServlet.class.getName());
w2.addInitParameter(ProxyServlet.P_LOG, "true");
w2.addInitParameter(ProxyServlet.P_TARGET_URI, String.format("http://localhost:%d/acceptEncoding/", serverPort));
w2.addInitParameter(ProxyServlet.P_HANDLECOMPRESSION, Boolean.FALSE.toString());
ctx.addServletMappingDecoded("/acceptEncodingProxy/*", "proxy2");

ServletHolder dummyBackend = new ServletHolder(new HttpServlet() {
Tomcat.addServlet(ctx, "backend", new HttpServlet() {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
resp.getOutputStream().write(req.getHeader("Accept-Encoding").getBytes(StandardCharsets.UTF_8));
}
});
servletHandler.addServletWithMapping(dummyBackend, "/acceptEncoding/*");
ctx.addServletMappingDecoded("/acceptEncoding/*", "backend");

HttpGet queryHandleCompression = new HttpGet(String.format("http://localhost:%d/acceptEncodingProxyHandleCompression/test", serverPort));
HttpGet query = new HttpGet(String.format("http://localhost:%d/acceptEncodingProxy/test", serverPort));
Expand All @@ -106,7 +108,7 @@ protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws Se

try (CloseableHttpClient chc = HttpClientBuilder.create().disableContentCompression().build();
CloseableHttpResponse responseHandleCompression = chc.execute(queryHandleCompression);
CloseableHttpResponse response = chc.execute(query);
CloseableHttpResponse response = chc.execute(query)
) {
try (InputStream is = response.getEntity().getContent()) {
byte[] readData = readBlock(is);
Expand Down
Loading
Loading