@@ -20,6 +20,7 @@ import java.net.ProtocolException
2020import okhttp3.Interceptor
2121import okhttp3.Response
2222import okhttp3.internal.EMPTY_RESPONSE
23+ import okhttp3.internal.http2.ConnectionShutdownException
2324import okio.buffer
2425
2526/* * This is the last interceptor in the chain. It makes a network call to the server. */
@@ -33,98 +34,118 @@ class CallServerInterceptor(private val forWebSocket: Boolean) : Interceptor {
3334 val requestBody = request.body
3435 val sentRequestMillis = System .currentTimeMillis()
3536
36- exchange.writeRequestHeaders(request)
37-
3837 var invokeStartEvent = true
3938 var responseBuilder: Response .Builder ? = null
40- if (HttpMethod .permitsRequestBody(request.method) && requestBody != null ) {
41- // If there's a "Expect: 100-continue" header on the request, wait for a "HTTP/1.1 100
42- // Continue" response before transmitting the request body. If we don't get that, return
43- // what we did get (such as a 4xx response) without ever transmitting the request body.
44- if (" 100-continue" .equals(request.header(" Expect" ), ignoreCase = true )) {
45- exchange.flushRequest()
46- responseBuilder = exchange.readResponseHeaders(expectContinue = true )
47- exchange.responseHeadersStart()
48- invokeStartEvent = false
49- }
50- if (responseBuilder == null ) {
51- if (requestBody.isDuplex()) {
52- // Prepare a duplex body so that the application can send a request body later.
39+ var sendRequestException: IOException ? = null
40+ try {
41+ exchange.writeRequestHeaders(request)
42+
43+ if (HttpMethod .permitsRequestBody(request.method) && requestBody != null ) {
44+ // If there's a "Expect: 100-continue" header on the request, wait for a "HTTP/1.1 100
45+ // Continue" response before transmitting the request body. If we don't get that, return
46+ // what we did get (such as a 4xx response) without ever transmitting the request body.
47+ if (" 100-continue" .equals(request.header(" Expect" ), ignoreCase = true )) {
5348 exchange.flushRequest()
54- val bufferedRequestBody = exchange.createRequestBody(request, true ).buffer()
55- requestBody.writeTo(bufferedRequestBody)
49+ responseBuilder = exchange.readResponseHeaders(expectContinue = true )
50+ exchange.responseHeadersStart()
51+ invokeStartEvent = false
52+ }
53+ if (responseBuilder == null ) {
54+ if (requestBody.isDuplex()) {
55+ // Prepare a duplex body so that the application can send a request body later.
56+ exchange.flushRequest()
57+ val bufferedRequestBody = exchange.createRequestBody(request, true ).buffer()
58+ requestBody.writeTo(bufferedRequestBody)
59+ } else {
60+ // Write the request body if the "Expect: 100-continue" expectation was met.
61+ val bufferedRequestBody = exchange.createRequestBody(request, false ).buffer()
62+ requestBody.writeTo(bufferedRequestBody)
63+ bufferedRequestBody.close()
64+ }
5665 } else {
57- // Write the request body if the "Expect: 100-continue" expectation was met.
58- val bufferedRequestBody = exchange.createRequestBody(request, false ).buffer()
59- requestBody.writeTo(bufferedRequestBody)
60- bufferedRequestBody.close()
66+ exchange.noRequestBody()
67+ if (! exchange.connection.isMultiplexed) {
68+ // If the "Expect: 100-continue" expectation wasn't met, prevent the HTTP/1 connection
69+ // from being reused. Otherwise we're still obligated to transmit the request body to
70+ // leave the connection in a consistent state.
71+ exchange.noNewExchangesOnConnection()
72+ }
6173 }
6274 } else {
6375 exchange.noRequestBody()
64- if (! exchange.connection.isMultiplexed) {
65- // If the "Expect: 100-continue" expectation wasn't met, prevent the HTTP/1 connection
66- // from being reused. Otherwise we're still obligated to transmit the request body to
67- // leave the connection in a consistent state.
68- exchange.noNewExchangesOnConnection()
69- }
7076 }
71- } else {
72- exchange.noRequestBody()
73- }
7477
75- if (requestBody == null || ! requestBody.isDuplex()) {
76- exchange.finishRequest()
77- }
78- if (responseBuilder == null ) {
79- responseBuilder = exchange.readResponseHeaders(expectContinue = false )!!
80- if (invokeStartEvent) {
81- exchange.responseHeadersStart()
82- invokeStartEvent = false
78+ if (requestBody == null || ! requestBody.isDuplex()) {
79+ exchange.finishRequest()
80+ }
81+ } catch (e: IOException ) {
82+ if (e is ConnectionShutdownException ) {
83+ throw e // No request was sent so there's no response to read.
84+ }
85+ if (! exchange.hasFailure) {
86+ throw e // Don't attempt to read the response; we failed to send the request.
8387 }
88+ sendRequestException = e
8489 }
85- var response = responseBuilder
86- .request(request)
87- .handshake(exchange.connection.handshake())
88- .sentRequestAtMillis(sentRequestMillis)
89- .receivedResponseAtMillis(System .currentTimeMillis())
90- .build()
91- var code = response.code
92- if (code == 100 ) {
93- // Server sent a 100-continue even though we did not request one. Try again to read the actual
94- // response status.
95- responseBuilder = exchange.readResponseHeaders(expectContinue = false )!!
96- if (invokeStartEvent) {
97- exchange.responseHeadersStart()
90+
91+ try {
92+ if (responseBuilder == null ) {
93+ responseBuilder = exchange.readResponseHeaders(expectContinue = false )!!
94+ if (invokeStartEvent) {
95+ exchange.responseHeadersStart()
96+ invokeStartEvent = false
97+ }
9898 }
99- response = responseBuilder
99+ var response = responseBuilder
100100 .request(request)
101101 .handshake(exchange.connection.handshake())
102102 .sentRequestAtMillis(sentRequestMillis)
103103 .receivedResponseAtMillis(System .currentTimeMillis())
104104 .build()
105- code = response.code
106- }
105+ var code = response.code
106+ if (code == 100 ) {
107+ // Server sent a 100-continue even though we did not request one. Try again to read the
108+ // actual response status.
109+ responseBuilder = exchange.readResponseHeaders(expectContinue = false )!!
110+ if (invokeStartEvent) {
111+ exchange.responseHeadersStart()
112+ }
113+ response = responseBuilder
114+ .request(request)
115+ .handshake(exchange.connection.handshake())
116+ .sentRequestAtMillis(sentRequestMillis)
117+ .receivedResponseAtMillis(System .currentTimeMillis())
118+ .build()
119+ code = response.code
120+ }
107121
108- exchange.responseHeadersEnd(response)
122+ exchange.responseHeadersEnd(response)
109123
110- response = if (forWebSocket && code == 101 ) {
111- // Connection is upgrading, but we need to ensure interceptors see a non-null response body.
112- response.newBuilder()
113- .body(EMPTY_RESPONSE )
114- .build()
115- } else {
116- response.newBuilder()
117- .body(exchange.openResponseBody(response))
118- .build()
119- }
120- if (" close" .equals(response.request.header(" Connection" ), ignoreCase = true ) ||
121- " close" .equals(response.header(" Connection" ), ignoreCase = true )) {
122- exchange.noNewExchangesOnConnection()
123- }
124- if ((code == 204 || code == 205 ) && response.body?.contentLength() ? : - 1L > 0L ) {
125- throw ProtocolException (
126- " HTTP $code had non-zero Content-Length: ${response.body?.contentLength()} " )
124+ response = if (forWebSocket && code == 101 ) {
125+ // Connection is upgrading, but we need to ensure interceptors see a non-null response body.
126+ response.newBuilder()
127+ .body(EMPTY_RESPONSE )
128+ .build()
129+ } else {
130+ response.newBuilder()
131+ .body(exchange.openResponseBody(response))
132+ .build()
133+ }
134+ if (" close" .equals(response.request.header(" Connection" ), ignoreCase = true ) ||
135+ " close" .equals(response.header(" Connection" ), ignoreCase = true )) {
136+ exchange.noNewExchangesOnConnection()
137+ }
138+ if ((code == 204 || code == 205 ) && response.body?.contentLength() ? : - 1L > 0L ) {
139+ throw ProtocolException (
140+ " HTTP $code had non-zero Content-Length: ${response.body?.contentLength()} " )
141+ }
142+ return response
143+ } catch (e: IOException ) {
144+ if (sendRequestException != null ) {
145+ sendRequestException.addSuppressed(e)
146+ throw sendRequestException
147+ }
148+ throw e
127149 }
128- return response
129150 }
130151}
0 commit comments