diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/cowboy_http_protocol.erl | 13 | ||||
-rw-r--r-- | src/cowboy_http_req.erl | 18 |
2 files changed, 26 insertions, 5 deletions
diff --git a/src/cowboy_http_protocol.erl b/src/cowboy_http_protocol.erl index 221e316..302df26 100644 --- a/src/cowboy_http_protocol.erl +++ b/src/cowboy_http_protocol.erl @@ -198,9 +198,9 @@ handler_terminate(HandlerState, Req=#http_req{buffer=Buffer}, HandlerRes = (catch Handler:terminate( Req#http_req{resp_state=locked}, HandlerState)), BodyRes = ensure_body_processed(Req), - ensure_response(Req, State), - case {HandlerRes, BodyRes, State#state.connection} of - {ok, ok, keepalive} -> + RespRes = ensure_response(Req, State), + case {HandlerRes, BodyRes, RespRes, State#state.connection} of + {ok, ok, ok, keepalive} -> ?MODULE:parse_request(State#state{buffer=Buffer}); _Closed -> terminate(State) @@ -223,7 +223,12 @@ ensure_response(#http_req{resp_state=done}, _State) -> %% No response has been sent but everything apparently went fine. %% Reply with 204 No Content to indicate this. ensure_response(#http_req{resp_state=waiting}, State) -> - error_response(204, State). + error_response(204, State); +%% Close the chunked reply. +ensure_response(#http_req{socket=Socket, transport=Transport, + resp_state=chunks}, _State) -> + Transport:send(Socket, <<"0\r\n\r\n">>), + close. -spec error_response(Code::http_status(), State::#state{}) -> ok. error_response(Code, #state{socket=Socket, diff --git a/src/cowboy_http_req.erl b/src/cowboy_http_req.erl index c430020..60f0b55 100644 --- a/src/cowboy_http_req.erl +++ b/src/cowboy_http_req.erl @@ -30,7 +30,7 @@ ]). %% Request Body API. -export([ - reply/4 + reply/4, chunked_reply/3, chunk/2 ]). %% Response API. -include("include/http.hrl"). @@ -192,6 +192,22 @@ reply(Code, Headers, Body, Req=#http_req{socket=Socket, Transport:send(Socket, [Head, Body]), {ok, Req#http_req{resp_state=done}}. +-spec chunked_reply(Code::http_status(), Headers::http_headers(), + Req::#http_req{}) -> {ok, Req::#http_req{}}. +chunked_reply(Code, Headers, Req=#http_req{socket=Socket, transport=Transport, + resp_state=waiting}) -> + Head = response_head(Code, Headers, [ + {<<"Connection">>, <<"close">>}, + {<<"Transfer-Encoding">>, <<"chunked">>} + ]), + Transport:send(Socket, Head), + {ok, Req#http_req{resp_state=chunks}}. + +-spec chunk(Data::iodata(), Req::#http_req{}) -> ok. +chunk(Data, #http_req{socket=Socket, transport=Transport, resp_state=chunks}) -> + Transport:send(Socket, [integer_to_list(iolist_size(Data), 16), + <<"\r\n">>, Data, <<"\r\n">>]). + %% Internal. -spec parse_qs(Qs::binary()) -> list({Name::binary(), Value::binary() | true}). |