1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34 package info.magnolia.module.cache.filter;
35
36 import info.magnolia.cms.filters.OncePerRequestAbstractMgnlFilter;
37 import info.magnolia.cms.util.RequestHeaderUtil;
38 import info.magnolia.module.cache.util.GZipUtil;
39
40 import java.io.IOException;
41
42 import javax.servlet.FilterChain;
43 import javax.servlet.ServletException;
44 import javax.servlet.ServletOutputStream;
45 import javax.servlet.http.HttpServletRequest;
46 import javax.servlet.http.HttpServletResponse;
47
48
49
50
51
52
53
54
55
56
57
58 public class GZipFilter extends OncePerRequestAbstractMgnlFilter {
59
60 @Override
61 public boolean bypasses(HttpServletRequest request) {
62 return !GZipUtil.isAcceptsGzip(request) || super.bypasses(request);
63 }
64
65 @Override
66 public void doFilter(HttpServletRequest request, final HttpServletResponse response, FilterChain chain) throws IOException, ServletException {
67
68
69
70
71 final GZipCacheResponseWrapper responseWrapper = new GZipCacheResponseWrapper(response, CacheResponseWrapper.DEFAULT_THRESHOLD, true);
72
73 chain.doFilter(request, responseWrapper);
74
75
76 responseWrapper.flush();
77
78
79 if (!responseWrapper.isGzipResponseDetected()) {
80 byte[] array = responseWrapper.getBufferedContent();
81
82
83 int statusCode = responseWrapper.getStatus();
84 if (statusCode == HttpServletResponse.SC_OK && !GZipUtil.isGZipped(array)) {
85 responseWrapper.replayHeadersAndStatus(response);
86
87 RequestHeaderUtil.addAndVerifyHeader(response, "Content-Encoding", "gzip");
88 RequestHeaderUtil.addAndVerifyHeader(response, "Vary", "Accept-Encoding");
89
90 array = GZipUtil.gzip(array);
91 response.setContentLength(array.length);
92 if (array.length > 0) {
93 response.getOutputStream().write(array);
94 }
95 }
96 else {
97 responseWrapper.replay(response);
98 }
99
100 response.flushBuffer();
101 }
102 }
103
104
105
106
107
108
109 private static final class GZipCacheResponseWrapper extends CacheResponseWrapper {
110
111 private final HttpServletResponse response;
112
113 private boolean gzipResponseDetected;
114
115 private ServletOutputStream deferredOutputStream = new DeferredServletOutputStream();
116
117 public boolean isGzipResponseDetected() {
118 return gzipResponseDetected;
119 }
120
121 private GZipCacheResponseWrapper(HttpServletResponse response, int threshold, boolean serveIfThresholdReached) {
122 super(response, threshold, serveIfThresholdReached, new GzipThresholdingCacheOutputStream(threshold));
123 this.response = response;
124 }
125
126 @Override
127 public void addHeader(String name, String value) {
128 if (name.equals("Content-Encoding")) {
129 gzipResponseDetected = true;
130 }
131 super.addHeader(name, value);
132 }
133
134 private ServletOutputStream getWrappedOutputStream() throws IOException {
135 return super.getOutputStream();
136 }
137
138 @Override
139 public ServletOutputStream getOutputStream() {
140 return deferredOutputStream;
141 }
142
143
144
145
146 private final class DeferredServletOutputStream extends ServletOutputStream {
147
148 private ServletOutputStream stream;
149
150 @Override
151 public void write(int b) throws IOException {
152 getStream().write(b);
153 }
154
155 @Override
156 public void write(byte[] b) throws IOException {
157 getStream().write(b);
158 }
159
160 @Override
161 public void write(byte[] b, int off, int len) throws IOException {
162 getStream().write(b, off, len);
163 }
164
165 private ServletOutputStream getStream() throws IOException {
166 if (stream == null) {
167 if (gzipResponseDetected) {
168 replayHeadersAndStatus(response);
169 stream = response.getOutputStream();
170 } else {
171 stream = getWrappedOutputStream();
172 }
173 }
174 return stream;
175 }
176 }
177 }
178
179 private final static class GzipThresholdingCacheOutputStream extends AbstractThresholdingCacheOutputStream {
180
181 public GzipThresholdingCacheOutputStream(int threshold) {
182 super(threshold);
183 }
184
185 @Override
186 protected void thresholdReached() throws IOException {
187
188 }
189 }
190
191 }