mirror of
https://github.com/square/okhttp.git
synced 2026-01-25 16:01:38 +03:00
Add support for following HTTP 307 temporary redirects.
Fixes Android bug 41739.
This commit is contained in:
@@ -60,6 +60,10 @@ import static com.squareup.okhttp.internal.Util.getEffectivePort;
|
||||
* is currently connected to a server.
|
||||
*/
|
||||
public class HttpURLConnectionImpl extends HttpURLConnection {
|
||||
|
||||
/** Numeric status code, 307: Temporary Redirect. */
|
||||
static final int HTTP_TEMP_REDIRECT = 307;
|
||||
|
||||
/**
|
||||
* How many redirects should we follow? Chrome follows 21; Firefox, curl,
|
||||
* and wget follow 20; Safari follows 16; and HTTP/1.0 recommends 5.
|
||||
@@ -400,7 +404,8 @@ public class HttpURLConnectionImpl extends HttpURLConnection {
|
||||
Proxy selectedProxy = httpEngine.connection != null
|
||||
? httpEngine.connection.getProxy()
|
||||
: requestedProxy;
|
||||
switch (getResponseCode()) {
|
||||
final int responseCode = getResponseCode();
|
||||
switch (responseCode) {
|
||||
case HTTP_PROXY_AUTH:
|
||||
if (selectedProxy.type() != Proxy.Type.HTTP) {
|
||||
throw new ProtocolException("Received HTTP_PROXY_AUTH (407) code while not using proxy");
|
||||
@@ -415,12 +420,18 @@ public class HttpURLConnectionImpl extends HttpURLConnection {
|
||||
case HTTP_MOVED_PERM:
|
||||
case HTTP_MOVED_TEMP:
|
||||
case HTTP_SEE_OTHER:
|
||||
case HTTP_TEMP_REDIRECT:
|
||||
if (!getInstanceFollowRedirects()) {
|
||||
return Retry.NONE;
|
||||
}
|
||||
if (++redirectionCount > MAX_REDIRECTS) {
|
||||
throw new ProtocolException("Too many redirects: " + redirectionCount);
|
||||
}
|
||||
if (responseCode == HTTP_TEMP_REDIRECT && !method.equals("GET") && !method.equals("HEAD")) {
|
||||
// "If the 307 status code is received in response to a request other than GET or HEAD,
|
||||
// the user agent MUST NOT automatically redirect the request"
|
||||
return Retry.NONE;
|
||||
}
|
||||
String location = getHeaderField("Location");
|
||||
if (location == null) {
|
||||
return Retry.NONE;
|
||||
|
||||
@@ -1731,6 +1731,70 @@ public final class URLConnectionTest {
|
||||
assertEquals(1, server.getRequestCount());
|
||||
}
|
||||
|
||||
@Test public void response307WithGet() throws Exception {
|
||||
test307Redirect("GET");
|
||||
}
|
||||
|
||||
@Test public void response307WithHead() throws Exception {
|
||||
test307Redirect("HEAD");
|
||||
}
|
||||
|
||||
@Test public void response307WithOptions() throws Exception {
|
||||
test307Redirect("OPTIONS");
|
||||
}
|
||||
|
||||
@Test public void response307WithPost() throws Exception {
|
||||
test307Redirect("POST");
|
||||
}
|
||||
|
||||
private void test307Redirect(String method) throws Exception {
|
||||
MockResponse response1 = new MockResponse()
|
||||
.setResponseCode(HttpURLConnectionImpl.HTTP_TEMP_REDIRECT)
|
||||
.addHeader("Location: /page2");
|
||||
if (!method.equals("HEAD")) {
|
||||
response1.setBody("This page has moved!");
|
||||
}
|
||||
server.enqueue(response1);
|
||||
server.enqueue(new MockResponse().setBody("Page 2"));
|
||||
server.play();
|
||||
|
||||
HttpURLConnection connection = client.open(server.getUrl("/page1"));
|
||||
connection.setRequestMethod(method);
|
||||
byte[] requestBody = { 'A', 'B', 'C', 'D' };
|
||||
if (method.equals("POST")) {
|
||||
connection.setDoOutput(true);
|
||||
OutputStream outputStream = connection.getOutputStream();
|
||||
outputStream.write(requestBody);
|
||||
outputStream.close();
|
||||
}
|
||||
|
||||
String response = readAscii(connection.getInputStream(), Integer.MAX_VALUE);
|
||||
|
||||
RecordedRequest page1 = server.takeRequest();
|
||||
assertEquals(method + " /page1 HTTP/1.1", page1.getRequestLine());
|
||||
|
||||
if (method.equals("GET")) {
|
||||
assertEquals("Page 2", response);
|
||||
} else if (method.equals("HEAD")) {
|
||||
assertTrue(response.isEmpty());
|
||||
} else {
|
||||
// Methods other than GET/HEAD shouldn't follow the redirect
|
||||
if (method.equals("POST")) {
|
||||
assertTrue(connection.getDoOutput());
|
||||
assertEquals(Arrays.toString(requestBody), Arrays.toString(page1.getBody()));
|
||||
}
|
||||
assertEquals(1, server.getRequestCount());
|
||||
assertEquals("This page has moved!", response);
|
||||
return;
|
||||
}
|
||||
|
||||
// GET/HEAD requests should have followed the redirect with the same method
|
||||
assertFalse(connection.getDoOutput());
|
||||
assertEquals(2, server.getRequestCount());
|
||||
RecordedRequest page2 = server.takeRequest();
|
||||
assertEquals(method + " /page2 HTTP/1.1", page2.getRequestLine());
|
||||
}
|
||||
|
||||
@Test public void follow20Redirects() throws Exception {
|
||||
for (int i = 0; i < 20; i++) {
|
||||
server.enqueue(new MockResponse().setResponseCode(HttpURLConnection.HTTP_MOVED_TEMP)
|
||||
|
||||
Reference in New Issue
Block a user