@@ -20,6 +20,7 @@ import java.net.ProtocolException
20
20
import okhttp3.Interceptor
21
21
import okhttp3.Response
22
22
import okhttp3.internal.EMPTY_RESPONSE
23
+ import okhttp3.internal.http2.ConnectionShutdownException
23
24
import okio.buffer
24
25
25
26
/* * 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 {
33
34
val requestBody = request.body
34
35
val sentRequestMillis = System .currentTimeMillis()
35
36
36
- exchange.writeRequestHeaders(request)
37
-
38
37
var invokeStartEvent = true
39
38
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 )) {
53
48
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
+ }
56
65
} 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
+ }
61
73
}
62
74
} else {
63
75
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
- }
70
76
}
71
- } else {
72
- exchange.noRequestBody()
73
- }
74
77
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.
83
87
}
88
+ sendRequestException = e
84
89
}
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
+ }
98
98
}
99
- response = responseBuilder
99
+ var response = responseBuilder
100
100
.request(request)
101
101
.handshake(exchange.connection.handshake())
102
102
.sentRequestAtMillis(sentRequestMillis)
103
103
.receivedResponseAtMillis(System .currentTimeMillis())
104
104
.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
+ }
107
121
108
- exchange.responseHeadersEnd(response)
122
+ exchange.responseHeadersEnd(response)
109
123
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
127
149
}
128
- return response
129
150
}
130
151
}
0 commit comments