1
2
3
4
5
6
7
8
9
10
11
12
13 package org.eclipse.jetty.servlets;
14
15 import java.io.IOException;
16 import java.io.OutputStream;
17 import java.io.OutputStreamWriter;
18 import java.io.PrintWriter;
19 import java.io.UnsupportedEncodingException;
20 import java.util.HashSet;
21 import java.util.Set;
22 import java.util.StringTokenizer;
23
24 import javax.servlet.FilterChain;
25 import javax.servlet.FilterConfig;
26 import javax.servlet.ServletException;
27 import javax.servlet.ServletRequest;
28 import javax.servlet.ServletResponse;
29 import javax.servlet.http.HttpServletRequest;
30 import javax.servlet.http.HttpServletResponse;
31
32 import org.eclipse.jetty.continuation.Continuation;
33 import org.eclipse.jetty.continuation.ContinuationListener;
34 import org.eclipse.jetty.continuation.ContinuationSupport;
35 import org.eclipse.jetty.http.HttpMethods;
36 import org.eclipse.jetty.http.gzip.GzipResponseWrapper;
37 import org.eclipse.jetty.util.log.Log;
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62 public class GzipFilter extends UserAgentFilter
63 {
64 protected Set<String> _mimeTypes;
65 protected int _bufferSize=8192;
66 protected int _minGzipSize=256;
67 protected Set<String> _excluded;
68
69
70
71
72
73 public void init(FilterConfig filterConfig) throws ServletException
74 {
75 super.init(filterConfig);
76
77 String tmp=filterConfig.getInitParameter("bufferSize");
78 if (tmp!=null)
79 _bufferSize=Integer.parseInt(tmp);
80
81 tmp=filterConfig.getInitParameter("minGzipSize");
82 if (tmp!=null)
83 _minGzipSize=Integer.parseInt(tmp);
84
85 tmp=filterConfig.getInitParameter("mimeTypes");
86 if (tmp!=null)
87 {
88 _mimeTypes=new HashSet<String>();
89 StringTokenizer tok = new StringTokenizer(tmp,",",false);
90 while (tok.hasMoreTokens())
91 _mimeTypes.add(tok.nextToken());
92 }
93
94 tmp=filterConfig.getInitParameter("excludedAgents");
95 if (tmp!=null)
96 {
97 _excluded=new HashSet<String>();
98 StringTokenizer tok = new StringTokenizer(tmp,",",false);
99 while (tok.hasMoreTokens())
100 _excluded.add(tok.nextToken());
101 }
102 }
103
104
105
106
107
108 public void destroy()
109 {
110 }
111
112
113
114
115
116 public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain)
117 throws IOException, ServletException
118 {
119 HttpServletRequest request=(HttpServletRequest)req;
120 HttpServletResponse response=(HttpServletResponse)res;
121
122 String ae = request.getHeader("accept-encoding");
123 if (ae != null && ae.indexOf("gzip")>=0 && !response.containsHeader("Content-Encoding")
124 && !HttpMethods.HEAD.equalsIgnoreCase(request.getMethod()))
125 {
126 if (_excluded!=null)
127 {
128 String ua=getUserAgent(request);
129 if (_excluded.contains(ua))
130 {
131 super.doFilter(request,response,chain);
132 return;
133 }
134 }
135
136 final GzipResponseWrapper wrappedResponse=newGzipResponseWrapper(request,response);
137
138 boolean exceptional=true;
139 try
140 {
141 super.doFilter(request,wrappedResponse,chain);
142 exceptional=false;
143 }
144 finally
145 {
146 Continuation continuation = ContinuationSupport.getContinuation(request);
147 if (continuation.isSuspended() && continuation.isResponseWrapped())
148 {
149 continuation.addContinuationListener(new ContinuationListener()
150 {
151 public void onComplete(Continuation continuation)
152 {
153 try
154 {
155 wrappedResponse.finish();
156 }
157 catch(IOException e)
158 {
159 Log.warn(e);
160 }
161 }
162
163 public void onTimeout(Continuation continuation)
164 {}
165 });
166 }
167 else if (exceptional && !response.isCommitted())
168 {
169 wrappedResponse.resetBuffer();
170 wrappedResponse.noGzip();
171 }
172 else
173 wrappedResponse.finish();
174 }
175 }
176 else
177 {
178 super.doFilter(request,response,chain);
179 }
180 }
181
182
183
184
185
186
187
188
189 protected GzipResponseWrapper newGzipResponseWrapper(HttpServletRequest request, HttpServletResponse response)
190 {
191 return new GzipResponseWrapper(request, response)
192 {
193 {
194 setMimeTypes(GzipFilter.this._mimeTypes);
195 setBufferSize(GzipFilter.this._bufferSize);
196 setMinGzipSize(GzipFilter.this._minGzipSize);
197 }
198
199 @Override
200 protected PrintWriter newWriter(OutputStream out,String encoding) throws UnsupportedEncodingException
201 {
202 return GzipFilter.this.newWriter(out,encoding);
203 }
204 };
205 }
206
207
208
209
210
211
212
213
214
215 protected PrintWriter newWriter(OutputStream out,String encoding) throws UnsupportedEncodingException
216 {
217 return encoding==null?new PrintWriter(out):new PrintWriter(new OutputStreamWriter(out,encoding));
218 }
219 }