diff --git a/jetty-http/src/test/java/org/eclipse/jetty/http/MimeTypesTest.java b/jetty-http/src/test/java/org/eclipse/jetty/http/MimeTypesTest.java index a45260f1639..362a211d03c 100644 --- a/jetty-http/src/test/java/org/eclipse/jetty/http/MimeTypesTest.java +++ b/jetty-http/src/test/java/org/eclipse/jetty/http/MimeTypesTest.java @@ -92,8 +92,8 @@ public class MimeTypesTest assertEquals(null,MimeTypes.getCharsetFromContentType("foo/bar")); assertEquals("utf-8",MimeTypes.getCharsetFromContentType("foo/bar;charset=uTf8")); assertEquals("utf-8",MimeTypes.getCharsetFromContentType("foo/bar;other=\"charset=abc\";charset=uTf8")); + assertEquals("utf-8",MimeTypes.getCharsetFromContentType("application/pdf;;; charset=UTF-8")); assertEquals("utf-8",MimeTypes.getCharsetFromContentType("text/html;charset=utf-8")); - } @Test diff --git a/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/PushCacheFilterTest.java b/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/PushCacheFilterTest.java index 9b796108397..8fccc5ae1f7 100644 --- a/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/PushCacheFilterTest.java +++ b/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/PushCacheFilterTest.java @@ -799,4 +799,90 @@ public class PushCacheFilterTest extends AbstractTest Assert.assertTrue(pushLatch.await(5, TimeUnit.SECONDS)); Assert.assertTrue(primaryResponseLatch.await(5, TimeUnit.SECONDS)); } + + @Test + public void testPOSTRequestIsNotPushed() throws Exception + { + final String primaryResource = "/primary.html"; + final String secondaryResource = "/secondary.png"; + final byte[] secondaryData = "SECONDARY".getBytes("UTF-8"); + start(new HttpServlet() + { + @Override + protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException + { + String requestURI = req.getRequestURI(); + ServletOutputStream output = resp.getOutputStream(); + if (requestURI.endsWith(primaryResource)) + output.print("PRIMARY"); + else if (requestURI.endsWith(secondaryResource)) + output.write(secondaryData); + } + }); + + final Session session = newClient(new Session.Listener.Adapter()); + + // Request for the primary and secondary resource to build the cache. + final String referrerURI = "http://localhost:" + connector.getLocalPort() + servletPath + primaryResource; + HttpFields primaryFields = new HttpFields(); + MetaData.Request primaryRequest = newRequest("GET", primaryResource, primaryFields); + final CountDownLatch warmupLatch = new CountDownLatch(1); + session.newStream(new HeadersFrame(primaryRequest, null, true), new Promise.Adapter<>(), new Stream.Listener.Adapter() + { + @Override + public void onData(Stream stream, DataFrame frame, Callback callback) + { + callback.succeeded(); + if (frame.isEndStream()) + { + // Request for the secondary resource. + HttpFields secondaryFields = new HttpFields(); + secondaryFields.put(HttpHeader.REFERER, referrerURI); + MetaData.Request secondaryRequest = newRequest("GET", secondaryResource, secondaryFields); + session.newStream(new HeadersFrame(secondaryRequest, null, true), new Promise.Adapter<>(), new Stream.Listener.Adapter() + { + @Override + public void onData(Stream stream, DataFrame frame, Callback callback) + { + callback.succeeded(); + warmupLatch.countDown(); + } + }); + } + } + }); + Assert.assertTrue(warmupLatch.await(5, TimeUnit.SECONDS)); + + // Request again the primary resource with POST, we should not get the secondary resource pushed. + primaryRequest = newRequest("POST", primaryResource, primaryFields); + final CountDownLatch primaryResponseLatch = new CountDownLatch(1); + final CountDownLatch pushLatch = new CountDownLatch(1); + session.newStream(new HeadersFrame(primaryRequest, null, true), new Promise.Adapter<>(), new Stream.Listener.Adapter() + { + @Override + public Stream.Listener onPush(Stream stream, PushPromiseFrame frame) + { + return new Adapter() + { + @Override + public void onData(Stream stream, DataFrame frame, Callback callback) + { + callback.succeeded(); + if (frame.isEndStream()) + pushLatch.countDown(); + } + }; + } + + @Override + public void onData(Stream stream, DataFrame frame, Callback callback) + { + callback.succeeded(); + if (frame.isEndStream()) + primaryResponseLatch.countDown(); + } + }); + Assert.assertTrue(primaryResponseLatch.await(5, TimeUnit.SECONDS)); + Assert.assertFalse(pushLatch.await(1, TimeUnit.SECONDS)); + } } diff --git a/jetty-servlets/src/main/java/org/eclipse/jetty/servlets/PushCacheFilter.java b/jetty-servlets/src/main/java/org/eclipse/jetty/servlets/PushCacheFilter.java index 74623f3ea1b..c97cf95b850 100644 --- a/jetty-servlets/src/main/java/org/eclipse/jetty/servlets/PushCacheFilter.java +++ b/jetty-servlets/src/main/java/org/eclipse/jetty/servlets/PushCacheFilter.java @@ -44,6 +44,7 @@ import javax.servlet.http.PushBuilder; import org.eclipse.jetty.http.HttpField; import org.eclipse.jetty.http.HttpFields; import org.eclipse.jetty.http.HttpHeader; +import org.eclipse.jetty.http.HttpMethod; import org.eclipse.jetty.http.HttpURI; import org.eclipse.jetty.http.HttpVersion; import org.eclipse.jetty.server.Request; @@ -114,17 +115,20 @@ public class PushCacheFilter implements Filter @Override public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws IOException, ServletException { - if (HttpVersion.fromString(req.getProtocol()).getVersion() < 20) + HttpServletRequest request = (HttpServletRequest)req; + + if (HttpVersion.fromString(req.getProtocol()).getVersion() < 20 || + !HttpMethod.GET.is(request.getMethod())) { chain.doFilter(req, resp); return; } long now = System.nanoTime(); - HttpServletRequest request = (HttpServletRequest)req; // Iterating over fields is more efficient than multiple gets - HttpFields fields = Request.getBaseRequest(request).getHttpFields(); + Request jettyRequest = Request.getBaseRequest(request); + HttpFields fields = jettyRequest.getHttpFields(); boolean conditional = false; String referrer = null; loop: @@ -173,7 +177,7 @@ public class PushCacheFilter implements Filter if (referredFromHere) { - if ("GET".equalsIgnoreCase(request.getMethod())) + if (HttpMethod.GET.is(request.getMethod())) { String referrerPath = referrerURI.getPath(); if (referrerPath == null) @@ -254,7 +258,7 @@ public class PushCacheFilter implements Filter // Push associated resources. if (!isPushRequest(request) && !conditional && !primaryResource._associated.isEmpty()) { - PushBuilder pushBuilder = Request.getBaseRequest(request).getPushBuilder(); + PushBuilder pushBuilder = jettyRequest.getPushBuilder(); // Breadth-first push of associated resources. Queue queue = new ArrayDeque<>();