1 28 29 package HTTPClient; 30 31 import java.net.InetAddress ; 32 import java.net.ProtocolException ; 33 import java.net.UnknownHostException ; 34 import java.io.IOException ; 35 import java.util.Hashtable ; 36 37 38 45 46 class RedirectionModule implements HTTPClientModule, GlobalConstants 47 { 48 49 private static Hashtable perm_redir_cntxt_list = new Hashtable (); 50 51 52 private int level; 53 54 55 private URI lastURI; 56 57 58 60 63 RedirectionModule() 64 { 65 level = 0; 66 lastURI = null; 67 } 68 69 70 72 75 public int requestHandler(Request req, Response[] resp) 76 { 77 HTTPConnection con = req.getConnection(); 78 URI new_loc, 79 cur_loc; 80 81 try 82 { 83 cur_loc = new URI(con.getProtocol(), con.getHost(), 84 con.getPort(), req.getRequestURI()); 85 } 86 catch (ParseException pe) 87 { 88 throw new Error ("HTTPClient Internal Error: unexpected exception '" 89 + pe + "'"); 90 } 91 92 93 95 Hashtable perm_redir_list = Util.getList(perm_redir_cntxt_list, 96 req.getConnection().getContext()); 97 if ((new_loc = (URI) perm_redir_list.get(cur_loc)) != null) 98 { 99 114 String nres = new_loc.getPath(); 115 req.setRequestURI(nres); 116 117 try 118 { lastURI = new URI(new_loc, nres); } 119 catch (ParseException pe) 120 { } 121 122 if (DebugMods) 123 System.err.println("RdirM: matched request in permanent " + 124 "redirection list - redoing request to " + 125 lastURI); 126 127 if (!sameServer(con, new_loc)) 128 { 129 try 130 { con = new HTTPConnection(new_loc.toURL()); } 131 catch (Exception e) 132 { 133 throw new Error ("HTTPClient Internal Error: unexpected " + 134 "exception '" + e + "'"); 135 } 136 137 con.setContext(req.getConnection().getContext()); 138 req.setConnection(con); 139 return REQ_NEWCON_RST; 140 } 141 else 142 { 143 return REQ_RESTART; 144 } 145 } 146 147 return REQ_CONTINUE; 148 } 149 150 151 154 public void responsePhase1Handler(Response resp, RoRequest req) 155 throws IOException 156 { 157 int sts = resp.getStatusCode(); 158 if (sts < 301 || sts > 307 || sts == 304) 159 { 160 if (lastURI != null) resp.setEffectiveURI(lastURI); 162 } 163 } 164 165 166 169 public int responsePhase2Handler(Response resp, Request req) 170 throws IOException 171 { 172 173 174 int sts = resp.getStatusCode(); 175 switch(sts) 176 { 177 case 302: 179 if (DebugMods) 180 System.err.println("RdirM: Received status: " + sts + 181 " " + resp.getReasonLine() + 182 " - treating as 303"); 183 184 sts = 303; 185 186 case 301: case 303: case 307: 190 if (DebugMods) 191 System.err.println("RdirM: Handling status: " + sts + 192 " " + resp.getReasonLine()); 193 194 if (!req.getMethod().equals("GET") && 197 !req.getMethod().equals("HEAD") && 198 sts != 303) 199 { 200 if (DebugMods) 201 System.err.println("RdirM: not redirected because " + 202 "method is neither HEAD nor GET"); 203 204 if (sts == 301 && resp.getHeader("Location") != null) 205 update_perm_redir_list(req, 206 resLocHdr(resp.getHeader("Location"), req)); 207 208 resp.setEffectiveURI(lastURI); 209 return RSP_CONTINUE; 210 } 211 212 case 305: case 306: 215 if (DebugMods) 216 if (sts == 305 || sts == 306) 217 System.err.println("RdirM: Handling status: " + sts + 218 " " + resp.getReasonLine()); 219 220 if (sts == 305 && req.getConnection().getProxyHost() != null) 222 { 223 if (DebugMods) 224 System.err.println("RdirM: 305 ignored because " + 225 "a proxy is already in use"); 226 227 resp.setEffectiveURI(lastURI); 228 return RSP_CONTINUE; 229 } 230 231 232 239 if (level == 15 || resp.getHeader("Location") == null) 240 { 241 if (DebugMods) 242 { 243 if (level == 15) 244 System.err.println("RdirM: not redirected because "+ 245 "of too many levels of redirection"); 246 else 247 System.err.println("RdirM: not redirected because "+ 248 "no Location header was present"); 249 } 250 251 resp.setEffectiveURI(lastURI); 252 return RSP_CONTINUE; 253 } 254 level++; 255 256 URI loc = resLocHdr(resp.getHeader("Location"), req); 257 258 if (req.getStream() != null && (sts == 306 || sts == 305)) 259 return RSP_CONTINUE; 260 261 HTTPConnection mvd; 262 boolean new_con = false; 263 String nres; 264 265 if (sts == 305) 266 { 267 mvd = new HTTPConnection(req.getConnection().getProtocol(), 268 req.getConnection().getHost(), 269 req.getConnection().getPort()); 270 mvd.setCurrentProxy(loc.getHost(), loc.getPort()); 271 mvd.setContext(req.getConnection().getContext()); 272 new_con = true; 273 274 nres = req.getRequestURI(); 275 276 284 req.setMethod("GET"); 285 req.setData(null); 286 req.setStream(null); 287 } 288 else if (sts == 306) 289 { 290 return RSP_CONTINUE; 292 } 293 else 294 { 295 if (sameServer(req.getConnection(), loc)) 296 { 297 mvd = req.getConnection(); 298 nres = loc.getPath(); 299 } 300 else 301 { 302 try 303 { 304 mvd = new HTTPConnection(loc.toURL()); 305 nres = loc.getPath(); 306 } 307 catch (Exception e) 308 { 309 if (req.getConnection().getProxyHost() == null || 310 !loc.getScheme().equalsIgnoreCase("ftp")) 311 return RSP_CONTINUE; 312 313 mvd = new HTTPConnection("http", 316 req.getConnection().getProxyHost(), 317 req.getConnection().getProxyPort()); 318 mvd.setCurrentProxy(null, 0); 319 nres = loc.toExternalForm(); 320 } 321 322 mvd.setContext(req.getConnection().getContext()); 323 new_con = true; 324 } 325 326 337 338 if (sts == 303 && !req.getMethod().equals("HEAD")) 339 { 340 342 req.setMethod("GET"); 343 req.setData(null); 344 req.setStream(null); 345 } 346 else if (sts == 301) 347 { 348 try 350 { 351 update_perm_redir_list(req, new URI(loc, nres)); 352 } 353 catch (ParseException pe) 354 { } 355 356 } 357 358 NVPair[] hdrs = req.getHeaders(); 360 for (int idx=0; idx<hdrs.length; idx++) 361 if (hdrs[idx].getName().equalsIgnoreCase("Referer")) 362 { 363 HTTPConnection con = req.getConnection(); 364 hdrs[idx] = 365 new NVPair("Referer", con+req.getRequestURI()); 366 break; 367 } 368 } 369 370 req.setConnection(mvd); 371 req.setRequestURI(nres); 372 373 try { resp.getInputStream().close(); } 374 catch (IOException ioe) { } 375 376 if (sts != 305 && sts != 306) 377 { 378 try 379 { lastURI = new URI(loc, nres); } 380 catch (ParseException pe) 381 { } 382 383 if (DebugMods) 384 System.err.println("RdirM: request redirected to " + 385 lastURI + " using method " + 386 req.getMethod()); 387 } 388 else 389 { 390 if (DebugMods) 391 System.err.println("RdirM: resending request using " + 392 "proxy " + mvd.getProxyHost() + 393 ":" + mvd.getProxyPort()); 394 } 395 396 if (new_con) 397 return RSP_NEWCON_REQ; 398 else 399 return RSP_REQUEST; 400 401 default: 402 403 return RSP_CONTINUE; 404 } 405 } 406 407 408 411 public void responsePhase3Handler(Response resp, RoRequest req) 412 { 413 } 414 415 416 419 public void trailerHandler(Response resp, RoRequest req) 420 { 421 } 422 423 424 430 private static void update_perm_redir_list(RoRequest req, URI new_loc) 431 { 432 HTTPConnection con = req.getConnection(); 433 URI cur_loc = null; 434 try 435 { 436 cur_loc = new URI(con.getProtocol(), 437 con.getHost(), 438 con.getPort(), 439 req.getRequestURI()); 440 } 441 catch (ParseException pe) 442 { } 443 444 if (!cur_loc.equals(new_loc)) 445 { 446 Hashtable perm_redir_list = 447 Util.getList(perm_redir_cntxt_list, con.getContext()); 448 perm_redir_list.put(cur_loc, new_loc); 449 } 450 } 451 452 453 464 private URI resLocHdr(String loc, RoRequest req) throws ProtocolException 465 { 466 try 467 { return new URI(loc); } 468 catch (ParseException pe) 469 { 470 try 472 { 473 URI base = new URI(req.getConnection().getProtocol(), 474 req.getConnection().getHost(), 475 req.getConnection().getPort(), 476 req.getRequestURI()); 477 return new URI(base, loc); 478 } 479 catch (ParseException pe2) 480 { 481 throw new ProtocolException ("Malformed URL in Location " + 482 "header: " + loc); 483 } 484 } 485 } 486 487 488 497 private boolean sameServer(HTTPConnection con, URI url) 498 { 499 if (!url.getScheme().equalsIgnoreCase(con.getProtocol())) 500 return false; 501 502 521 if (!url.getHost().equalsIgnoreCase(con.getHost())) 522 return false; 523 524 if (url.getPort() != con.getPort()) 525 return false; 526 527 return true; 528 } 529 } 530 531 | Popular Tags |