Rietveld Code Review Tool
Help | Bug tracker | Discussion group | Source code

Side by Side Diff: src/org/adblockplus/brazil/RequestHandler.java

Issue 5697499218051072: Usage of new API, cleanups (reduced) (Closed)
Patch Set: Even more review issues fixed. Created April 28, 2014, 10:18 a.m.
Left:
Right:
Use n/p to move between diff chunks; N/P to move between comments.
Jump to:
View unified diff | Download patch
OLDNEW
1 /* 1 /*
2 * This file is part of Adblock Plus <http://adblockplus.org/>, 2 * This file is part of Adblock Plus <http://adblockplus.org/>,
3 * Copyright (C) 2006-2014 Eyeo GmbH 3 * Copyright (C) 2006-2014 Eyeo GmbH
4 * 4 *
5 * Adblock Plus is free software: you can redistribute it and/or modify 5 * Adblock Plus is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License version 3 as 6 * it under the terms of the GNU General Public License version 3 as
7 * published by the Free Software Foundation. 7 * published by the Free Software Foundation.
8 * 8 *
9 * Adblock Plus is distributed in the hope that it will be useful, 9 * Adblock Plus is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after
77 * </pre> 77 * </pre>
78 * 78 *
79 * See the description under {@link sunlabs.brazil.server.Handler#respond 79 * See the description under {@link sunlabs.brazil.server.Handler#respond
80 * respond} for a more detailed explanation. 80 * respond} for a more detailed explanation.
81 */ 81 */
82 82
83 public class RequestHandler extends BaseRequestHandler 83 public class RequestHandler extends BaseRequestHandler
84 { 84 {
85 private AdblockPlus application; 85 private AdblockPlus application;
86 private String via; 86 private String via;
87 private static Pattern RE_HTTP = Pattern.compile("^https?:"); 87 private static final Pattern RE_HTTP = Pattern.compile("^https?:");
88 88
89 @Override 89 @Override
90 public boolean init(Server server, String prefix) 90 public boolean init(final Server server, final String prefix)
91 { 91 {
92 super.init(server, prefix); 92 super.init(server, prefix);
93 93
94 application = AdblockPlus.getApplication(); 94 application = AdblockPlus.getApplication();
95 via = " " + server.hostName + ":" + server.listen.getLocalPort() + " (" + se rver.name + ")"; 95 via = " " + server.hostName + ":" + server.listen.getLocalPort() + " (" + se rver.name + ")";
96 96
97 return true; 97 return true;
98 } 98 }
99 99
100 @Override 100 @Override
101 public boolean respond(Request request) throws IOException 101 public boolean respond(final Request request) throws IOException
102 { 102 {
103 boolean block = false; 103 boolean block = false;
104 104
105 try 105 try
106 { 106 {
107 block = application.matches(request.url, request.query, request.getRequest Header("referer"), request.getRequestHeader("accept")); 107 block = application.matches(request.url, request.query, request.getRequest Header("referer"), request.getRequestHeader("accept"));
108 } 108 }
109 catch (Exception e) 109 catch (final Exception e)
110 { 110 {
111 Log.e(prefix, "Filter error", e); 111 Log.e(prefix, "Filter error", e);
112 } 112 }
113 113
114 request.log(Server.LOG_LOG, prefix, block + ": " + request.url); 114 request.log(Server.LOG_LOG, prefix, block + ": " + request.url);
115 115
116 int count = request.server.requestCount; 116 int count = request.server.requestCount;
117 if (shouldLogHeaders) 117 if (shouldLogHeaders)
118 { 118 {
119 System.err.println(dumpHeaders(count, request, request.headers, true)); 119 System.err.println(dumpHeaders(count, request, request.headers, true));
(...skipping 15 matching lines...) Expand all
135 135
136 if ((request.query != null) && (request.query.length() > 0)) 136 if ((request.query != null) && (request.query.length() > 0))
137 { 137 {
138 url += "?" + request.query; 138 url += "?" + request.query;
139 } 139 }
140 140
141 /* 141 /*
142 * "Proxy-Connection" may be used (instead of just "Connection") 142 * "Proxy-Connection" may be used (instead of just "Connection")
143 * to keep alive a connection between a client and this proxy. 143 * to keep alive a connection between a client and this proxy.
144 */ 144 */
145 String pc = request.headers.get("Proxy-Connection"); 145 final String pc = request.headers.get("Proxy-Connection");
146 if (pc != null) 146 if (pc != null)
147 { 147 {
148 request.connectionHeader = "Proxy-Connection"; 148 request.connectionHeader = "Proxy-Connection";
149 request.keepAlive = pc.equalsIgnoreCase("Keep-Alive"); 149 request.keepAlive = pc.equalsIgnoreCase("Keep-Alive");
150 } 150 }
151 151
152 HttpRequest.removePointToPointHeaders(request.headers, false); 152 HttpRequest.removePointToPointHeaders(request.headers, false);
153 153
154 HttpRequest target = new HttpRequest(url); 154 final HttpRequest target = new HttpRequest(url);
155 try 155 try
156 { 156 {
157 target.setMethod(request.method); 157 target.setMethod(request.method);
158 request.headers.copyTo(target.requestHeaders); 158 request.headers.copyTo(target.requestHeaders);
159 159
160 if (proxyHost != null) 160 if (proxyHost != null)
161 { 161 {
162 target.setProxy(proxyHost, proxyPort); 162 target.setProxy(proxyHost, proxyPort);
163 if (auth != null) 163 if (auth != null)
164 { 164 {
165 target.requestHeaders.add("Proxy-Authorization", auth); 165 target.requestHeaders.add("Proxy-Authorization", auth);
166 } 166 }
167 } 167 }
168 168
169 if (request.postData != null) 169 if (request.postData != null)
170 { 170 {
171 OutputStream out = target.getOutputStream(); 171 final OutputStream out = target.getOutputStream();
172 out.write(request.postData); 172 out.write(request.postData);
173 out.close(); 173 out.close();
174 } 174 }
175 else 175 else
176 { 176 {
177 target.setHttpInputStream(request.in); 177 target.setHttpInputStream(request.in);
178 } 178 }
179 target.connect(); 179 target.connect();
180 180
181 if (shouldLogHeaders) 181 if (shouldLogHeaders)
182 { 182 {
183 System.err.println(" " + target.status + "\n" + dumpHeaders(count, request, target.responseHeaders, false)); 183 System.err.println(" " + target.status + "\n" + dumpHeaders(count, request, target.responseHeaders, false));
184 } 184 }
185 HttpRequest.removePointToPointHeaders(target.responseHeaders, true); 185 HttpRequest.removePointToPointHeaders(target.responseHeaders, true);
186 186
187 request.setStatus(target.getResponseCode()); 187 request.setStatus(target.getResponseCode());
188 target.responseHeaders.copyTo(request.responseHeaders); 188 target.responseHeaders.copyTo(request.responseHeaders);
189 try 189 try
190 { 190 {
191 request.responseHeaders.add("Via", target.status.substring(0, 8) + via); 191 request.responseHeaders.add("Via", target.status.substring(0, 8) + via);
192 } 192 }
193 catch (StringIndexOutOfBoundsException e) 193 catch (final StringIndexOutOfBoundsException e)
194 { 194 {
195 request.responseHeaders.add("Via", via); 195 request.responseHeaders.add("Via", via);
196 } 196 }
197 197
198 // Detect if we need to add ElemHide filters 198 // Detect if we need to add ElemHide filters
199 String type = request.responseHeaders.get("Content-Type"); 199 final String type = request.responseHeaders.get("Content-Type");
200 200
201 String[] selectors = null; 201 String[] selectors = null;
202 if (type != null && type.toLowerCase().startsWith("text/html")) 202 if (type != null && type.toLowerCase().startsWith("text/html"))
203 { 203 {
204 String reqHost = ""; 204 String reqHost = "";
205 205
206 try 206 try
207 { 207 {
208 reqHost = (new URL(request.url)).getHost(); 208 reqHost = (new URL(request.url)).getHost();
209 } 209 }
210 catch (MalformedURLException e) 210 catch (final MalformedURLException e)
211 { 211 {
212 // We are transparent, it's not our deal if it's malformed. 212 // We are transparent, it's not our deal if it's malformed.
213 } 213 }
214 214
215 selectors = application.getSelectorsForDomain(reqHost); 215 selectors = application.getSelectorsForDomain(reqHost);
216 } 216 }
217 // If no filters are applicable just pass through the response 217 // If no filters are applicable just pass through the response
218 if (selectors == null || target.getResponseCode() != 200) 218 if (selectors == null || target.getResponseCode() != 200)
219 { 219 {
220 int contentLength = target.getContentLength(); 220 final int contentLength = target.getContentLength();
221 if (contentLength == 0) 221 if (contentLength == 0)
222 { 222 {
223 // we do not use request.sendResponse to avoid arbitrary 223 // we do not use request.sendResponse to avoid arbitrary
224 // 200 -> 204 response code conversion 224 // 200 -> 204 response code conversion
225 request.sendHeaders(-1, null, -1); 225 request.sendHeaders(-1, null, -1);
226 } 226 }
227 else 227 else
228 { 228 {
229 request.sendResponse(target.getInputStream(), contentLength, null, -1) ; 229 request.sendResponse(target.getInputStream(), contentLength, null, -1) ;
230 } 230 }
231 } 231 }
232 // Insert filters otherwise 232 // Insert filters otherwise
233 else 233 else
234 { 234 {
235 HttpInputStream his = target.getInputStream(); 235 final HttpInputStream his = target.getInputStream();
236 int size = target.getContentLength(); 236 int size = target.getContentLength();
237 if (size < 0) 237 if (size < 0)
238 { 238 {
239 size = Integer.MAX_VALUE; 239 size = Integer.MAX_VALUE;
240 } 240 }
241 241
242 FilterInputStream in = null; 242 FilterInputStream in = null;
243 FilterOutputStream out = null; 243 FilterOutputStream out = null;
244 244
245 // Detect if content needs decoding 245 // Detect if content needs decoding
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
283 { 283 {
284 final Matcher matcher = Pattern.compile("charset=([^;]*)").matcher(con tentType); 284 final Matcher matcher = Pattern.compile("charset=([^;]*)").matcher(con tentType);
285 if (matcher.matches()) 285 if (matcher.matches())
286 { 286 {
287 try 287 try
288 { 288 {
289 final String extractedCharsetName = matcher.group(0); 289 final String extractedCharsetName = matcher.group(0);
290 Charset.forName(extractedCharsetName); 290 Charset.forName(extractedCharsetName);
291 charsetName = extractedCharsetName; 291 charsetName = extractedCharsetName;
292 } 292 }
293 catch (IllegalArgumentException e) 293 catch (final IllegalArgumentException e)
294 { 294 {
295 Log.e(prefix, "Unsupported site charset, falling back to " + chars etName, e); 295 Log.e(prefix, "Unsupported site charset, falling back to " + chars etName, e);
296 } 296 }
297 } 297 }
298 } 298 }
299 299
300 request.sendHeaders(-1, null, -1); 300 request.sendHeaders(-1, null, -1);
301 301
302 byte[] buf = new byte[Math.min(4096, size)]; 302 final byte[] buf = new byte[Math.min(4096, size)];
303 303
304 boolean sent = selectors == null; 304 boolean sent = selectors == null;
305 BoyerMoore matcher = new BoyerMoore("<html".getBytes()); 305 final BoyerMoore matcher = new BoyerMoore("<html".getBytes());
306 306
307 while (size > 0) 307 while (size > 0)
308 { 308 {
309 out.flush(); 309 out.flush();
310 310
311 count = in.read(buf, 0, Math.min(buf.length, size)); 311 count = in.read(buf, 0, Math.min(buf.length, size));
312 if (count < 0) 312 if (count < 0)
313 { 313 {
314 break; 314 break;
315 } 315 }
316 size -= count; 316 size -= count;
317 try 317 try
318 { 318 {
319 // Search for <html> tag 319 // Search for <html> tag
320 if (!sent && count > 0) 320 if (!sent && count > 0)
321 { 321 {
322 List<Integer> matches = matcher.match(buf, 0, count); 322 final List<Integer> matches = matcher.match(buf, 0, count);
323 if (!matches.isEmpty()) 323 if (!matches.isEmpty())
324 { 324 {
325 // Add filters right before match 325 // Add filters right before match
326 int m = matches.get(0); 326 final int m = matches.get(0);
327 out.write(buf, 0, m); 327 out.write(buf, 0, m);
328 out.write("<style type=\"text/css\">\n".getBytes()); 328 out.write("<style type=\"text/css\">\n".getBytes());
329 out.write(StringUtils.join(selectors, ",\r\n").getBytes(charsetN ame)); 329 out.write(StringUtils.join(selectors, ",\r\n").getBytes(charsetN ame));
330 out.write("{ display: none !important }</style>\n".getBytes()); 330 out.write("{ display: none !important }</style>\n".getBytes());
331 out.write(buf, m, count - m); 331 out.write(buf, m, count - m);
332 sent = true; 332 sent = true;
333 continue; 333 continue;
334 } 334 }
335 } 335 }
336 out.write(buf, 0, count); 336 out.write(buf, 0, count);
337 } 337 }
338 catch (IOException e) 338 catch (final IOException e)
339 { 339 {
340 break; 340 break;
341 } 341 }
342 } 342 }
343 // The correct way would be to close ChunkedOutputStream 343 // The correct way would be to close ChunkedOutputStream
344 // but we can not do it because underlying output stream is 344 // but we can not do it because underlying output stream is
345 // used later in caller code. So we use this ugly hack: 345 // used later in caller code. So we use this ugly hack:
346 if (out instanceof ChunkedOutputStream) 346 if (out instanceof ChunkedOutputStream)
347 ((ChunkedOutputStream) out).writeFinalChunk(); 347 ((ChunkedOutputStream) out).writeFinalChunk();
348 } 348 }
349 } 349 }
350 catch (InterruptedIOException e) 350 catch (final InterruptedIOException e)
351 { 351 {
352 /* 352 /*
353 * Read timeout while reading from the remote side. We use a 353 * Read timeout while reading from the remote side. We use a
354 * read timeout in case the target never responds. 354 * read timeout in case the target never responds.
355 */ 355 */
356 request.sendError(408, "Timeout / No response"); 356 request.sendError(408, "Timeout / No response");
357 } 357 }
358 catch (EOFException e) 358 catch (final EOFException e)
359 { 359 {
360 request.sendError(500, "No response"); 360 request.sendError(500, "No response");
361 } 361 }
362 catch (UnknownHostException e) 362 catch (final UnknownHostException e)
363 { 363 {
364 request.sendError(500, "Unknown host"); 364 request.sendError(500, "Unknown host");
365 } 365 }
366 catch (ConnectException e) 366 catch (final ConnectException e)
367 { 367 {
368 request.sendError(500, "Connection refused"); 368 request.sendError(500, "Connection refused");
369 } 369 }
370 catch (IOException e) 370 catch (final IOException e)
371 { 371 {
372 /* 372 /*
373 * An IOException will happen if we can't communicate with the 373 * An IOException will happen if we can't communicate with the
374 * target or the client. Rather than attempting to discriminate, 374 * target or the client. Rather than attempting to discriminate,
375 * just send an error message to the client, and let the send 375 * just send an error message to the client, and let the send
376 * fail if the client was the one that was in error. 376 * fail if the client was the one that was in error.
377 */ 377 */
378 378
379 String msg = "Error from proxy"; 379 String msg = "Error from proxy";
380 if (e.getMessage() != null) 380 if (e.getMessage() != null)
381 { 381 {
382 msg += ": " + e.getMessage(); 382 msg += ": " + e.getMessage();
383 } 383 }
384 request.sendError(500, msg); 384 request.sendError(500, msg);
385 Log.e(prefix, msg, e); 385 Log.e(prefix, msg, e);
386 } 386 }
387 finally 387 finally
388 { 388 {
389 target.close(); 389 target.close();
390 } 390 }
391 return true; 391 return true;
392 } 392 }
393 } 393 }
OLDNEW
« no previous file with comments | « src/org/adblockplus/brazil/BaseRequestHandler.java ('k') | src/org/adblockplus/brazil/SSLConnectionHandler.java » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld