package io.dropwizard.jetty; import com.google.common.io.ByteStreams; import com.google.common.io.CharStreams; import com.google.common.io.Resources; import com.google.common.net.HttpHeaders; import com.google.common.net.MediaType; import org.eclipse.jetty.http.HttpHeader; import org.eclipse.jetty.http.HttpTester; import org.eclipse.jetty.servlet.ServletTester; import org.junit.After; import org.junit.Before; import org.junit.Test; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.nio.charset.StandardCharsets; import java.util.zip.DeflaterOutputStream; import java.util.zip.GZIPInputStream; import java.util.zip.GZIPOutputStream; import java.util.zip.Deflater; import static org.assertj.core.api.Assertions.assertThat; public class BiDiGzipHandlerTest { private static final String PLAIN_TEXT_UTF_8 = MediaType.PLAIN_TEXT_UTF_8.toString().replace(" ", ""); private final BiDiGzipHandler gzipHandler = new BiDiGzipHandler(); private final ServletTester servletTester = new ServletTester(); private final HttpTester.Request request = HttpTester.newRequest(); @Before public void setUp() throws Exception { request.setHeader(HttpHeaders.HOST, "localhost"); request.setHeader("Connection", "close"); gzipHandler.setExcludedAgentPatterns(); gzipHandler.addIncludedMethods("POST"); servletTester.addServlet(BannerServlet.class, "/banner"); servletTester.getContext().setGzipHandler(gzipHandler); servletTester.start(); } @After public void tearDown() throws Exception { servletTester.stop(); } @Test public void testCompressResponse() throws Exception { request.setMethod("GET"); request.setURI("/banner"); request.setHeader(HttpHeaders.ACCEPT_ENCODING, "gzip"); HttpTester.Response response = HttpTester.parseResponse(servletTester.getResponses(request.generate())); assertThat(response.getStatus()).isEqualTo(200); assertThat(response.get(HttpHeader.CONTENT_ENCODING)).isEqualTo("gzip"); assertThat(response.get(HttpHeader.VARY)).isEqualTo(HttpHeaders.ACCEPT_ENCODING); assertThat(response.get(HttpHeader.CONTENT_TYPE)).isEqualToIgnoringCase(PLAIN_TEXT_UTF_8); try (GZIPInputStream is = new GZIPInputStream(new ByteArrayInputStream(response.getContentBytes()))) { assertThat(ByteStreams.toByteArray(is)).isEqualTo( Resources.toByteArray(Resources.getResource("assets/banner.txt"))); } } @Test public void testDecompressRequest() throws Exception { request.setMethod("POST"); request.setURI("/banner"); request.setHeader(HttpHeaders.CONTENT_ENCODING, "gzip"); request.setHeader(HttpHeaders.CONTENT_TYPE, PLAIN_TEXT_UTF_8); ByteArrayOutputStream baos = new ByteArrayOutputStream(); try (GZIPOutputStream gz = new GZIPOutputStream(baos)) { Resources.copy(Resources.getResource("assets/new-banner.txt"), gz); } request.setContent(baos.toByteArray()); HttpTester.Response response = HttpTester.parseResponse(servletTester.getResponses(request.generate())); assertThat(response.getStatus()).isEqualTo(200); assertThat(response.getContent()).isEqualTo("Banner has been updated"); } @Test public void testDecompressDeflateRequestGzipIncompatible() throws Exception { request.setMethod("POST"); request.setURI("/banner"); request.setHeader(HttpHeaders.CONTENT_ENCODING, "deflate"); request.setHeader(HttpHeaders.CONTENT_TYPE, PLAIN_TEXT_UTF_8); ByteArrayOutputStream baos = new ByteArrayOutputStream(); try (DeflaterOutputStream deflate = new DeflaterOutputStream(baos)) { Resources.copy(Resources.getResource("assets/new-banner.txt"), deflate); } request.setContent(baos.toByteArray()); gzipHandler.setInflateNoWrap(false); HttpTester.Response response = HttpTester.parseResponse(servletTester.getResponses(request.generate())); assertThat(response.getStatus()).isEqualTo(200); assertThat(response.getContent()).isEqualTo("Banner has been updated"); } @Test public void testDecompressDeflateRequestGzipCompatible() throws Exception { request.setMethod("POST"); request.setURI("/banner"); request.setHeader(HttpHeaders.CONTENT_ENCODING, "deflate"); request.setHeader(HttpHeaders.CONTENT_TYPE, PLAIN_TEXT_UTF_8); ByteArrayOutputStream baos = new ByteArrayOutputStream(); try (DeflaterOutputStream deflate = new DeflaterOutputStream(baos, new Deflater(-1, true))) { Resources.copy(Resources.getResource("assets/new-banner.txt"), deflate); } request.setContent(baos.toByteArray()); HttpTester.Response response = HttpTester.parseResponse(servletTester.getResponses(request.generate())); assertThat(response.getStatus()).isEqualTo(200); assertThat(response.getContent()).isEqualTo("Banner has been updated"); } public static class BannerServlet extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { resp.setCharacterEncoding(StandardCharsets.UTF_8.toString()); resp.setContentType(PLAIN_TEXT_UTF_8); Resources.asCharSource(Resources.getResource("assets/banner.txt"), StandardCharsets.UTF_8) .copyTo(resp.getWriter()); } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { assertThat(req.getHeader(HttpHeaders.CONTENT_TYPE)).isEqualToIgnoringCase(PLAIN_TEXT_UTF_8); assertThat(req.getHeader(HttpHeaders.CONTENT_ENCODING)).isNull(); assertThat(CharStreams.toString(req.getReader())).isEqualTo( Resources.toString(Resources.getResource("assets/new-banner.txt"), StandardCharsets.UTF_8)); resp.setContentType(PLAIN_TEXT_UTF_8); resp.getWriter().write("Banner has been updated"); } } }