@@ -153,7 +153,15 @@ fn flow_run(
153
153
SendRequestResult :: RecvResponse ( flow) => flow,
154
154
} ;
155
155
156
- let ( mut response, response_result) = recv_response ( flow, & mut connection, config, timings) ?;
156
+ let is_following_redirects = redirect_count < config. max_redirects ( ) ;
157
+
158
+ let ( mut response, response_result) = recv_response (
159
+ flow,
160
+ & mut connection,
161
+ config,
162
+ timings,
163
+ is_following_redirects,
164
+ ) ?;
157
165
158
166
info ! ( "{:?}" , DebugResponse ( & response) ) ;
159
167
@@ -190,7 +198,7 @@ fn flow_run(
190
198
} ;
191
199
192
200
if response. status ( ) . is_redirection ( ) {
193
- if redirect_count < config . max_redirects ( ) {
201
+ if is_following_redirects {
194
202
let flow = handler. consume_redirect_body ( ) ?;
195
203
196
204
FlowResult :: Redirect ( flow, handler. timings )
@@ -206,7 +214,7 @@ fn flow_run(
206
214
RecvResponseResult :: Redirect ( flow) => {
207
215
cleanup ( connection, flow. must_close_connection ( ) , timings. now ( ) ) ;
208
216
209
- if redirect_count < config . max_redirects ( ) {
217
+ if is_following_redirects {
210
218
FlowResult :: Redirect ( flow, mem:: take ( timings) )
211
219
} else if config. max_redirects_do_error ( ) {
212
220
return Err ( Error :: TooManyRedirects ) ;
@@ -488,14 +496,29 @@ fn recv_response(
488
496
connection : & mut Connection ,
489
497
config : & Config ,
490
498
timings : & mut CallTimings ,
499
+ is_following_redirects : bool ,
491
500
) -> Result < ( Response < ( ) > , RecvResponseResult < ( ) > ) , Error > {
492
501
let response = loop {
493
502
let timeout = timings. next_timeout ( Timeout :: RecvResponse ) ;
494
503
let made_progress = connection. await_input ( timeout) ?;
495
504
496
505
let input = connection. buffers ( ) . input ( ) ;
497
506
498
- let ( amount, maybe_response) = flow. try_response ( input) ?;
507
+ // If cookies are disabled, we can allow ourselves to follow
508
+ // the redirect as soon as we discover the `Location` header.
509
+ // There are plenty of broken servers out there that don't send
510
+ // the finishing \r\n on redirects. With cookies off, we can
511
+ // handle that situation.
512
+ //
513
+ // If cookies are enabled, we risk mising a `Set-Cookie` header
514
+ // with such a strategy.
515
+ let cookies_enabled = cfg ! ( feature = "cookies" ) ;
516
+
517
+ // If we are not following redirects, do not allow partial returned
518
+ // 302 responses.
519
+ let allow_partial_redirect = !cookies_enabled && is_following_redirects;
520
+
521
+ let ( amount, maybe_response) = flow. try_response ( input, allow_partial_redirect) ?;
499
522
500
523
if input. len ( ) > config. max_response_header_size ( ) {
501
524
return Err ( Error :: LargeResponseHeader (
0 commit comments