Skip to content
This repository has been archived by the owner on Jan 31, 2024. It is now read-only.

Commit

Permalink
Hopefully more sane error handling.
Browse files Browse the repository at this point in the history
  • Loading branch information
oscarh committed Jul 3, 2009
1 parent 7cd8301 commit 34edf52
Show file tree
Hide file tree
Showing 2 changed files with 22 additions and 27 deletions.
7 changes: 5 additions & 2 deletions src/lhttpc.erl
Original file line number Diff line number Diff line change
Expand Up @@ -65,11 +65,12 @@ stop(_) ->
%% Header = string() | binary() | atom()
%% Value = string() | binary()
%% Timeout = integer() | infinity
%% Result = {ok, {{StatusCode, ReasonPhrase}, Hdrs, Body}}
%% Result = {ok, {{StatusCode, ReasonPhrase}, Hdrs, ResponseBody}}
%% | {error, Reason}
%% StatusCode = integer()
%% ReasonPhrase = string()
%% Body = binary()
%% ResponseBody = binary()
%% Reason = connection_closed | connect_timeout | timeout
%% @doc Sends a request without a body.
%% Would be the same as calling `request(URL, Method, Hdrs, [], Timeout)',
%% that is {@link request/5} with an empty body (`Body' could also be `<<>>').
Expand All @@ -92,6 +93,7 @@ request(URL, Method, Hdrs, Timeout) ->
%% StatusCode = integer()
%% ReasonPhrase = string()
%% ResponseBody = binary()
%% Reason = connection_closed | connect_timeout | timeout
%% @doc Sends a request with a body.
%% Would be the same as calling
%% `request(URL, Method, Hdrs, Body, Timeout, [])', that is {@link request/6} with
Expand Down Expand Up @@ -119,6 +121,7 @@ request(URL, Method, Hdrs, Body, Timeout) ->
%% StatusCode = integer()
%% ReasonPhrase = string()
%% ResponseBody = binary()
%% Reason = connection_closed | connect_timeout | timeout
%% @doc Sends a request with a body.
%% `URL' is expected to be a valid URL:
%% `scheme://host[:port][/path]'.
Expand Down
42 changes: 17 additions & 25 deletions src/lhttpc_client.erl
Original file line number Diff line number Diff line change
Expand Up @@ -62,10 +62,10 @@ request(From, URL, Method, Hdrs, Body, Options) ->
Result = try
execute(URL, Method, Hdrs, Body, Options)
catch
closed ->
{response, self(), {error, connection_closed}};
Reason ->
{response, self(), {error, Reason}};
error:closed ->
{response, self(), {error, connection_closed}};
error:Error ->
{exit, self(), {Error, erlang:get_stacktrace()}}
end,
Expand All @@ -91,9 +91,9 @@ execute(URL, Method, Hdrs, Body, Options) ->
attempts = 1 + proplists:get_value(send_retry, Options, 1)
},
Response = case send_request(State) of
{ok, R, undefined} ->
{R, undefined} ->
{ok, R};
{ok, R, NewSocket} ->
{R, NewSocket} ->
% The socket we ended up doing the request over is returned
% here, it might be the same as Socket, but we don't know.
% I've noticed that we don't want to give send sockets that we
Expand All @@ -110,15 +110,13 @@ execute(URL, Method, Hdrs, Body, Options) ->
_ ->
ok
end,
{ok, R};
{error, Reason} ->
throw(Reason)
{ok, R}
end,
{response, self(), Response}.

send_request(#client_state{attempts = 0}) ->
% Don't try again if the number of allowed attempts is 0.
{error, connection_closed};
throw(connection_closed);
send_request(#client_state{socket = undefined} = State) ->
Host = State#client_state.host,
Port = State#client_state.port,
Expand All @@ -134,7 +132,7 @@ send_request(#client_state{socket = undefined} = State) ->
{error, timeout} ->
throw(connect_timeout);
{error, Reason} ->
throw(Reason)
erlang:error(Reason)
end;
send_request(State) ->
Socket = State#client_state.socket,
Expand All @@ -143,23 +141,17 @@ send_request(State) ->
case lhttpc_sock:send(Socket, Request, Ssl) of
ok ->
lhttpc_sock:setopts(Socket, [{packet, http}], Ssl),
case read_response(State, nil, nil, [], <<>>) of
{ok, Response, NewSocket} ->
{ok, Response, NewSocket};
{error, Reason} ->
lhttpc_sock:close(Socket, Ssl),
throw(Reason)
end;
read_response(State, nil, nil, [], <<>>);
{error, closed} ->
lhttpc_sock:close(Socket, Ssl),
NewState = State#client_state{
socket = undefined,
attempts = State#client_state.attempts - 1
},
send_request(NewState);
Other ->
{error, Reason} ->
lhttpc_sock:close(Socket, Ssl),
Other
erlang:error(Reason)
end.

read_response(State, Vsn, Status, Hdrs, Body) ->
Expand All @@ -175,7 +167,7 @@ read_response(State, Vsn, Status, Hdrs, Body) ->
{ok, http_eoh} ->
lhttpc_sock:setopts(Socket, [{packet, raw}], Ssl),
{NewBody, NewHdrs, NewSocket} = read_body(Vsn, Hdrs, Ssl, Socket),
{ok, {Status, NewHdrs, NewBody}, NewSocket};
{{Status, NewHdrs, NewBody}, NewSocket};
{error, closed} ->
% Either we only noticed that the socket was closed after we
% sent the request, the server closed it just after we put
Expand All @@ -189,7 +181,7 @@ read_response(State, Vsn, Status, Hdrs, Body) ->
},
send_request(NewState);
{error, Reason} ->
throw(Reason)
erlang:error(Reason)
end.

read_body(Vsn, Hdrs, Ssl, Socket) ->
Expand Down Expand Up @@ -222,7 +214,7 @@ read_length(Hdrs, Ssl, Socket, Length) ->
end,
{Data, Hdrs, NewSocket};
{error, Reason} ->
throw(Reason)
erlang:error(Reason)
end.

read_chunked_body(Socket, Ssl, Hdrs, Chunks) ->
Expand All @@ -239,7 +231,7 @@ read_chunked_body(Socket, Ssl, Hdrs, Chunks) ->
read_chunked_body(Socket, Ssl, Hdrs, [Chunk | Chunks])
end;
{error, Reason} ->
throw(Reason)
erlang:error(Reason)
end.

chunk_size(Bin) ->
Expand All @@ -260,7 +252,7 @@ read_chunk(Socket, Ssl, Size) ->
{ok, Data} ->
erlang:error({invalid_chunk, Data});
{error, Reason} ->
throw(Reason)
erlang:error(Reason)
end.

read_trailers(Socket, Ssl, Hdrs) ->
Expand All @@ -271,7 +263,7 @@ read_trailers(Socket, Ssl, Hdrs) ->
Header = {lhttpc_lib:maybe_atom_to_list(Name), Value},
read_trailers(Socket, Ssl, [Header | Hdrs]);
{error, {http_error, Data}} ->
throw({bad_trailer, Data})
erlang:error({bad_trailer, Data})
end.

read_infinite_body(Socket, {1, 1}, Hdrs, Ssl) ->
Expand All @@ -294,5 +286,5 @@ read_until_closed(Socket, Acc, Hdrs, Ssl) ->
lhttpc_sock:close(Socket, Ssl),
{Acc, Hdrs, undefined}; % The socket has been closed
{error, Reason} ->
throw(Reason)
erlang:error(Reason)
end.

0 comments on commit 34edf52

Please sign in to comment.