1 package com.atlassian.gzipfilter;
2
3 import java.io.File;
4 import java.io.IOException;
5
6 import javax.servlet.FilterChain;
7 import javax.servlet.FilterConfig;
8 import javax.servlet.ServletContext;
9 import javax.servlet.ServletException;
10 import javax.servlet.ServletRequest;
11 import javax.servlet.ServletResponse;
12 import javax.servlet.http.HttpServletRequest;
13 import javax.servlet.http.HttpServletResponse;
14
15 import com.atlassian.gzipfilter.integration.GzipFilterIntegration;
16 import com.atlassian.gzipfilter.selector.GzipCompatibilitySelector;
17 import com.atlassian.gzipfilter.selector.GzipCompatibilitySelectorFactory;
18 import com.atlassian.gzipfilter.selector.NoGzipCompatibilitySelector;
19 import com.atlassian.gzipfilter.selector.UserAgentBasedGzipSelectorFactory;
20
21 import org.slf4j.Logger;
22 import org.slf4j.LoggerFactory;
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41 public class GzipFilter extends AbstractFilter
42 {
43 private static final Logger log = LoggerFactory.getLogger(GzipFilter.class);
44 private static final String ALREADY_FILTERED = GzipFilter.class.getName() + "_already_filtered";
45
46 private static final GzipCompatibilitySelector NO_GZIP_SELECTOR = new NoGzipCompatibilitySelector();
47
48 private GzipCompatibilitySelectorFactory factory;
49 private final GzipFilterIntegration integration;
50 private FilterConfig filterConfig;
51
52 protected static final String LEGACY_INIT_PARAM = "urlrewrite.configfile";
53
54 protected static final String LEGACY_CONFIG_FILE = "urlrewrite-gzip.xml";
55
56 public GzipFilter(GzipFilterIntegration integration)
57 {
58 this.integration = integration;
59 }
60
61 public void init(FilterConfig filterConfig) throws ServletException
62 {
63
64 if (filterConfig.getInitParameter(LEGACY_INIT_PARAM) != null)
65 {
66 throw new IllegalArgumentException("Url rewrite is no longer used in gzip filter, "
67 + "you provided " + LEGACY_INIT_PARAM + " as init param");
68 }
69
70 final ServletContext servletContext = filterConfig.getServletContext();
71 if (servletContext != null)
72 {
73 final String path = servletContext.getRealPath("/WEB-INF/" + LEGACY_CONFIG_FILE);
74 if (new File(path).exists())
75 {
76 throw new IllegalArgumentException("Url rewrite is no longer used in gzip filter, "
77 + "but you have " + LEGACY_CONFIG_FILE + " in web-inf directory");
78 }
79
80 }
81
82 this.filterConfig = filterConfig;
83 this.factory = new UserAgentBasedGzipSelectorFactory(filterConfig);
84 super.init(filterConfig);
85 }
86
87 public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain)
88 throws IOException, ServletException
89 {
90 if (req.getAttribute(ALREADY_FILTERED) == null)
91 {
92 doFilterInternal(req, res, chain);
93 }
94 else
95 {
96 chain.doFilter(req, res);
97 }
98 }
99
100 private void doFilterInternal(ServletRequest req, ServletResponse res, FilterChain chain)
101 throws IOException, ServletException
102 {
103 req.setAttribute(ALREADY_FILTERED, Boolean.TRUE);
104
105 if (req instanceof HttpServletRequest && integration.useGzip() && isTopLevelRequest(req))
106 {
107 HttpServletRequest request = (HttpServletRequest) req;
108 HttpServletResponse response = (HttpServletResponse) res;
109 GzipCompatibilitySelector selector = getCompatibilitySelector(request);
110 if (selector.shouldGzip())
111 {
112 log.debug("GZIP supported, compressing.");
113
114 SelectingResponseWrapper wrappedResponse = new SelectingResponseWrapper(response, selector, integration.getResponseEncoding(request));
115 chain.doFilter(req, wrappedResponse);
116 wrappedResponse.finishResponse();
117 return;
118 }
119 }
120
121 chain.doFilter(req, res);
122 }
123
124 private GzipCompatibilitySelector getCompatibilitySelector(HttpServletRequest request)
125 {
126 String acceptEncodingHeader = request.getHeader("accept-encoding");
127 if (acceptEncodingHeader == null || acceptEncodingHeader.indexOf("gzip") == -1)
128 {
129 return NO_GZIP_SELECTOR;
130 }
131
132 return getFactory().getSelector(filterConfig, request);
133 }
134
135 protected GzipCompatibilitySelectorFactory getFactory()
136 {
137 return factory;
138 }
139
140 private boolean isTopLevelRequest(ServletRequest request)
141 {
142 return request.getAttribute("javax.servlet.include.servlet_path") == null;
143 }
144
145 }