aboutsummaryrefslogtreecommitdiffstats
path: root/src/cowboy_http.erl
diff options
context:
space:
mode:
authorLoïc Hoguin <[email protected]>2017-11-20 21:07:04 +0100
committerLoïc Hoguin <[email protected]>2017-11-20 21:12:05 +0100
commit1af508c4cdad328a14fb889dfebf3fff23bc77d4 (patch)
tree6fc9847d0a83f77f3a36b284734b59f8fb34cbe7 /src/cowboy_http.erl
parent3da9a6eef9910946ec2500ea1f28faa71b85c855 (diff)
downloadcowboy-1af508c4cdad328a14fb889dfebf3fff23bc77d4.tar.gz
cowboy-1af508c4cdad328a14fb889dfebf3fff23bc77d4.tar.bz2
cowboy-1af508c4cdad328a14fb889dfebf3fff23bc77d4.zip
Add more rfc7230 tests and improve transfer-encoding
It's worth noting that transfer-encoding now takes precedence over content-length as recommended by the RFC, so that when both headers are sent we only care about transfer-encoding and explicitly remove content-length from the headers.
Diffstat (limited to 'src/cowboy_http.erl')
-rw-r--r--src/cowboy_http.erl29
1 files changed, 20 insertions, 9 deletions
diff --git a/src/cowboy_http.erl b/src/cowboy_http.erl
index 9b671a9..c94efe2 100644
--- a/src/cowboy_http.erl
+++ b/src/cowboy_http.erl
@@ -598,28 +598,39 @@ default_port(_) -> 80.
request(Buffer, State0=#state{ref=Ref, transport=Transport, peer=Peer, sock=Sock, cert=Cert,
in_streamid=StreamID, in_state=
PS=#ps_header{method=Method, path=Path, qs=Qs, version=Version}},
- Headers, Host, Port) ->
+ Headers0, Host, Port) ->
Scheme = case Transport:secure() of
true -> <<"https">>;
false -> <<"http">>
end,
- {HasBody, BodyLength, TDecodeFun, TDecodeState} = case Headers of
+ {Headers, HasBody, BodyLength, TDecodeFun, TDecodeState} = case Headers0 of
+ #{<<"transfer-encoding">> := TransferEncoding0} ->
+ try cow_http_hd:parse_transfer_encoding(TransferEncoding0) of
+ [<<"chunked">>] ->
+ {maps:remove(<<"content-length">>, Headers0),
+ true, undefined, fun cow_http_te:stream_chunked/2, {0, 0}};
+ _ ->
+ error_terminate(400, State0#state{in_state=PS#ps_header{headers=Headers0}},
+ {stream_error, StreamID, protocol_error,
+ 'Cowboy only supports transfer-encoding: chunked. (RFC7230 3.3.1)'})
+ catch _:_ ->
+ error_terminate(400, State0#state{in_state=PS#ps_header{headers=Headers0}},
+ {stream_error, StreamID, protocol_error,
+ 'The transfer-encoding header is invalid. (RFC7230 3.3.1)'})
+ end;
#{<<"content-length">> := <<"0">>} ->
- {false, 0, undefined, undefined};
+ {Headers0, false, 0, undefined, undefined};
#{<<"content-length">> := BinLength} ->
Length = try
cow_http_hd:parse_content_length(BinLength)
catch _:_ ->
- error_terminate(400, State0#state{in_state=PS#ps_header{headers=Headers}},
+ error_terminate(400, State0#state{in_state=PS#ps_header{headers=Headers0}},
{stream_error, StreamID, protocol_error,
'The content-length header is invalid. (RFC7230 3.3.2)'})
end,
- {true, Length, fun cow_http_te:stream_identity/2, {0, Length}};
- %% @todo Better handling of transfer decoding.
- #{<<"transfer-encoding">> := <<"chunked">>} ->
- {true, undefined, fun cow_http_te:stream_chunked/2, {0, 0}};
+ {Headers0, true, Length, fun cow_http_te:stream_identity/2, {0, Length}};
_ ->
- {false, 0, undefined, undefined}
+ {Headers0, false, 0, undefined, undefined}
end,
Req = #{
ref => Ref,