diff options
author | Loïc Hoguin <[email protected]> | 2013-11-08 21:59:41 +0100 |
---|---|---|
committer | Loïc Hoguin <[email protected]> | 2013-11-08 21:59:41 +0100 |
commit | a485e152ebb449773b92a2ca7557b3c7e495c530 (patch) | |
tree | acfdd8cae6aa88597a11e085e59647967f1045b5 /src | |
parent | 9d2096cd35c05ac43fa34ebe4ac31c9265d263cb (diff) | |
parent | c2e946708e479d647a81afc8d8f59992f92c6a95 (diff) | |
download | cowboy-a485e152ebb449773b92a2ca7557b3c7e495c530.tar.gz cowboy-a485e152ebb449773b92a2ca7557b3c7e495c530.tar.bz2 cowboy-a485e152ebb449773b92a2ca7557b3c7e495c530.zip |
Merge branch 'adrianroe-streaming-http1.1-compat'
Diffstat (limited to 'src')
-rw-r--r-- | src/cowboy_req.erl | 53 |
1 files changed, 33 insertions, 20 deletions
diff --git a/src/cowboy_req.erl b/src/cowboy_req.erl index 452d390..539d961 100644 --- a/src/cowboy_req.erl +++ b/src/cowboy_req.erl @@ -164,7 +164,8 @@ %% Response. resp_compress = false :: boolean(), - resp_state = waiting :: locked | waiting | chunks | done, + resp_state = waiting :: locked | waiting | waiting_stream + | chunks | stream | done, resp_headers = [] :: cowboy:http_headers(), resp_body = <<>> :: iodata() | resp_body_fun() | {non_neg_integer(), resp_body_fun()} @@ -946,7 +947,8 @@ reply(Status, Headers, Body, Req=#http_req{ socket=Socket, transport=Transport, version=Version, connection=Connection, method=Method, resp_compress=Compress, - resp_state=waiting, resp_headers=RespHeaders}) -> + resp_state=RespState, resp_headers=RespHeaders}) + when RespState =:= waiting; RespState =:= waiting_stream -> HTTP11Headers = if Transport =/= cowboy_spdy, Version =:= 'HTTP/1.1' -> [{<<"connection">>, atom_to_connection(Connection)}]; @@ -982,10 +984,12 @@ reply(Status, Headers, Body, Req=#http_req{ if RespType =/= hook, Method =/= <<"HEAD">> -> ChunkFun = fun(IoData) -> chunk(IoData, Req2) end, BodyFun(ChunkFun), - %% Terminate the chunked body for HTTP/1.1 only. - case Version of - 'HTTP/1.0' -> Req2; - _ -> last_chunk(Req2) + %% Send the last chunk if chunked encoding was used. + if + Version =:= 'HTTP/1.0'; RespState =:= waiting_stream -> + Req2; + true -> + last_chunk(Req2) end; true -> Req2 end; @@ -1086,7 +1090,7 @@ chunk(Data, #http_req{socket=Socket, transport=cowboy_spdy, resp_state=chunks}) -> cowboy_spdy:stream_data(Socket, Data); chunk(Data, #http_req{socket=Socket, transport=Transport, - resp_state=chunks, version='HTTP/1.0'}) -> + resp_state=stream}) -> Transport:send(Socket, Data); chunk(Data, #http_req{socket=Socket, transport=Transport, resp_state=chunks}) -> @@ -1136,16 +1140,17 @@ ensure_response(#http_req{resp_state=done}, _) -> ok; %% No response has been sent but everything apparently went fine. %% Reply with the status code found in the second argument. -ensure_response(Req=#http_req{resp_state=waiting}, Status) -> +ensure_response(Req=#http_req{resp_state=RespState}, Status) + when RespState =:= waiting; RespState =:= waiting_stream -> _ = reply(Status, [], [], Req), ok; %% Terminate the chunked body for HTTP/1.1 only. -ensure_response(#http_req{method= <<"HEAD">>, resp_state=chunks}, _) -> - ok; -ensure_response(#http_req{version='HTTP/1.0', resp_state=chunks}, _) -> +ensure_response(#http_req{method= <<"HEAD">>}, _) -> ok; ensure_response(Req=#http_req{resp_state=chunks}, _) -> _ = last_chunk(Req), + ok; +ensure_response(#http_req{}, _) -> ok. %% Private setter/getter API. @@ -1269,19 +1274,27 @@ chunked_response(Status, Headers, Req=#http_req{ resp_headers=[], resp_body= <<>>}}; chunked_response(Status, Headers, Req=#http_req{ version=Version, connection=Connection, - resp_state=waiting, resp_headers=RespHeaders}) -> + resp_state=RespState, resp_headers=RespHeaders}) + when RespState =:= waiting; RespState =:= waiting_stream -> RespConn = response_connection(Headers, Connection), - HTTP11Headers = case Version of - 'HTTP/1.1' -> [ - {<<"connection">>, atom_to_connection(Connection)}, - {<<"transfer-encoding">>, <<"chunked">>}]; - _ -> [] + HTTP11Headers = if + Version =:= 'HTTP/1.0' -> []; + true -> + MaybeTE = if + RespState =:= waiting_stream -> []; + true -> [{<<"transfer-encoding">>, <<"chunked">>}] + end, + [{<<"connection">>, atom_to_connection(Connection)}|MaybeTE] + end, + RespState2 = if + Version =:= 'HTTP/1.1', RespState =:= 'waiting' -> chunks; + true -> stream end, {RespType, Req2} = response(Status, Headers, RespHeaders, [ {<<"date">>, cowboy_clock:rfc1123()}, {<<"server">>, <<"Cowboy">>} |HTTP11Headers], <<>>, Req), - {RespType, Req2#http_req{connection=RespConn, resp_state=chunks, + {RespType, Req2#http_req{connection=RespConn, resp_state=RespState2, resp_headers=[], resp_body= <<>>}}. -spec response(cowboy:http_status(), cowboy:http_headers(), @@ -1313,7 +1326,7 @@ response(Status, Headers, RespHeaders, DefaultHeaders, Body, Req=#http_req{ cowboy_spdy:reply(Socket, status(Status), FullHeaders, Body), ReqPid ! {?MODULE, resp_sent}, normal; - waiting -> + RespState when RespState =:= waiting; RespState =:= waiting_stream -> HTTPVer = atom_to_binary(Version, latin1), StatusLine = << HTTPVer/binary, " ", (status(Status))/binary, "\r\n" >>, @@ -1361,7 +1374,7 @@ response_merge_headers(Headers, RespHeaders, DefaultHeaders) -> merge_headers(Headers, []) -> Headers; merge_headers(Headers, [{<<"set-cookie">>, Value}|Tail]) -> - merge_headers([{<<"set-cookie">>, Value}|Headers], Tail); + merge_headers([{<<"set-cookie">>, Value}|Headers], Tail); merge_headers(Headers, [{Name, Value}|Tail]) -> Headers2 = case lists:keymember(Name, 1, Headers) of true -> Headers; |