Permalink
Browse files

Consistent error handling when streaming

The lhttpc_client process, spawned by the caller and linked to
it, used erlang:error/1 when an error was received from the socket.
This is not friendly for callers to deal with errors, as they
have to trap exits or monitor the lhttc_client process. It also
didn't respect the spec/documentation for lhttpc:get_body_part/1,2
because {error, Reason} could never be returned.
  • Loading branch information...
1 parent 4e5edc2 commit fbfed83da02c28a380957d71111909b925cad96e @fdmanana committed Jul 5, 2012
Showing with 25 additions and 31 deletions.
  1. +6 −2 src/lhttpc.erl
  2. +19 −29 src/lhttpc_client.erl
View
@@ -507,7 +507,9 @@ get_body_part(Pid) ->
%% `{partial_download, PartialDownloadOptions}' is used.
%% `Timeout' is the timeout for reading the next body part in milliseconds.
%% `http_eob' marks the end of the body. If there were Trailers in the
-%% response those are returned with `http_eob' as well.
+%% response those are returned with `http_eob' as well.
+%% If it evers returns an error, no further calls to this function should
+%% be done.
%% @end
-spec get_body_part(pid(), timeout()) ->
{ok, binary()} |
@@ -519,7 +521,9 @@ get_body_part(Pid, Timeout) ->
Pid ! {ack, self()},
{ok, Bin};
{http_eob, Pid, Trailers} ->
- {ok, {http_eob, Trailers}}
+ {ok, {http_eob, Trailers}};
+ {error, Pid, Reason} ->
+ {error, Reason}
after Timeout ->
kill_client(Pid)
end.
View
@@ -489,48 +489,38 @@ read_partial_finite_body(State = #client_state{requester = To}, Hdrs,
exit(normal)
end;
read_partial_finite_body(State, Hdrs, ContentLength, Window) when Window >= 0->
- Bin = read_body_part(State, ContentLength),
- State#client_state.requester ! {body_part, self(), Bin},
- To = State#client_state.requester,
- receive
- {ack, To} ->
- Length = ContentLength - iolist_size(Bin),
- read_partial_finite_body(State, Hdrs, Length, Window);
- {'DOWN', _, process, To, _} ->
+ case read_body_part(State, ContentLength) of
+ {ok, Bin} ->
+ State#client_state.requester ! {body_part, self(), Bin},
+ To = State#client_state.requester,
+ receive
+ {ack, To} ->
+ Length = ContentLength - iolist_size(Bin),
+ read_partial_finite_body(State, Hdrs, Length, Window);
+ {'DOWN', _, process, To, _} ->
+ exit(normal)
+ after 0 ->
+ Length = ContentLength - iolist_size(Bin),
+ read_partial_finite_body(State, Hdrs, Length, lhttpc_lib:dec(Window))
+ end;
+ {error, Reason} ->
+ State#client_state.requester ! {error, self(), Reason},
exit(normal)
- after 0 ->
- Length = ContentLength - iolist_size(Bin),
- read_partial_finite_body(State, Hdrs, Length, lhttpc_lib:dec(Window))
end.
read_body_part(#client_state{part_size = infinity} = State, _ContentLength) ->
- case lhttpc_sock:recv(State#client_state.socket, State#client_state.ssl) of
- {ok, Data} ->
- Data;
- {error, Reason} ->
- erlang:error(Reason)
- end;
+ lhttpc_sock:recv(State#client_state.socket, State#client_state.ssl);
read_body_part(#client_state{part_size = PartSize} = State, ContentLength)
when PartSize =< ContentLength ->
Socket = State#client_state.socket,
Ssl = State#client_state.ssl,
PartSize = State#client_state.part_size,
- case lhttpc_sock:recv(Socket, PartSize, Ssl) of
- {ok, Data} ->
- Data;
- {error, Reason} ->
- erlang:error(Reason)
- end;
+ lhttpc_sock:recv(Socket, PartSize, Ssl);
read_body_part(#client_state{part_size = PartSize} = State, ContentLength)
when PartSize > ContentLength ->
Socket = State#client_state.socket,
Ssl = State#client_state.ssl,
- case lhttpc_sock:recv(Socket, ContentLength, Ssl) of
- {ok, Data} ->
- Data;
- {error, Reason} ->
- erlang:error(Reason)
- end.
+ lhttpc_sock:recv(Socket, ContentLength, Ssl).
read_length(Hdrs, Ssl, Socket, Length) ->
case lhttpc_sock:recv(Socket, Length, Ssl) of

0 comments on commit fbfed83

Please sign in to comment.