1
2
3
4
5
6
7
8
9
10
11
12
13
14 package org.eclipse.jetty.server.handler;
15
16 import java.io.IOException;
17 import java.io.OutputStream;
18 import java.io.OutputStreamWriter;
19 import java.io.PrintWriter;
20 import java.io.UnsupportedEncodingException;
21 import java.util.HashSet;
22 import java.util.Set;
23 import java.util.StringTokenizer;
24 import java.util.zip.DeflaterOutputStream;
25 import java.util.zip.GZIPOutputStream;
26
27 import javax.servlet.ServletException;
28 import javax.servlet.http.HttpServletRequest;
29 import javax.servlet.http.HttpServletResponse;
30
31 import org.eclipse.jetty.continuation.Continuation;
32 import org.eclipse.jetty.continuation.ContinuationListener;
33 import org.eclipse.jetty.continuation.ContinuationSupport;
34 import org.eclipse.jetty.http.HttpMethods;
35 import org.eclipse.jetty.http.gzip.CompressedResponseWrapper;
36 import org.eclipse.jetty.http.gzip.AbstractCompressedStream;
37 import org.eclipse.jetty.server.Request;
38 import org.eclipse.jetty.util.log.Log;
39 import org.eclipse.jetty.util.log.Logger;
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58 public class GzipHandler extends HandlerWrapper
59 {
60 private static final Logger LOG = Log.getLogger(GzipHandler.class);
61
62 protected Set<String> _mimeTypes;
63 protected Set<String> _excluded;
64 protected int _bufferSize = 8192;
65 protected int _minGzipSize = 256;
66
67
68
69
70
71 public GzipHandler()
72 {
73 }
74
75
76
77
78
79
80
81 public Set<String> getMimeTypes()
82 {
83 return _mimeTypes;
84 }
85
86
87
88
89
90
91
92
93 public void setMimeTypes(Set<String> mimeTypes)
94 {
95 _mimeTypes = mimeTypes;
96 }
97
98
99
100
101
102
103
104
105 public void setMimeTypes(String mimeTypes)
106 {
107 if (mimeTypes != null)
108 {
109 _mimeTypes = new HashSet<String>();
110 StringTokenizer tok = new StringTokenizer(mimeTypes,",",false);
111 while (tok.hasMoreTokens())
112 {
113 _mimeTypes.add(tok.nextToken());
114 }
115 }
116 }
117
118
119
120
121
122
123
124 public Set<String> getExcluded()
125 {
126 return _excluded;
127 }
128
129
130
131
132
133
134
135
136 public void setExcluded(Set<String> excluded)
137 {
138 _excluded = excluded;
139 }
140
141
142
143
144
145
146
147
148 public void setExcluded(String excluded)
149 {
150 if (excluded != null)
151 {
152 _excluded = new HashSet<String>();
153 StringTokenizer tok = new StringTokenizer(excluded,",",false);
154 while (tok.hasMoreTokens())
155 _excluded.add(tok.nextToken());
156 }
157 }
158
159
160
161
162
163
164
165 public int getBufferSize()
166 {
167 return _bufferSize;
168 }
169
170
171
172
173
174
175
176
177 public void setBufferSize(int bufferSize)
178 {
179 _bufferSize = bufferSize;
180 }
181
182
183
184
185
186
187
188 public int getMinGzipSize()
189 {
190 return _minGzipSize;
191 }
192
193
194
195
196
197
198
199
200 public void setMinGzipSize(int minGzipSize)
201 {
202 _minGzipSize = minGzipSize;
203 }
204
205
206
207
208
209 @Override
210 public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException
211 {
212 if (_handler!=null && isStarted())
213 {
214 String ae = request.getHeader("accept-encoding");
215 if (ae != null && ae.indexOf("gzip")>=0 && !response.containsHeader("Content-Encoding")
216 && !HttpMethods.HEAD.equalsIgnoreCase(request.getMethod()))
217 {
218 if (_excluded!=null)
219 {
220 String ua = request.getHeader("User-Agent");
221 if (_excluded.contains(ua))
222 {
223 _handler.handle(target,baseRequest, request, response);
224 return;
225 }
226 }
227
228 final CompressedResponseWrapper wrappedResponse = newGzipResponseWrapper(request,response);
229
230 boolean exceptional=true;
231 try
232 {
233 _handler.handle(target, baseRequest, request, wrappedResponse);
234 exceptional=false;
235 }
236 finally
237 {
238 Continuation continuation = ContinuationSupport.getContinuation(request);
239 if (continuation.isSuspended() && continuation.isResponseWrapped())
240 {
241 continuation.addContinuationListener(new ContinuationListener()
242 {
243 public void onComplete(Continuation continuation)
244 {
245 try
246 {
247 wrappedResponse.finish();
248 }
249 catch(IOException e)
250 {
251 LOG.warn(e);
252 }
253 }
254
255 public void onTimeout(Continuation continuation)
256 {}
257 });
258 }
259 else if (exceptional && !response.isCommitted())
260 {
261 wrappedResponse.resetBuffer();
262 wrappedResponse.noCompression();
263 }
264 else
265 wrappedResponse.finish();
266 }
267 }
268 else
269 {
270 _handler.handle(target,baseRequest, request, response);
271 }
272 }
273 }
274
275
276
277
278
279
280
281
282 protected CompressedResponseWrapper newGzipResponseWrapper(HttpServletRequest request, HttpServletResponse response)
283 {
284 return new CompressedResponseWrapper(request,response)
285 {
286 {
287 super.setMimeTypes(GzipHandler.this._mimeTypes);
288 super.setBufferSize(GzipHandler.this._bufferSize);
289 super.setMinCompressSize(GzipHandler.this._minGzipSize);
290 }
291
292 @Override
293 protected AbstractCompressedStream newCompressedStream(HttpServletRequest request,HttpServletResponse response,long contentLength,int bufferSize, int minCompressSize) throws IOException
294 {
295 return new AbstractCompressedStream("gzip",request,response,contentLength,bufferSize,minCompressSize)
296 {
297 @Override
298 protected DeflaterOutputStream createStream() throws IOException
299 {
300 return new GZIPOutputStream(_response.getOutputStream(),_bufferSize);
301 }
302 };
303 }
304
305 @Override
306 protected PrintWriter newWriter(OutputStream out,String encoding) throws UnsupportedEncodingException
307 {
308 return GzipHandler.this.newWriter(out,encoding);
309 }
310 };
311 }
312
313
314
315
316
317
318
319
320
321 protected PrintWriter newWriter(OutputStream out,String encoding) throws UnsupportedEncodingException
322 {
323 return encoding==null?new PrintWriter(out):new PrintWriter(new OutputStreamWriter(out,encoding));
324 }
325 }