aboutsummaryrefslogtreecommitdiffstats
path: root/test
diff options
context:
space:
mode:
authorLoïc Hoguin <[email protected]>2018-04-30 13:47:33 +0200
committerLoïc Hoguin <[email protected]>2018-04-30 13:47:33 +0200
commit8d1f468ac00427184c094392bb5f7a465ab04364 (patch)
tree51530013099ca99e30bc3285472afd44a19cd8d5 /test
parent17349fafc2b64cf424e7bae4e33d3e6bd9deec6e (diff)
downloadcowboy-8d1f468ac00427184c094392bb5f7a465ab04364.tar.gz
cowboy-8d1f468ac00427184c094392bb5f7a465ab04364.tar.bz2
cowboy-8d1f468ac00427184c094392bb5f7a465ab04364.zip
Reject HTTP/2 requests with a body size different than content-length
Diffstat (limited to 'test')
-rw-r--r--test/rfc7540_SUITE.erl98
1 files changed, 90 insertions, 8 deletions
diff --git a/test/rfc7540_SUITE.erl b/test/rfc7540_SUITE.erl
index adc84b5..509d1d3 100644
--- a/test/rfc7540_SUITE.erl
+++ b/test/rfc7540_SUITE.erl
@@ -3778,14 +3778,96 @@ reject_many_pseudo_header_path(Config) ->
% before being passed into a non-HTTP/2 context, such as an HTTP/1.1
% connection, or a generic HTTP server application.
-%% (RFC7540 8.1.2.6)
-% A request or response that includes a payload body can include a
-% content-length header field. A request or response is also malformed
-% if the value of a content-length header field does not equal the sum
-% of the DATA frame payload lengths that form the body. A response
-% that is defined to have no payload, as described in [RFC7230],
-% Section 3.3.2, can have a non-zero content-length header field, even
-% though no content is included in DATA frames.
+reject_data_size_smaller_than_content_length(Config) ->
+ doc("Requests that have a content-length header whose value does not "
+ "match the total length of the DATA frames must be rejected with "
+ "a PROTOCOL_ERROR stream error. (RFC7540 8.1.2.6)"),
+ {ok, Socket} = do_handshake(Config),
+ %% Send a HEADERS frame with a content-length header different
+ %% than the sum of the DATA frame sizes.
+ {HeadersBlock, _} = cow_hpack:encode([
+ {<<":method">>, <<"POST">>},
+ {<<":scheme">>, <<"http">>},
+ {<<":authority">>, <<"localhost">>}, %% @todo Correct port number.
+ {<<":path">>, <<"/long_polling">>},
+ {<<"content-length">>, <<"12">>}
+ ]),
+ ok = gen_tcp:send(Socket, [
+ cow_http2:headers(1, nofin, HeadersBlock),
+ cow_http2:data(1, fin, <<"Hello!">>)
+ ]),
+ %% Receive a PROTOCOL_ERROR stream error.
+ {ok, << _:24, 3:8, _:8, 1:32, 1:32 >>} = gen_tcp:recv(Socket, 13, 6000),
+ ok.
+
+reject_data_size_larger_than_content_length(Config) ->
+ doc("Requests that have a content-length header whose value does not "
+ "match the total length of the DATA frames must be rejected with "
+ "a PROTOCOL_ERROR stream error. (RFC7540 8.1.2.6)"),
+ {ok, Socket} = do_handshake(Config),
+ %% Send a HEADERS frame with a content-length header different
+ %% than the sum of the DATA frame sizes.
+ {HeadersBlock, _} = cow_hpack:encode([
+ {<<":method">>, <<"POST">>},
+ {<<":scheme">>, <<"http">>},
+ {<<":authority">>, <<"localhost">>}, %% @todo Correct port number.
+ {<<":path">>, <<"/long_polling">>},
+ {<<"content-length">>, <<"12">>}
+ ]),
+ ok = gen_tcp:send(Socket, [
+ cow_http2:headers(1, nofin, HeadersBlock),
+ cow_http2:data(1, nofin, <<"Hello! World! Universe!">>),
+ cow_http2:data(1, fin, <<"Multiverse!">>)
+ ]),
+ %% Receive a PROTOCOL_ERROR stream error.
+ {ok, << _:24, 3:8, _:8, 1:32, 1:32 >>} = gen_tcp:recv(Socket, 13, 6000),
+ ok.
+
+reject_content_length_without_data(Config) ->
+ doc("Requests that have a content-length header whose value does not "
+ "match the total length of the DATA frames must be rejected with "
+ "a PROTOCOL_ERROR stream error. (RFC7540 8.1.2.6)"),
+ {ok, Socket} = do_handshake(Config),
+ %% Send a HEADERS frame with a content-length header different
+ %% than the sum of the DATA frame sizes.
+ {HeadersBlock, _} = cow_hpack:encode([
+ {<<":method">>, <<"POST">>},
+ {<<":scheme">>, <<"http">>},
+ {<<":authority">>, <<"localhost">>}, %% @todo Correct port number.
+ {<<":path">>, <<"/long_polling">>},
+ {<<"content-length">>, <<"12">>}
+ ]),
+ ok = gen_tcp:send(Socket, cow_http2:headers(1, fin, HeadersBlock)),
+ %% Receive a PROTOCOL_ERROR stream error.
+ {ok, << _:24, 3:8, _:8, 1:32, 1:32 >>} = gen_tcp:recv(Socket, 13, 6000),
+ ok.
+
+reject_data_size_different_than_content_length_with_trailers(Config) ->
+ doc("Requests that have a content-length header whose value does not "
+ "match the total length of the DATA frames must be rejected with "
+ "a PROTOCOL_ERROR stream error. (RFC7540 8.1.2.6)"),
+ {ok, Socket} = do_handshake(Config),
+ %% Send a HEADERS frame with a content-length header different
+ %% than the sum of the DATA frame sizes.
+ {HeadersBlock, EncodeState} = cow_hpack:encode([
+ {<<":method">>, <<"POST">>},
+ {<<":scheme">>, <<"http">>},
+ {<<":authority">>, <<"localhost">>}, %% @todo Correct port number.
+ {<<":path">>, <<"/long_polling">>},
+ {<<"content-length">>, <<"12">>},
+ {<<"trailer">>, <<"x-checksum">>}
+ ]),
+ {TrailersBlock, _} = cow_hpack:encode([
+ {<<"x-checksum">>, <<"md5:4cc909a007407f3706399b6496babec3">>}
+ ], EncodeState),
+ ok = gen_tcp:send(Socket, [
+ cow_http2:headers(1, nofin, HeadersBlock),
+ cow_http2:data(1, nofin, <<"Hello!">>),
+ cow_http2:headers(1, fin, TrailersBlock)
+ ]),
+ %% Receive a PROTOCOL_ERROR stream error.
+ {ok, << _:24, 3:8, _:8, 1:32, 1:32 >>} = gen_tcp:recv(Socket, 13, 6000),
+ ok.
reject_duplicate_content_length_header(Config) ->
doc("A request with duplicate content-length headers must be rejected "