Skip to content

Commit

Permalink
fix redirection
Browse files Browse the repository at this point in the history
  • Loading branch information
benoitc committed Dec 1, 2013
1 parent d9e7d9a commit a5f9e34
Show file tree
Hide file tree
Showing 2 changed files with 43 additions and 33 deletions.
31 changes: 20 additions & 11 deletions src/hackney.erl
Expand Up @@ -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;
Expand Down Expand Up @@ -522,16 +522,14 @@ 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),
#hackney_url{transport=RedirectTransport,
host=RedirectHost,
port=RedirectPort}=RedirectUrl,
RedirectRequest = make_request(Method, RedirectUrl, Headers, Body),

%% make a request without any redirection
#client{transport=Transport,
host=Host,
Expand All @@ -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) ->
Expand Down
45 changes: 23 additions & 22 deletions src/hackney_connect.erl
Expand Up @@ -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
Expand All @@ -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) ->
Expand Down Expand Up @@ -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
Expand All @@ -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} ->
Expand Down

0 comments on commit a5f9e34

Please sign in to comment.