/** Invoked by the HTTPClient. */ public int responsePhase2Handler(Response resp, Request req) throws IOException { /* handle various response status codes until satisfied */ int sts = resp.getStatusCode(); switch (sts) { case 302: // General (temporary) Redirection (handle like 303) /* * Note we only do this munging for POST and PUT. For GET it's not * necessary; for HEAD we probably want to do another HEAD. For all * others (i.e. methods from WebDAV, IPP, etc) it's somewhat unclear - * servers supporting those should really return a 307 or 303, but some * don't (guess who...), so we just don't touch those. */ if (req.getMethod().equals("POST") || req.getMethod().equals("PUT")) { if (LOG.isDebugEnabled()) LOG.debug( "Received status: " + sts + " " + resp.getReasonLine() + " - treating as 303"); sts = 303; } case 301: // Moved Permanently case 303: // See Other (use GET) case 307: // Moved Temporarily (we mean it!) if (LOG.isDebugEnabled()) LOG.debug("Handling status: " + sts + " " + resp.getReasonLine()); // the spec says automatic redirection may only be done if // the second request is a HEAD or GET. if (!req.getMethod().equals("GET") && !req.getMethod().equals("HEAD") && sts != 303) { if (LOG.isDebugEnabled()) LOG.debug("Not redirected because method is neither HEAD nor GET"); if (sts == 301 && resp.getHeader("Location") != null) update_perm_redir_list(req, resLocHdr(resp.getHeader("Location"), req)); resp.setEffectiveURI(lastURI); return RSP_CONTINUE; } case 305: // Use Proxy case 306: // Switch Proxy if (sts == 305 || sts == 306) { if (LOG.isDebugEnabled()) LOG.debug("Handling status: " + sts + " " + resp.getReasonLine()); } // Don't accept 305 from a proxy if (sts == 305 && req.getConnection().getProxyHost() != null) { if (LOG.isDebugEnabled()) LOG.debug("305 ignored because a proxy is already in use"); resp.setEffectiveURI(lastURI); return RSP_CONTINUE; } /* * the level is a primitive way of preventing infinite redirections. * RFC-2068 set the max to 5, but RFC-2616 has loosened this. Since some * sites (notably M$) need more levels, this is now set to the * (arbitrary) value of 15 (god only knows why they need to do even 5 * redirections...). */ if (level >= 15 || resp.getHeader("Location") == null) { if (LOG.isDebugEnabled()) { if (level >= 15) LOG.debug("Not redirected because of too many levels of redirection"); else LOG.debug("Not redirected because no Location header was present"); } resp.setEffectiveURI(lastURI); return RSP_CONTINUE; } level++; URI loc = resLocHdr(resp.getHeader("Location"), req); HTTPConnection mvd; String nres; new_con = false; if (sts == 305) { mvd = new HTTPConnection( req.getConnection().getProtocol(), req.getConnection().getHost(), req.getConnection().getPort()); mvd.setCurrentProxy(loc.getHost(), loc.getPort()); mvd.setContext(req.getConnection().getContext()); new_con = true; nres = req.getRequestURI(); /* * There was some discussion about this, and especially Foteos * Macrides (Lynx) said a 305 should also imply a change to GET (for * security reasons) - see the thread starting at * http://www.ics.uci.edu/pub/ietf/http/hypermail/1997q4/0351.html * However, this is not in the latest draft, but since I agree with * Foteos we do it anyway... */ req.setMethod("GET"); req.setData(null); req.setStream(null); } else if (sts == 306) { // We'll have to wait for Josh to create a new spec here. return RSP_CONTINUE; } else { if (req.getConnection().isCompatibleWith(loc)) { mvd = req.getConnection(); nres = loc.getPathAndQuery(); } else { try { mvd = new HTTPConnection(loc); nres = loc.getPathAndQuery(); } catch (ProtocolNotSuppException e) { if (req.getConnection().getProxyHost() == null || !loc.getScheme().equalsIgnoreCase("ftp")) return RSP_CONTINUE; // We're using a proxy and the protocol is ftp - // maybe the proxy will also proxy ftp... mvd = new HTTPConnection( "http", req.getConnection().getProxyHost(), req.getConnection().getProxyPort()); mvd.setCurrentProxy(null, 0); nres = loc.toExternalForm(); } mvd.setContext(req.getConnection().getContext()); new_con = true; } /* * copy query if present in old url but not in new url. This isn't * strictly conforming, but some scripts fail to propagate the query * properly to the Location header. See comment on line 126. String * oquery = Util.getQuery(req.getRequestURI()), nquery = * Util.getQuery(nres); if (nquery == null && oquery != null) nres += * "?" + oquery; */ if (sts == 303) { // 303 means "use GET" if (!req.getMethod().equals("HEAD")) req.setMethod("GET"); req.setData(null); req.setStream(null); } else { // If they used an output stream then they'll have // to do the resend themselves if (req.getStream() != null) { if (!HTTPConnection.deferStreamed) { if (LOG.isDebugEnabled()) LOG.debug("Status " + sts + " not handled - request has an output stream"); return RSP_CONTINUE; } saved_req = (Request) req.clone(); deferred_redir_list.put(req.getStream(), this); req.getStream().reset(); resp.setRetryRequest(true); } if (sts == 301) { // update permanent redirection list try { update_perm_redir_list(req, new URI(loc, nres)); } catch (ParseException pe) { throw new Error( "HTTPClient Internal Error: " + "unexpected exception '" + pe + "'", pe); } } } // Adjust Referer, if present NVPair[] hdrs = req.getHeaders(); for (int idx = 0; idx < hdrs.length; idx++) if (hdrs[idx].getName().equalsIgnoreCase("Referer")) { HTTPConnection con = req.getConnection(); hdrs[idx] = new NVPair("Referer", con + req.getRequestURI()); break; } } req.setConnection(mvd); req.setRequestURI(nres); try { resp.getInputStream().close(); } catch (IOException ioe) { if (LOG.isTraceEnabled()) { LOG.trace("An exception occurred: " + ioe.getMessage()); } } if (sts != 305 && sts != 306) { try { lastURI = new URI(loc, nres); } catch (ParseException pe) { if (LOG.isTraceEnabled()) { LOG.trace("An exception occurred: " + pe.getMessage()); } } if (LOG.isDebugEnabled()) LOG.debug( "Request redirected to " + lastURI.toExternalForm() + " using method " + req.getMethod()); } else { if (LOG.isDebugEnabled()) LOG.debug( "Resending request using " + "proxy " + mvd.getProxyHost() + ":" + mvd.getProxyPort()); } if (req.getStream() != null) return RSP_CONTINUE; else if (new_con) return RSP_NEWCON_REQ; else return RSP_REQUEST; default: return RSP_CONTINUE; } }
public int getPort() { log("getPort: " + uri.getPort()); return uri.getPort(); }