Search in sources :

Example 1 with ConnectionShutdownException

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;
    }
}
Also used : StreamAllocation(okhttp3.internal.connection.StreamAllocation) Response(okhttp3.Response) RouteException(okhttp3.internal.connection.RouteException) ProtocolException(java.net.ProtocolException) ConnectionShutdownException(okhttp3.internal.http2.ConnectionShutdownException) Request(okhttp3.Request) InterruptedIOException(java.io.InterruptedIOException) IOException(java.io.IOException) HttpRetryException(java.net.HttpRetryException)

Example 2 with ConnectionShutdownException

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));
}
Also used : InFrame(okhttp3.internal.http2.MockHttp2Peer.InFrame) BufferedSink(okio.BufferedSink) InterruptedIOException(java.io.InterruptedIOException) IOException(java.io.IOException) Test(org.junit.Test)

Example 3 with ConnectionShutdownException

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);
}
Also used : InFrame(okhttp3.internal.http2.MockHttp2Peer.InFrame) Test(org.junit.Test)

Example 4 with ConnectionShutdownException

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));
}
Also used : InFrame(okhttp3.internal.http2.MockHttp2Peer.InFrame) BufferedSink(okio.BufferedSink) InterruptedIOException(java.io.InterruptedIOException) IOException(java.io.IOException) Test(org.junit.Test)

Example 5 with ConnectionShutdownException

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);
}
Also used : Buffer(okio.Buffer) InFrame(okhttp3.internal.http2.MockHttp2Peer.InFrame) BufferedSink(okio.BufferedSink) InterruptedIOException(java.io.InterruptedIOException) IOException(java.io.IOException) Test(org.junit.Test)

Aggregations

IOException (java.io.IOException)4 InterruptedIOException (java.io.InterruptedIOException)4 InFrame (okhttp3.internal.http2.MockHttp2Peer.InFrame)4 Test (org.junit.Test)4 BufferedSink (okio.BufferedSink)3 ConnectionShutdownException (okhttp3.internal.http2.ConnectionShutdownException)2 HttpRetryException (java.net.HttpRetryException)1 ProtocolException (java.net.ProtocolException)1 Socket (java.net.Socket)1 Request (okhttp3.Request)1 Response (okhttp3.Response)1 RouteException (okhttp3.internal.connection.RouteException)1 StreamAllocation (okhttp3.internal.connection.StreamAllocation)1 StreamResetException (okhttp3.internal.http2.StreamResetException)1 Buffer (okio.Buffer)1