@@ -1124,36 +1124,49 @@ func (cc *ClientConn) RoundTrip(req *http.Request) (*http.Response, error) {
1124
1124
}
1125
1125
}
1126
1126
1127
+ handleResponseHeaders := func () (* http.Response , error ) {
1128
+ res := cs .res
1129
+ if res .StatusCode > 299 {
1130
+ // On error or status code 3xx, 4xx, 5xx, etc abort any
1131
+ // ongoing write, assuming that the server doesn't care
1132
+ // about our request body. If the server replied with 1xx or
1133
+ // 2xx, however, then assume the server DOES potentially
1134
+ // want our body (e.g. full-duplex streaming:
1135
+ // golang.org/issue/13444). If it turns out the server
1136
+ // doesn't, they'll RST_STREAM us soon enough. This is a
1137
+ // heuristic to avoid adding knobs to Transport. Hopefully
1138
+ // we can keep it.
1139
+ cs .abortRequestBodyWrite ()
1140
+ }
1141
+ res .Request = req
1142
+ res .TLS = cc .tlsState
1143
+ if res .Body == noBody && actualContentLength (req ) == 0 {
1144
+ // If there isn't a request or response body still being
1145
+ // written, then wait for the stream to be closed before
1146
+ // RoundTrip returns.
1147
+ if err := waitDone (); err != nil {
1148
+ return nil , err
1149
+ }
1150
+ }
1151
+ return res , nil
1152
+ }
1153
+
1127
1154
for {
1128
1155
select {
1129
1156
case <- cs .respHeaderRecv :
1130
- res := cs .res
1131
- if res .StatusCode > 299 {
1132
- // On error or status code 3xx, 4xx, 5xx, etc abort any
1133
- // ongoing write, assuming that the server doesn't care
1134
- // about our request body. If the server replied with 1xx or
1135
- // 2xx, however, then assume the server DOES potentially
1136
- // want our body (e.g. full-duplex streaming:
1137
- // golang.org/issue/13444). If it turns out the server
1138
- // doesn't, they'll RST_STREAM us soon enough. This is a
1139
- // heuristic to avoid adding knobs to Transport. Hopefully
1140
- // we can keep it.
1141
- cs .abortRequestBodyWrite ()
1142
- }
1143
- res .Request = req
1144
- res .TLS = cc .tlsState
1145
- if res .Body == noBody && actualContentLength (req ) == 0 {
1146
- // If there isn't a request or response body still being
1147
- // written, then wait for the stream to be closed before
1148
- // RoundTrip returns.
1149
- if err := waitDone (); err != nil {
1150
- return nil , err
1151
- }
1152
- }
1153
- return res , nil
1157
+ return handleResponseHeaders ()
1154
1158
case <- cs .abort :
1155
- waitDone ()
1156
- return nil , cs .abortErr
1159
+ select {
1160
+ case <- cs .respHeaderRecv :
1161
+ // If both cs.respHeaderRecv and cs.abort are signaling,
1162
+ // pick respHeaderRecv. The server probably wrote the
1163
+ // response and immediately reset the stream.
1164
+ // golang.org/issue/49645
1165
+ return handleResponseHeaders ()
1166
+ default :
1167
+ waitDone ()
1168
+ return nil , cs .abortErr
1169
+ }
1157
1170
case <- ctx .Done ():
1158
1171
err := ctx .Err ()
1159
1172
cs .abortStream (err )
0 commit comments