1 /* 2 * $HeadURL: http://svn.apache.org/repos/asf/httpcomponents/httpclient/trunk/module-client/src/main/java/org/apache/http/impl/client/DefaultRedirectHandler.java $ 3 * $Revision: 673450 $ 4 * $Date: 2008-07-02 10:35:05 -0700 (Wed, 02 Jul 2008) $ 5 * 6 * ==================================================================== 7 * Licensed to the Apache Software Foundation (ASF) under one 8 * or more contributor license agreements. See the NOTICE file 9 * distributed with this work for additional information 10 * regarding copyright ownership. The ASF licenses this file 11 * to you under the Apache License, Version 2.0 (the 12 * "License"); you may not use this file except in compliance 13 * with the License. You may obtain a copy of the License at 14 * 15 * http://www.apache.org/licenses/LICENSE-2.0 16 * 17 * Unless required by applicable law or agreed to in writing, 18 * software distributed under the License is distributed on an 19 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 20 * KIND, either express or implied. See the License for the 21 * specific language governing permissions and limitations 22 * under the License. 23 * ==================================================================== 24 * 25 * This software consists of voluntary contributions made by many 26 * individuals on behalf of the Apache Software Foundation. For more 27 * information on the Apache Software Foundation, please see 28 * <http://www.apache.org/>. 29 * 30 */ 31 32 package org.apache.http.impl.client; 33 34 import java.net.URI; 35 import java.net.URISyntaxException; 36 37 import org.apache.commons.logging.Log; 38 import org.apache.commons.logging.LogFactory; 39 import org.apache.http.Header; 40 import org.apache.http.HttpHost; 41 import org.apache.http.HttpRequest; 42 import org.apache.http.HttpResponse; 43 import org.apache.http.HttpStatus; 44 import org.apache.http.ProtocolException; 45 import org.apache.http.client.CircularRedirectException; 46 import org.apache.http.client.RedirectHandler; 47 import org.apache.http.client.params.ClientPNames; 48 import org.apache.http.client.utils.URIUtils; 49 import org.apache.http.params.HttpParams; 50 import org.apache.http.protocol.HttpContext; 51 import org.apache.http.protocol.ExecutionContext; 52 53 54 /** 55 * Default implementation of {@link RedirectHandler}. 56 * 57 * @author <a href="mailto:oleg at ural.ru">Oleg Kalnichevski</a> 58 * 59 * 60 * <!-- empty lines to avoid svn diff problems --> 61 * @version $Revision: 673450 $ 62 * 63 * @since 4.0 64 */ 65 public class DefaultRedirectHandler implements RedirectHandler { 66 67 private final Log log = LogFactory.getLog(getClass()); 68 69 private static final String REDIRECT_LOCATIONS = "http.protocol.redirect-locations"; 70 71 public DefaultRedirectHandler() { 72 super(); 73 } 74 75 public boolean isRedirectRequested( 76 final HttpResponse response, 77 final HttpContext context) { 78 if (response == null) { 79 throw new IllegalArgumentException("HTTP response may not be null"); 80 } 81 int statusCode = response.getStatusLine().getStatusCode(); 82 switch (statusCode) { 83 case HttpStatus.SC_MOVED_TEMPORARILY: 84 case HttpStatus.SC_MOVED_PERMANENTLY: 85 case HttpStatus.SC_SEE_OTHER: 86 case HttpStatus.SC_TEMPORARY_REDIRECT: 87 return true; 88 default: 89 return false; 90 } //end of switch 91 } 92 93 public URI getLocationURI( 94 final HttpResponse response, 95 final HttpContext context) throws ProtocolException { 96 if (response == null) { 97 throw new IllegalArgumentException("HTTP response may not be null"); 98 } 99 //get the location header to find out where to redirect to 100 Header locationHeader = response.getFirstHeader("location"); 101 if (locationHeader == null) { 102 // got a redirect response, but no location header 103 throw new ProtocolException( 104 "Received redirect response " + response.getStatusLine() 105 + " but no location header"); 106 } 107 String location = locationHeader.getValue(); 108 if (this.log.isDebugEnabled()) { 109 this.log.debug("Redirect requested to location '" + location + "'"); 110 } 111 112 URI uri; 113 try { 114 uri = new URI(location); 115 } catch (URISyntaxException ex) { 116 throw new ProtocolException("Invalid redirect URI: " + location, ex); 117 } 118 119 HttpParams params = response.getParams(); 120 // rfc2616 demands the location value be a complete URI 121 // Location = "Location" ":" absoluteURI 122 if (!uri.isAbsolute()) { 123 if (params.isParameterTrue(ClientPNames.REJECT_RELATIVE_REDIRECT)) { 124 throw new ProtocolException("Relative redirect location '" 125 + uri + "' not allowed"); 126 } 127 // Adjust location URI 128 HttpHost target = (HttpHost) context.getAttribute( 129 ExecutionContext.HTTP_TARGET_HOST); 130 if (target == null) { 131 throw new IllegalStateException("Target host not available " + 132 "in the HTTP context"); 133 } 134 135 HttpRequest request = (HttpRequest) context.getAttribute( 136 ExecutionContext.HTTP_REQUEST); 137 138 try { 139 URI requestURI = new URI(request.getRequestLine().getUri()); 140 URI absoluteRequestURI = URIUtils.rewriteURI(requestURI, target, true); 141 uri = URIUtils.resolve(absoluteRequestURI, uri); 142 } catch (URISyntaxException ex) { 143 throw new ProtocolException(ex.getMessage(), ex); 144 } 145 } 146 147 if (params.isParameterFalse(ClientPNames.ALLOW_CIRCULAR_REDIRECTS)) { 148 149 RedirectLocations redirectLocations = (RedirectLocations) context.getAttribute( 150 REDIRECT_LOCATIONS); 151 152 if (redirectLocations == null) { 153 redirectLocations = new RedirectLocations(); 154 context.setAttribute(REDIRECT_LOCATIONS, redirectLocations); 155 } 156 157 URI redirectURI; 158 if (uri.getFragment() != null) { 159 try { 160 HttpHost target = new HttpHost( 161 uri.getHost(), 162 uri.getPort(), 163 uri.getScheme()); 164 redirectURI = URIUtils.rewriteURI(uri, target, true); 165 } catch (URISyntaxException ex) { 166 throw new ProtocolException(ex.getMessage(), ex); 167 } 168 } else { 169 redirectURI = uri; 170 } 171 172 if (redirectLocations.contains(redirectURI)) { 173 throw new CircularRedirectException("Circular redirect to '" + 174 redirectURI + "'"); 175 } else { 176 redirectLocations.add(redirectURI); 177 } 178 } 179 180 return uri; 181 } 182 183 } 184