fix gzip filter on resteasy 3.6.2

This commit is contained in:
Sebastian Sdorra
2019-01-30 13:43:29 +01:00
parent 69dda6403d
commit e5e4ae9ac9
2 changed files with 120 additions and 13 deletions

View File

@@ -1,24 +1,50 @@
package sonia.scm.filter;
import lombok.extern.slf4j.Slf4j;
import sonia.scm.util.WebUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.ws.rs.container.ContainerRequestContext;
import javax.ws.rs.container.ContainerResponseContext;
import javax.ws.rs.container.ContainerResponseFilter;
import javax.ws.rs.WebApplicationException;
import javax.ws.rs.core.HttpHeaders;
import javax.ws.rs.ext.Provider;
import javax.ws.rs.ext.WriterInterceptor;
import javax.ws.rs.ext.WriterInterceptorContext;
import java.io.IOException;
import java.io.OutputStream;
import java.util.Locale;
import java.util.zip.GZIPOutputStream;
@Provider
@Slf4j
public class GZipResponseFilter implements ContainerResponseFilter {
public void filter(ContainerRequestContext requestContext, ContainerResponseContext responseContext) throws IOException {
if (WebUtil.isGzipSupported(requestContext::getHeaderString)) {
log.trace("compress output with gzip");
GZIPOutputStream wrappedResponse = new GZIPOutputStream(responseContext.getEntityStream());
responseContext.getHeaders().add("Content-Encoding", "gzip");
responseContext.setEntityStream(wrappedResponse);
public class GZipResponseFilter implements WriterInterceptor {
private static final Logger LOG = LoggerFactory.getLogger(GZipResponseFilter.class);
@Override
public void aroundWriteTo(WriterInterceptorContext context) throws IOException, WebApplicationException {
if (isGZipSupported(context)) {
LOG.trace("compress output with gzip");
encodeWithGZip(context);
} else {
context.proceed();
}
}
private void encodeWithGZip(WriterInterceptorContext context) throws IOException {
context.getHeaders().remove(HttpHeaders.CONTENT_LENGTH);
context.getHeaders().add(HttpHeaders.CONTENT_ENCODING, "gzip");
OutputStream outputStream = context.getOutputStream();
GZIPOutputStream compressedOutputStream = new GZIPOutputStream(outputStream);
context.setOutputStream(compressedOutputStream);
try {
context.proceed();
} finally {
compressedOutputStream.finish();
context.setOutputStream(outputStream);
}
}
private boolean isGZipSupported(WriterInterceptorContext context) {
Object encoding = context.getHeaders().getFirst(HttpHeaders.ACCEPT_ENCODING);
return encoding != null && encoding.toString().toLowerCase(Locale.ENGLISH).contains("gzip");
}
}

View File

@@ -0,0 +1,81 @@
package sonia.scm.filter;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Nested;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;
import javax.ws.rs.core.HttpHeaders;
import javax.ws.rs.core.MultivaluedMap;
import javax.ws.rs.ext.WriterInterceptorContext;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.util.zip.GZIPOutputStream;
import static org.mockito.Mockito.*;
@ExtendWith(MockitoExtension.class)
class GZipResponseFilterTest {
@Mock
private WriterInterceptorContext context;
@Mock
private MultivaluedMap<String,Object> headers;
private final GZipResponseFilter filter = new GZipResponseFilter();
@BeforeEach
void setUpContext() {
when(context.getHeaders()).thenReturn(headers);
}
@Test
void shouldSkipGZipCompression() throws IOException {
when(headers.getFirst(HttpHeaders.ACCEPT_ENCODING)).thenReturn("deflate, br");
filter.aroundWriteTo(context);
verifySkipped();
}
@Test
void shouldSkipGZipCompressionWithoutAcceptEncodingHeader() throws IOException {
filter.aroundWriteTo(context);
verifySkipped();
}
private void verifySkipped() throws IOException {
verify(context, never()).getOutputStream();
verify(context).proceed();
}
@Nested
class AcceptGZipEncoding {
@BeforeEach
void setUpContext() {
when(headers.getFirst(HttpHeaders.ACCEPT_ENCODING)).thenReturn("gzip, deflate, br");
when(context.getOutputStream()).thenReturn(new ByteArrayOutputStream());
}
@Test
void shouldEncode() throws IOException {
filter.aroundWriteTo(context);
verify(headers).remove(HttpHeaders.CONTENT_LENGTH);
verify(headers).add(HttpHeaders.CONTENT_ENCODING, "gzip");
verify(context).setOutputStream(any(GZIPOutputStream.class));
verify(context, times(2)).setOutputStream(any(OutputStream.class));
}
}
}