From 84d7671e91bb2dee2081172dbf651860134ae75e Mon Sep 17 00:00:00 2001 From: rambocoder Date: Wed, 6 Mar 2013 08:50:45 -0500 Subject: Check the length before reading the body in body/1 and body_qs/1 --- test/http_SUITE.erl | 42 +++++++++++++++++++++++++++++++++++++++++ test/http_handler_body_qs.erl | 39 ++++++++++++++++++++++++++++++++++++++ test/http_handler_echo_body.erl | 34 +++++++++++++++++++++++++++++---- 3 files changed, 111 insertions(+), 4 deletions(-) create mode 100644 test/http_handler_body_qs.erl (limited to 'test') diff --git a/test/http_SUITE.erl b/test/http_SUITE.erl index bd76f00..911efb8 100644 --- a/test/http_SUITE.erl +++ b/test/http_SUITE.erl @@ -30,6 +30,9 @@ -export([check_status/1]). -export([chunked_response/1]). -export([echo_body/1]). +-export([echo_body_max_length/1]). +-export([echo_body_qs/1]). +-export([echo_body_qs_max_length/1]). -export([error_chain_handle_after_reply/1]). -export([error_chain_handle_before_reply/1]). -export([error_handle_after_reply/1]). @@ -102,6 +105,9 @@ groups() -> check_status, chunked_response, echo_body, + echo_body_max_length, + echo_body_qs, + echo_body_qs_max_length, error_chain_handle_after_reply, error_chain_handle_before_reply, error_handle_after_reply, @@ -348,6 +354,7 @@ init_dispatch(Config) -> {file, <<"test_file.css">>}]}, {"/multipart", http_handler_multipart, []}, {"/echo/body", http_handler_echo_body, []}, + {"/echo/body_qs", http_handler_body_qs, []}, {"/param_all", rest_param_all, []}, {"/bad_accept", rest_simple_resource, []}, {"/simple", rest_simple_resource, []}, @@ -533,6 +540,41 @@ echo_body(Config) -> {ok, Body, _} = cowboy_client:response_body(Client3) end || Size <- lists:seq(MTU - 500, MTU)]. +%% Check if sending request whose size is bigger than 1000000 bytes causes 413 +echo_body_max_length(Config) -> + Client = ?config(client, Config), + Body = <<$a:8000008>>, + {ok, Client2} = cowboy_client:request(<<"POST">>, + build_url("/echo/body", Config), + [{<<"connection">>, <<"close">>}], + Body, Client), + {ok, 413, _, _} = cowboy_client:response(Client2). + +% check if body_qs echo's back results +echo_body_qs(Config) -> + Client = ?config(client, Config), + Body = <<"echo=67890">>, + {ok, Client2} = cowboy_client:request(<<"POST">>, + build_url("/echo/body_qs", Config), + [{<<"connection">>, <<"close">>}], + Body, Client), + {ok, 200, _, Client3} = cowboy_client:response(Client2), + {ok, <<"67890">>, _} = cowboy_client:response_body(Client3). + +%% Check if sending request whose size is bigger 16000 bytes causes 413 +echo_body_qs_max_length(Config) -> + Client = ?config(client, Config), + DefaultMaxBodyQsLength = 16000, + % subtract "echo=" minus 1 byte from max to hit the limit + Bits = (DefaultMaxBodyQsLength - 4) * 8, + AppendedBody = <<$a:Bits>>, + Body = <<"echo=", AppendedBody/binary>>, + {ok, Client2} = cowboy_client:request(<<"POST">>, + build_url("/echo/body_qs", Config), + [{<<"connection">>, <<"close">>}], + Body, Client), + {ok, 413, _, _} = cowboy_client:response(Client2). + error_chain_handle_after_reply(Config) -> Client = ?config(client, Config), {ok, Client2} = cowboy_client:request(<<"GET">>, diff --git a/test/http_handler_body_qs.erl b/test/http_handler_body_qs.erl new file mode 100644 index 0000000..306f4dc --- /dev/null +++ b/test/http_handler_body_qs.erl @@ -0,0 +1,39 @@ +%% Feel free to use, reuse and abuse the code in this file. + +-module(http_handler_body_qs). +-behaviour(cowboy_http_handler). +-export([init/3, handle/2, terminate/3]). + +init({_, http}, Req, _) -> + {ok, Req, undefined}. + +handle(Req, State) -> + {Method, Req2} = cowboy_req:method(Req), + HasBody = cowboy_req:has_body(Req2), + {ok, Req3} = maybe_echo(Method, HasBody, Req2), + {ok, Req3, State}. + +maybe_echo(<<"POST">>, true, Req) -> + case cowboy_req:body_qs(Req) of + {error,badlength} -> + echo(badlength, Req); + {ok, PostVals, Req2} -> + echo(proplists:get_value(<<"echo">>, PostVals), Req2) + end; + +maybe_echo(<<"POST">>, false, Req) -> + cowboy_req:reply(400, [], <<"Missing body.">>, Req); +maybe_echo(_, _, Req) -> + %% Method not allowed. + cowboy_req:reply(405, Req). + +echo(badlength, Req) -> + cowboy_req:reply(413, [], <<"POST body bigger than 16000 bytes">>, Req); +echo(undefined, Req) -> + cowboy_req:reply(400, [], <<"Missing echo parameter.">>, Req); +echo(Echo, Req) -> + cowboy_req:reply(200, + [{<<"content-encoding">>, <<"utf-8">>}], Echo, Req). + +terminate(_, _, _) -> + ok. diff --git a/test/http_handler_echo_body.erl b/test/http_handler_echo_body.erl index 31595d5..4b9e765 100644 --- a/test/http_handler_echo_body.erl +++ b/test/http_handler_echo_body.erl @@ -9,11 +9,37 @@ init({_, http}, Req, _) -> handle(Req, State) -> true = cowboy_req:has_body(Req), - {ok, Body, Req2} = cowboy_req:body(Req), - {Size, Req3} = cowboy_req:body_length(Req2), + {ok, Req3} = case cowboy_req:body(1000000, Req) of + {error, chunked} -> handle_chunked(Req); + {error, badlength} -> handle_badlength(Req); + {ok, Body, Req2} -> handle_body(Req2, Body) + end, + {ok, Req3, State}. + +handle_chunked(Req) -> + {ok, Data, Req2} = read_body(Req, <<>>, 1000000), + {ok, Req3} = cowboy_req:reply(200, [], Data, Req2), + {ok, Req3}. + +handle_badlength(Req) -> + {ok, Req2} = cowboy_req:reply(413, [], <<"Request entity too large">>, Req), + {ok, Req2}. + +handle_body(Req, Body) -> + {Size, Req2} = cowboy_req:body_length(Req), Size = byte_size(Body), - {ok, Req4} = cowboy_req:reply(200, [], Body, Req3), - {ok, Req4, State}. + {ok, Req3} = cowboy_req:reply(200, [], Body, Req2), + {ok, Req3}. terminate(_, _, _) -> ok. + +% Read chunked request content +read_body(Req, Acc, BodyLengthRemaining) -> + case cowboy_req:stream_body(Req) of + {ok, Data, Req2} -> + BodyLengthRem = BodyLengthRemaining - byte_size(Data), + read_body(Req2, << Acc/binary, Data/binary >>, BodyLengthRem); + {done, Req2} -> + {ok, Acc, Req2} + end. -- cgit v1.2.3