1
0
mirror of https://github.com/square/okhttp.git synced 2025-11-27 18:21:14 +03:00

Keep the response body alive after the callback.

This commit is contained in:
Jesse Wilson
2014-06-10 19:31:46 -04:00
parent ac6ac338a3
commit aa7e7a751c
3 changed files with 44 additions and 2 deletions

View File

@@ -34,11 +34,13 @@ import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import java.util.UUID;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.Callable;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.SynchronousQueue;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicReference;
@@ -1285,6 +1287,44 @@ public final class CallTest {
.assertRequestHeader("Accept-Encoding", "gzip");
}
@Test public void asyncResponseCanBeConsumedLater() throws Exception {
server.enqueue(new MockResponse().setBody("abc"));
server.enqueue(new MockResponse().setBody("def"));
server.play();
Request request = new Request.Builder()
.url(server.getUrl("/"))
.header("User-Agent", "SyncApiTest")
.build();
final BlockingQueue<Response> responseRef = new SynchronousQueue<Response>();
client.newCall(request).enqueue(new Callback() {
@Override public void onFailure(Request request, Throwable throwable) {
throw new AssertionError();
}
@Override public void onResponse(Response response) throws IOException {
try {
responseRef.put(response);
} catch (InterruptedException e) {
throw new AssertionError();
}
}
});
Response response = responseRef.take();
assertEquals(200, response.code());
assertEquals("abc", response.body().string());
// Make another request just to confirm that that connection can be reused...
executeSynchronously(new Request.Builder().url(server.getUrl("/")).build()).assertBody("def");
assertEquals(0, server.takeRequest().getSequenceNumber()); // New connection.
assertEquals(1, server.takeRequest().getSequenceNumber()); // Connection reused.
// ... even before we close the response body!
response.body().close();
}
private RecordedResponse executeSynchronously(Request request) throws IOException {
Response response = client.newCall(request).execute();
return new RecordedResponse(request, response, response.body().string(), null);

View File

@@ -146,13 +146,13 @@ public final class Call {
responseCallback.onFailure(request, new IOException("Canceled"));
} else {
signalledCallback = true;
engine.releaseConnection();
responseCallback.onResponse(response);
}
} catch (IOException e) {
if (signalledCallback) throw new RuntimeException(e); // Do not signal the callback twice!
responseCallback.onFailure(request, e);
} finally {
engine.close(); // Close the connection if it isn't already.
dispatcher.finished(this);
}
}

View File

@@ -29,7 +29,9 @@ public interface Callback {
/**
* Called when the HTTP response was successfully returned by the remote
* server. The callback may proceed to read the response body with {@link
* Response#body}.
* Response#body}. The response is still live until its response body is
* closed with {@code response.body().close()}. The recipient of the callback
* may even consume the response body on another thread.
*
* <p>Note that transport-layer success (receiving a HTTP response code,
* headers and body) does not necessarily indicate application-layer