@@ -166,45 +166,70 @@ maybe_continue(Parent, Owner, Ref, #client{transport=Transport,
166166% % - {redirect, To, Headers}
167167% % - {see_other, To, Headers} for status 303 and POST requests.
168168maybe_redirect (Parent , Owner , Ref , StatusInt , Reason ,
169- # client {transport = Transport ,
170- socket = Socket ,
171- method = Method ,
172- follow_redirect = true }= Client ) ->
169+ # client {method = Method , follow_redirect = true }= Client ) ->
173170 case lists :member (StatusInt , [301 , 302 , 307 , 308 ]) of
174171 true ->
175- Transport :setopts (Socket , [{active , false }]),
176- case parse (Client ) of
177- {loop , Client2 } ->
178- maybe_redirect (Parent , Owner , Ref , StatusInt ,
179- Reason , Client2 );
180- {ok , {headers , Headers }, Client2 } ->
181- Location = hackney :redirect_location (Headers ),
182- case {Location , lists :member (Method , [get , head ])} of
183- {undefined , _ } ->
172+ maybe_redirect_1 (Parent , Owner , Ref , Reason , Client );
173+ false when StatusInt =:= 303 , Method =:= <<" POST" >> ->
174+ maybe_redirect_2 (Parent , Owner , Ref , Reason , Client );
175+ _ ->
176+ Owner ! {hackney_response , Ref , {status , StatusInt , Reason }},
177+ maybe_continue (Parent , Owner , Ref , Client )
178+ end ;
179+ maybe_redirect (Parent , Owner , Ref , StatusInt , Reason , Client ) ->
180+ Owner ! {hackney_response , Ref , {status , StatusInt , Reason }},
181+ maybe_continue (Parent , Owner , Ref , Client ).
182+
183+ % % The first case for redirections are status codes 301, 302, 307 and 308.
184+ % % In this case {redirect, Location, Headers} is sent to the owner if
185+ % % the request is valid.
186+ maybe_redirect_1 (Parent , Owner , Ref , Reason ,
187+ # client {transport = Transport , socket = Socket }= Client ) ->
188+ Transport :setopts (Socket , [{active , false }]),
189+ case parse (Client ) of
190+ {loop , Client2 } ->
191+ maybe_redirect_1 (Parent , Owner , Ref , Reason , Client2 );
192+ {more , Client2 , Rest } ->
193+ Continuation = fun (Client3 ) ->
194+ maybe_redirect_1 (Parent , Owner , Ref , Reason , Client3 )
195+ end ,
196+ async_recv (Parent , Owner , Ref , Client2 , Rest , Continuation );
197+ {ok , {headers , Headers }, Client2 } ->
198+ Location = hackney :redirect_location (Headers ),
199+ case Location of
200+ undefined ->
201+ Owner ! {hackney_response , Ref , {error ,invalid_redirection }},
202+ hackney_manager :handle_error (Client2 );
203+ _ ->
204+ case hackney_response :skip_body (Client2 ) of
205+ {skip , Client3 } ->
206+ hackney_manager :store_state (Client3 ),
184207 Owner ! {hackney_response , Ref ,
185- {error ,invalid_redirection }},
186- hackney_manager :handle_error (Client2 );
187- {_ , _ } ->
188- case hackney_response :skip_body (Client2 ) of
189- {skip , Client3 } ->
190- hackney_manager :store_state (Client3 ),
191- Owner ! {hackney_response , Ref ,
192- {redirect , Location , Headers }};
193- Error ->
194- Owner ! {hackney_response , Ref , Error },
195- hackney_manager :handle_error (Client2 )
208+ {redirect , Location , Headers }};
209+ Error ->
210+ Owner ! {hackney_response , Ref , Error },
211+ hackney_manager :handle_error (Client2 )
196212 end
197213 end ;
198- {error , Error } ->
199- Owner ! {hackney_response , Ref , {error , Error }},
200- hackney_manager :handle_error (Client )
201- end ;
202- false when StatusInt =:= 303 , Method =:= post ->
214+ {error , Error } ->
215+ Owner ! {hackney_response , Ref , {error , Error }},
216+ hackney_manager :handle_error (Client )
217+ end .
218+
219+ % % The second case is for status code 303 and POST requests.
220+ % % This results in sending {see_other, Location, Headers} to the owner.
221+ maybe_redirect_2 (Parent , Owner , Ref , Reason ,
222+ # client {transport = Transport ,
223+ socket = Socket }= Client ) ->
203224 Transport :setopts (Socket , [{active , false }]),
204225 case parse (Client ) of
205226 {loop , Client2 } ->
206- maybe_redirect (Parent , Owner , Ref , StatusInt ,
207- Reason , Client2 );
227+ maybe_redirect_2 (Parent , Owner , Ref , Reason , Client2 );
228+ {more , Client2 , Rest } ->
229+ Continuation = fun (Client3 ) ->
230+ maybe_redirect_2 (Parent , Owner , Ref , Reason , Client3 )
231+ end ,
232+ async_recv (Parent , Owner , Ref , Client2 , Rest , Continuation );
208233 {ok , {headers , Headers }, Client2 } ->
209234 case hackney :redirect_location (Headers ) of
210235 undefined ->
@@ -225,21 +250,19 @@ maybe_redirect(Parent, Owner, Ref, StatusInt, Reason,
225250 {error , Error } ->
226251 Owner ! {hackney_response , Ref , {error , Error }},
227252 hackney_manager :handle_error (Client )
228- end ;
229- _ ->
230- Owner ! {hackney_response , Ref , {status , StatusInt , Reason }},
231- maybe_continue (Parent , Owner , Ref , Client )
232- end ;
233- maybe_redirect (Parent , Owner , Ref , StatusInt , Reason , Client ) ->
234- Owner ! {hackney_response , Ref , {status , StatusInt , Reason }},
235- maybe_continue (Parent , Owner , Ref , Client ).
253+ end .
236254
237255
256+ async_recv (Parent , Owner , Ref , Client , Buffer ) ->
257+ Continuation = fun (Client2 ) ->
258+ stream_loop (Parent , Owner , Ref , Client2 )
259+ end ,
260+ async_recv (Parent , Owner , Ref , Client , Buffer , Continuation ).
261+
238262async_recv (Parent , Owner , Ref ,
239263 # client {transport = Transport ,
240264 socket = TSock ,
241- recv_timeout = Timeout }= Client , Buffer ) ->
242-
265+ recv_timeout = Timeout }= Client , Buffer , Continuation ) ->
243266 {OK , Closed , Error } = Transport :messages (TSock ),
244267 Sock = raw_sock (TSock ),
245268 Transport :setopts (TSock , [{active , once }]),
@@ -263,7 +286,7 @@ async_recv(Parent, Owner, Ref,
263286 Transport :controlling_process (TSock , From ),
264287 From ! {Ref , ok };
265288 {OK , Sock , Data } ->
266- stream_loop ( Parent , Owner , Ref , Client # client {buffer = Data });
289+ Continuation ( Client # client {buffer = Data });
267290 {Closed , Sock } ->
268291 case Client # client .response_state of
269292 on_body when (Version =:= {1 , 0 } orelse Version =:= {1 , 1 })
0 commit comments