1
0
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:
Christopher Orr
2013-02-27 19:09:12 +01:00
parent f24072ec6b
commit 0665b628fa
2 changed files with 76 additions and 1 deletions

View File

@@ -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;

View File

@@ -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)