diff --git a/scm-core/src/main/java/sonia/scm/filter/GZipFilter.java b/scm-core/src/main/java/sonia/scm/filter/GZipFilter.java deleted file mode 100644 index 49fa8ebebf..0000000000 --- a/scm-core/src/main/java/sonia/scm/filter/GZipFilter.java +++ /dev/null @@ -1,125 +0,0 @@ -/** - * Copyright (c) 2010, Sebastian Sdorra - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. Neither the name of SCM-Manager; nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * http://bitbucket.org/sdorra/scm-manager - * - */ - - - -package sonia.scm.filter; - -//~--- non-JDK imports -------------------------------------------------------- - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import sonia.scm.Priority; -import sonia.scm.util.WebUtil; -import sonia.scm.web.filter.HttpFilter; - -//~--- JDK imports ------------------------------------------------------------ - -import java.io.IOException; - -import javax.servlet.FilterChain; -import javax.servlet.ServletException; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; - -/** - * Filter for gzip encoding. - * - * @author Sebastian Sdorra - * @since 1.15 - */ -@Priority(Filters.PRIORITY_PRE_BASEURL) -@WebElement(value = Filters.PATTERN_RESOURCE_REGEX, regex = true) -public class GZipFilter extends HttpFilter -{ - - /** - * the logger for GZipFilter - */ - private static final Logger logger = - LoggerFactory.getLogger(GZipFilter.class); - - //~--- get methods ---------------------------------------------------------- - - /** - * Return the configuration for the gzip filter. - * - * - * @return gzip filter configuration - */ - public GZipFilterConfig getConfig() - { - return config; - } - - //~--- methods -------------------------------------------------------------- - - /** - * Encodes the response, if the request has support for gzip encoding. - * - * - * @param request http request - * @param response http response - * @param chain filter chain - * - * @throws IOException - * @throws ServletException - */ - @Override - protected void doFilter(HttpServletRequest request, - HttpServletResponse response, FilterChain chain) - throws IOException, ServletException - { - if (WebUtil.isGzipSupported(request)) - { - if (logger.isTraceEnabled()) - { - logger.trace("compress output with gzip"); - } - - GZipResponseWrapper wrappedResponse = new GZipResponseWrapper(response, - config); - - chain.doFilter(request, wrappedResponse); - wrappedResponse.finishResponse(); - } - else - { - chain.doFilter(request, response); - } - } - - //~--- fields --------------------------------------------------------------- - - /** gzip filter configuration */ - private GZipFilterConfig config = new GZipFilterConfig(); -} diff --git a/scm-core/src/main/java/sonia/scm/filter/GZipResponseFilter.java b/scm-core/src/main/java/sonia/scm/filter/GZipResponseFilter.java new file mode 100644 index 0000000000..1fa525d4fd --- /dev/null +++ b/scm-core/src/main/java/sonia/scm/filter/GZipResponseFilter.java @@ -0,0 +1,24 @@ +package sonia.scm.filter; + +import lombok.extern.slf4j.Slf4j; +import sonia.scm.util.WebUtil; + +import javax.ws.rs.container.ContainerRequestContext; +import javax.ws.rs.container.ContainerResponseContext; +import javax.ws.rs.container.ContainerResponseFilter; +import javax.ws.rs.ext.Provider; +import java.io.IOException; +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); + } + } +} diff --git a/scm-core/src/main/java/sonia/scm/util/WebUtil.java b/scm-core/src/main/java/sonia/scm/util/WebUtil.java index 2fc0876668..a9337b0598 100644 --- a/scm-core/src/main/java/sonia/scm/util/WebUtil.java +++ b/scm-core/src/main/java/sonia/scm/util/WebUtil.java @@ -49,6 +49,7 @@ import java.text.SimpleDateFormat; import java.util.Date; import java.util.Locale; import java.util.TimeZone; +import java.util.function.Function; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; @@ -266,7 +267,12 @@ public final class WebUtil */ public static boolean isGzipSupported(HttpServletRequest request) { - String enc = request.getHeader(HEADER_ACCEPTENCODING); + return isGzipSupported(request::getHeader); + } + + public static boolean isGzipSupported(Function headerResolver) + { + String enc = headerResolver.apply(HEADER_ACCEPTENCODING); return (enc != null) && enc.contains("gzip"); } diff --git a/scm-plugins/scm-svn-plugin/src/main/java/sonia/scm/web/SvnGZipFilter.java b/scm-plugins/scm-svn-plugin/src/main/java/sonia/scm/web/SvnGZipFilter.java index 7cc78180ff..4352299ed5 100644 --- a/scm-plugins/scm-svn-plugin/src/main/java/sonia/scm/web/SvnGZipFilter.java +++ b/scm-plugins/scm-svn-plugin/src/main/java/sonia/scm/web/SvnGZipFilter.java @@ -32,122 +32,45 @@ package sonia.scm.web; -//~--- non-JDK imports -------------------------------------------------------- - import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import sonia.scm.filter.GZipFilter; +import sonia.scm.filter.GZipFilterConfig; +import sonia.scm.filter.GZipResponseWrapper; import sonia.scm.repository.Repository; import sonia.scm.repository.SvnRepositoryHandler; import sonia.scm.repository.spi.ScmProviderHttpServlet; +import sonia.scm.util.WebUtil; -import javax.servlet.FilterChain; -import javax.servlet.FilterConfig; import javax.servlet.ServletConfig; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; -//~--- JDK imports ------------------------------------------------------------ - -/** - * - * @author Sebastian Sdorra - */ -public class SvnGZipFilter extends GZipFilter implements ScmProviderHttpServlet -{ +class SvnGZipFilter implements ScmProviderHttpServlet { private static final Logger logger = LoggerFactory.getLogger(SvnGZipFilter.class); private final SvnRepositoryHandler handler; private final ScmProviderHttpServlet delegate; - //~--- constructors --------------------------------------------------------- + private GZipFilterConfig config = new GZipFilterConfig(); - /** - * Constructs ... - * - * - * @param handler - */ - public SvnGZipFilter(SvnRepositoryHandler handler, ScmProviderHttpServlet delegate) - { + SvnGZipFilter(SvnRepositoryHandler handler, ScmProviderHttpServlet delegate) { this.handler = handler; this.delegate = delegate; - } - - //~--- methods -------------------------------------------------------------- - - /** - * Method description - * - * - * @param filterConfig - * - * @throws ServletException - */ - @Override - public void init(FilterConfig filterConfig) throws ServletException - { - super.init(filterConfig); - getConfig().setBufferResponse(false); - } - - /** - * Method description - * - * - * @param request - * @param response - * @param chain - * - * @throws IOException - * @throws ServletException - */ - @Override - protected void doFilter(HttpServletRequest request, - HttpServletResponse response, FilterChain chain) - throws IOException, ServletException - { - if (handler.getConfig().isEnabledGZip()) - { - if (logger.isTraceEnabled()) - { - logger.trace("encode svn request with gzip"); - } - - super.doFilter(request, response, chain); - } - else - { - if (logger.isTraceEnabled()) - { - logger.trace("skip gzip encoding"); - } - - chain.doFilter(request, response); - } + config.setBufferResponse(false); } @Override public void service(HttpServletRequest request, HttpServletResponse response, Repository repository) throws ServletException, IOException { - if (handler.getConfig().isEnabledGZip()) - { - if (logger.isTraceEnabled()) - { - logger.trace("encode svn request with gzip"); - } - - super.doFilter(request, response, (servletRequest, servletResponse) -> delegate.service((HttpServletRequest) servletRequest, (HttpServletResponse) servletResponse, repository)); - } - else - { - if (logger.isTraceEnabled()) - { - logger.trace("skip gzip encoding"); - } - + if (handler.getConfig().isEnabledGZip() && WebUtil.isGzipSupported(request)) { + logger.trace("compress svn response with gzip"); + GZipResponseWrapper wrappedResponse = new GZipResponseWrapper(response, config); + delegate.service(request, wrappedResponse, repository); + wrappedResponse.finishResponse(); + } else { + logger.trace("skip gzip encoding"); delegate.service(request, response, repository); } } diff --git a/scm-webapp/src/main/java/sonia/scm/WebResourceServlet.java b/scm-webapp/src/main/java/sonia/scm/WebResourceServlet.java index 059c990718..6b4a29961d 100644 --- a/scm-webapp/src/main/java/sonia/scm/WebResourceServlet.java +++ b/scm-webapp/src/main/java/sonia/scm/WebResourceServlet.java @@ -58,8 +58,10 @@ public class WebResourceServlet extends HttpServlet { LOG.trace("try to load {}", uri); URL url = webResourceLoader.getResource(uri); if (url != null) { + LOG.trace("found {} -- serve as resource {}", uri, url); serveResource(request, response, url); } else { + LOG.trace("could not find {} -- dispatch", uri); dispatch(request, response, uri); } } @@ -79,6 +81,7 @@ public class WebResourceServlet extends HttpServlet { private void serveResource(HttpServletRequest request, HttpServletResponse response, URL url) { try { + LOG.debug("using sender to serve {}", request.getRequestURI()); sender.resource(url).send(request, response); } catch (IOException ex) { LOG.warn("failed to serve resource: {}", url);