From a5f9e34f20e4b5fd4774c7988444b8bd66476434 Mon Sep 17 00:00:00 2001 From: benoitc Date: Sun, 1 Dec 2013 09:43:16 +0100 Subject: [PATCH] fix redirection --- src/hackney.erl | 31 ++++++++++++++++++---------- src/hackney_connect.erl | 45 +++++++++++++++++++++-------------------- 2 files changed, 43 insertions(+), 33 deletions(-) diff --git a/src/hackney.erl b/src/hackney.erl index a8d5c64e..42a559ca 100644 --- a/src/hackney.erl +++ b/src/hackney.erl @@ -188,8 +188,8 @@ request(Method, #hackney_url{}=URL, Headers, Body, Options0) -> Request = make_request(Method, URL, Headers, Body), case hackney_http_proxy:maybe_proxy(Transport, Host, Port, Options) of - {ok, State} -> - send_request(State, Request); + {ok, Ref} -> + send_request(Ref, Request); Error -> Error end; @@ -522,8 +522,7 @@ maybe_redirect(Resp, _Req, _Tries) -> redirect(Client0, {Method, NewLocation, Headers, Body}) -> %% skip the body - {ok, Client} = skip_body(Client0), - + {ok, Client} = hackney_response:skip_body(Client0), %% close the connection if we don't use a pool RedirectUrl = hackney_url:parse_url(NewLocation), @@ -531,7 +530,6 @@ redirect(Client0, {Method, NewLocation, Headers, Body}) -> host=RedirectHost, port=RedirectPort}=RedirectUrl, RedirectRequest = make_request(Method, RedirectUrl, Headers, Body), - %% make a request without any redirection #client{transport=Transport, host=Host, @@ -542,27 +540,38 @@ redirect(Client0, {Method, NewLocation, Headers, Body}) -> Opts = lists:keystore(follow_redirect, 1, Opts0, {follow_redirect, false}), - %% update the state with the redirect info Client1 = Client#client{transport=RedirectTransport, host=RedirectHost, port=RedirectPort, options=Opts}, - + %% send a request to the new location case send_request(Client1, RedirectRequest) of + {ok, S, H, RedirectRef} when is_reference(RedirectRef) -> + RedirectState = hackney_manager:get_state(RedirectRef), + RedirectState1 = case Redirect of + nil -> + RedirectState#client{redirect=Redirect, + options=Opts0}; + _ -> + NewRedirect = {Transport, Host, Port, Opts0}, + RedirectState#client{redirect=NewRedirect, + options=Opts0} + end, + {ok, S, H, RedirectState1}; {ok, S, H, RedirectClient} when Redirect /= nil -> NewClient = RedirectClient#client{redirect=Redirect, options=Opts0}, - reply_response({ok, S, H, NewClient}, Client1); + {ok, S, H, NewClient}; {ok, S, H, RedirectClient} -> NewRedirect = {Transport, Host, Port, Opts0}, + io:format("got ~p~n", [RedirectClient]), NewClient = RedirectClient#client{redirect=NewRedirect, options=Opts0}, - reply_response({ok, S, H, NewClient}, Client1); - + {ok, S, H, NewClient}; Error -> - reply_response(Error, Client1) + Error end. redirect_location(Headers) -> diff --git a/src/hackney_connect.erl b/src/hackney_connect.erl index cf52142e..06f53847 100644 --- a/src/hackney_connect.erl +++ b/src/hackney_connect.erl @@ -58,10 +58,23 @@ create_connection(Transport, Host, Port, Options, Dynamic) %% @doc connect a socket and create a client state. -maybe_connect(#client{state=connected, redirect=nil}=Client) -> +%% +maybe_connect(#client{state=closed, redirect=nil}=Client) -> + %% the socket has been closed, reconnect it. + #client{transport=Transport, + host=Host, + port=Port} = Client, + reconnect(Host, Port, Transport, Client); +maybe_connect(#client{state=closed, redirect=Redirect}=Client) -> + %% connection closed after a redirection, reinit the options and + %% reconnect it. + {Transport, Host, Port, Options} = Redirect, + Client1 = Client#client{options=Options, + redirect=nil}, + reconnect(Host, Port, Transport, Client1); +maybe_connect(#client{redirect=nil}=Client) -> {ok, Client}; - -maybe_connect(#client{state=connected, redirect=Redirect}=Client) -> +maybe_connect(#client{redirect=Redirect}=Client) -> #client{socket=Socket, socket_ref=Ref, pool_handler=Handler}=Client, %% the connection was redirected. If we are using a pool, checkin %% the socket and create the newone, else close the current socket @@ -76,20 +89,8 @@ maybe_connect(#client{state=connected, redirect=Redirect}=Client) -> {Transport, Host, Port, Options} = Redirect, Client1 = Client#client{options=Options, redirect=nil}, - reconnect(Transport, Host, Port, Client1); -maybe_connect(#client{state=closed, redirect=Redirect}=Client) -> - %% connection closed after a redirection, reinit the options and - %% reconnect it. - {Transport, Host, Port, Options} = Redirect, - Client1 = Client#client{options=Options, - redirect=nil}, - reconnect(Transport, Host, Port, Client1); -maybe_connect(#client{state=closed, redirect=nil}=Client) -> - %% the socket has been closed, reconnect it. - #client{transport=Transport, - host=Host, - port=Port} = Client, - reconnect(Transport, Host, Port, Client). + reconnect(Host, Port, Transport, Client1). + %% @doc add set sockets options in the client set_sockopts(#client{transport=Transport, socket=Skt}, Options) -> @@ -133,7 +134,7 @@ reconnect(Host, Port, Transport, State) -> %% socket_from_pool(Host, Port, Transport, #client{options=Opts, - request_ref=Ref0}=Client) -> + request_ref=ReqRef0}=Client) -> PoolHandler = hackney_app:get_app_env(pool_handler, hackney_pool), case PoolHandler:checkout(Host, Port, Transport, Client) of @@ -156,13 +157,13 @@ socket_from_pool(Host, Port, Transport, #client{options=Opts, buffer = <<>>}, - FinalClient = case is_reference(Ref0) of + FinalClient = case is_reference(ReqRef0) of true -> - ok = hackney_manager:update_state(Ref0, Client1), + ok = hackney_manager:update_state(ReqRef0, Client1), Client1; false -> - Ref = hackney_manager:new_request(Client1), - Client1#client{request_ref=Ref} + RequestRef = hackney_manager:new_request(Client1), + Client1#client{request_ref=RequestRef} end, {ok, FinalClient}; {error, no_socket, Ref} ->