use of okhttp3.internal.http2.ConnectionShutdownException in project okhttp by square.
the class RetryAndFollowUpInterceptor method intercept.
@Override
public Response intercept(Chain chain) throws IOException {
Request request = chain.request();
streamAllocation = new StreamAllocation(client.connectionPool(), createAddress(request.url()), callStackTrace);
int followUpCount = 0;
Response priorResponse = null;
while (true) {
if (canceled) {
streamAllocation.release();
throw new IOException("Canceled");
}
Response response = null;
boolean releaseConnection = true;
try {
response = ((RealInterceptorChain) chain).proceed(request, streamAllocation, null, null);
releaseConnection = false;
} catch (RouteException e) {
// The attempt to connect via a route failed. The request will not have been sent.
if (!recover(e.getLastConnectException(), false, request)) {
throw e.getLastConnectException();
}
releaseConnection = false;
continue;
} catch (IOException e) {
// An attempt to communicate with a server failed. The request may have been sent.
boolean requestSendStarted = !(e instanceof ConnectionShutdownException);
if (!recover(e, requestSendStarted, request))
throw e;
releaseConnection = false;
continue;
} finally {
// We're throwing an unchecked exception. Release any resources.
if (releaseConnection) {
streamAllocation.streamFailed(null);
streamAllocation.release();
}
}
// Attach the prior response if it exists. Such responses never have a body.
if (priorResponse != null) {
response = response.newBuilder().priorResponse(priorResponse.newBuilder().body(null).build()).build();
}
Request followUp = followUpRequest(response);
if (followUp == null) {
if (!forWebSocket) {
streamAllocation.release();
}
return response;
}
closeQuietly(response.body());
if (++followUpCount > MAX_FOLLOW_UPS) {
streamAllocation.release();
throw new ProtocolException("Too many follow-up requests: " + followUpCount);
}
if (followUp.body() instanceof UnrepeatableRequestBody) {
streamAllocation.release();
throw new HttpRetryException("Cannot retry streamed HTTP body", response.code());
}
if (!sameConnection(response, followUp.url())) {
streamAllocation.release();
streamAllocation = new StreamAllocation(client.connectionPool(), createAddress(followUp.url()), callStackTrace);
} else if (streamAllocation.codec() != null) {
throw new IllegalStateException("Closing the body of " + response + " didn't close its backing stream. Bad interceptor?");
}
request = followUp;
priorResponse = response;
}
}
use of okhttp3.internal.http2.ConnectionShutdownException in project okhttp by square.
the class Http2ConnectionTest method receiveGoAwayHttp2.
@Test
public void receiveGoAwayHttp2() throws Exception {
// write the mocking script
peer.sendFrame().settings(new Settings());
// ACK
peer.acceptFrame();
// SYN_STREAM 3
peer.acceptFrame();
// SYN_STREAM 5
peer.acceptFrame();
peer.sendFrame().goAway(3, ErrorCode.PROTOCOL_ERROR, EMPTY_BYTE_ARRAY);
// PING
peer.acceptFrame();
peer.sendFrame().ping(true, 1, 0);
// DATA STREAM 3
peer.acceptFrame();
peer.play();
// play it back
Http2Connection connection = connect(peer);
Http2Stream stream1 = connection.newStream(headerEntries("a", "android"), true);
Http2Stream stream2 = connection.newStream(headerEntries("b", "banana"), true);
// Ensure the GO_AWAY that resets stream2 has been received.
connection.ping().roundTripTime();
BufferedSink sink1 = Okio.buffer(stream1.getSink());
BufferedSink sink2 = Okio.buffer(stream2.getSink());
sink1.writeUtf8("abc");
try {
sink2.writeUtf8("abc");
sink2.flush();
fail();
} catch (IOException expected) {
assertEquals("stream was reset: REFUSED_STREAM", expected.getMessage());
}
sink1.writeUtf8("def");
sink1.close();
try {
connection.newStream(headerEntries("c", "cola"), true);
fail();
} catch (ConnectionShutdownException expected) {
}
assertTrue(stream1.isOpen());
assertFalse(stream2.isOpen());
assertEquals(1, connection.openStreamCount());
// verify the peer received what was expected
InFrame synStream1 = peer.takeFrame();
assertEquals(Http2.TYPE_HEADERS, synStream1.type);
InFrame synStream2 = peer.takeFrame();
assertEquals(Http2.TYPE_HEADERS, synStream2.type);
InFrame ping = peer.takeFrame();
assertEquals(Http2.TYPE_PING, ping.type);
InFrame data1 = peer.takeFrame();
assertEquals(Http2.TYPE_DATA, data1.type);
assertEquals(3, data1.streamId);
assertTrue(Arrays.equals("abcdef".getBytes("UTF-8"), data1.data));
}
use of okhttp3.internal.http2.ConnectionShutdownException in project okhttp by square.
the class Http2ConnectionTest method noPingsAfterShutdown.
@Test
public void noPingsAfterShutdown() throws Exception {
// write the mocking script
peer.sendFrame().settings(new Settings());
// ACK
peer.acceptFrame();
// GOAWAY
peer.acceptFrame();
peer.play();
// play it back
Http2Connection connection = connect(peer);
connection.shutdown(ErrorCode.INTERNAL_ERROR);
try {
connection.ping();
fail();
} catch (ConnectionShutdownException expected) {
}
// verify the peer received what was expected
InFrame goaway = peer.takeFrame();
assertEquals(Http2.TYPE_GOAWAY, goaway.type);
assertEquals(ErrorCode.INTERNAL_ERROR, goaway.errorCode);
}
use of okhttp3.internal.http2.ConnectionShutdownException in project okhttp by square.
the class Http2ConnectionTest method receiveGoAway.
@Test
public void receiveGoAway() throws Exception {
// write the mocking script
peer.sendFrame().settings(new Settings());
// ACK
peer.acceptFrame();
// SYN_STREAM 1
peer.acceptFrame();
// SYN_STREAM 3
peer.acceptFrame();
// PING.
peer.acceptFrame();
peer.sendFrame().goAway(3, ErrorCode.PROTOCOL_ERROR, Util.EMPTY_BYTE_ARRAY);
peer.sendFrame().ping(true, 1, 0);
// DATA STREAM 1
peer.acceptFrame();
peer.play();
// play it back
Http2Connection connection = connect(peer);
Http2Stream stream1 = connection.newStream(headerEntries("a", "android"), true);
Http2Stream stream2 = connection.newStream(headerEntries("b", "banana"), true);
// Ensure the GO_AWAY that resets stream2 has been received.
connection.ping().roundTripTime();
BufferedSink sink1 = Okio.buffer(stream1.getSink());
BufferedSink sink2 = Okio.buffer(stream2.getSink());
sink1.writeUtf8("abc");
try {
sink2.writeUtf8("abc");
sink2.flush();
fail();
} catch (IOException expected) {
assertEquals("stream was reset: REFUSED_STREAM", expected.getMessage());
}
sink1.writeUtf8("def");
sink1.close();
try {
connection.newStream(headerEntries("c", "cola"), false);
fail();
} catch (ConnectionShutdownException expected) {
}
assertTrue(stream1.isOpen());
assertFalse(stream2.isOpen());
assertEquals(1, connection.openStreamCount());
// verify the peer received what was expected
InFrame synStream1 = peer.takeFrame();
assertEquals(Http2.TYPE_HEADERS, synStream1.type);
InFrame synStream2 = peer.takeFrame();
assertEquals(Http2.TYPE_HEADERS, synStream2.type);
InFrame ping = peer.takeFrame();
assertEquals(Http2.TYPE_PING, ping.type);
InFrame data1 = peer.takeFrame();
assertEquals(Http2.TYPE_DATA, data1.type);
assertEquals(3, data1.streamId);
assertTrue(Arrays.equals("abcdef".getBytes("UTF-8"), data1.data));
}
use of okhttp3.internal.http2.ConnectionShutdownException in project okhttp by square.
the class Http2ConnectionTest method close.
@Test
public void close() throws Exception {
// write the mocking script
peer.sendFrame().settings(new Settings());
// ACK
peer.acceptFrame();
// SYN_STREAM
peer.acceptFrame();
// GOAWAY
peer.acceptFrame();
// RST_STREAM
peer.acceptFrame();
peer.play();
// play it back
Http2Connection connection = connect(peer);
Http2Stream stream = connection.newStream(headerEntries("a", "android"), false);
assertEquals(1, connection.openStreamCount());
connection.close();
assertEquals(0, connection.openStreamCount());
try {
connection.newStream(headerEntries("b", "banana"), false);
fail();
} catch (ConnectionShutdownException expected) {
}
BufferedSink sink = Okio.buffer(stream.getSink());
try {
sink.writeByte(0);
sink.flush();
fail();
} catch (IOException expected) {
assertEquals("stream finished", expected.getMessage());
}
try {
stream.getSource().read(new Buffer(), 1);
fail();
} catch (IOException expected) {
assertEquals("stream was reset: CANCEL", expected.getMessage());
}
// verify the peer received what was expected
InFrame synStream = peer.takeFrame();
assertEquals(Http2.TYPE_HEADERS, synStream.type);
InFrame goaway = peer.takeFrame();
assertEquals(Http2.TYPE_GOAWAY, goaway.type);
InFrame rstStream = peer.takeFrame();
assertEquals(Http2.TYPE_RST_STREAM, rstStream.type);
assertEquals(3, rstStream.streamId);
}
Aggregations