Merge pull request #9708 from rabbitmq/mk-limit-max-http-api-payload-size
Introduce a configurable limit to HTTP API request body size
This commit is contained in:
commit
6009a4973f
|
@ -35,7 +35,8 @@ APP_ENV = """[
|
|||
|
||||
{cors_allow_origins, []},
|
||||
{cors_max_age, 1800},
|
||||
{content_security_policy, "script-src 'self' 'unsafe-eval' 'unsafe-inline'; object-src 'self'"}
|
||||
{content_security_policy, "script-src 'self' 'unsafe-eval' 'unsafe-inline'; object-src 'self'"},
|
||||
{max_http_body_size, 10000000}
|
||||
]"""
|
||||
|
||||
genrule(
|
||||
|
|
|
@ -12,7 +12,8 @@ define PROJECT_ENV
|
|||
|
||||
{cors_allow_origins, []},
|
||||
{cors_max_age, 1800},
|
||||
{content_security_policy, "script-src 'self' 'unsafe-eval' 'unsafe-inline'; object-src 'self'"}
|
||||
{content_security_policy, "script-src 'self' 'unsafe-eval' 'unsafe-inline'; object-src 'self'"},
|
||||
{max_http_body_size, 10000000}
|
||||
]
|
||||
endef
|
||||
|
||||
|
|
|
@ -11,3 +11,5 @@
|
|||
|
||||
-define(MANAGEMENT_PG_SCOPE, rabbitmq_management).
|
||||
-define(MANAGEMENT_PG_GROUP, management_db).
|
||||
|
||||
-define(MANAGEMENT_DEFAULT_HTTP_MAX_BODY_SIZE, 20000000).
|
||||
|
|
|
@ -20,6 +20,23 @@
|
|||
{mapping, "management.http_log_dir", "rabbitmq_management.http_log_dir",
|
||||
[{datatype, string}]}.
|
||||
|
||||
%% Max HTTP body limit
|
||||
|
||||
{mapping, "management.http.max_body_size", "rabbitmq_management.max_http_body_size",
|
||||
[{datatype, integer}, {validators, ["non_negative_integer"]}]}.
|
||||
|
||||
{translation, "rabbitmq_management.max_http_body_size",
|
||||
fun(Conf) ->
|
||||
case cuttlefish:conf_get("management.http.max_body_size", Conf, undefined) of
|
||||
%% 10 MiB allows for about 100K queues with short names across a small (single digit) number of virtual hosts with
|
||||
%% an equally small number of users. MK.
|
||||
undefined -> 10000000;
|
||||
Val when is_integer(Val) -> Val;
|
||||
Other -> cuttlefish:invalid("management.http.max_body_size must be set to a positive integer")
|
||||
end
|
||||
end}.
|
||||
|
||||
|
||||
%% HTTP (TCP) listener options ========================================================
|
||||
|
||||
%% HTTP listener consistent with Web STOMP and Web MQTT.
|
||||
|
|
|
@ -686,15 +686,27 @@ id(Key, ReqData) ->
|
|||
|
||||
read_complete_body(Req) ->
|
||||
read_complete_body(Req, <<"">>).
|
||||
read_complete_body(Req0, Acc) ->
|
||||
case cowboy_req:read_body(Req0) of
|
||||
{ok, Data, Req} -> {ok, <<Acc/binary, Data/binary>>, Req};
|
||||
{more, Data, Req} -> read_complete_body(Req, <<Acc/binary, Data/binary>>)
|
||||
read_complete_body(Req, Acc) ->
|
||||
BodySizeLimit = application:get_env(rabbitmq_management, max_http_body_size, ?MANAGEMENT_DEFAULT_HTTP_MAX_BODY_SIZE),
|
||||
read_complete_body(Req, Acc, BodySizeLimit).
|
||||
read_complete_body(Req0, Acc, BodySizeLimit) ->
|
||||
case bit_size(Acc) > BodySizeLimit of
|
||||
true ->
|
||||
{error, "Exceeded HTTP request body size limit"};
|
||||
false ->
|
||||
case cowboy_req:read_body(Req0) of
|
||||
{ok, Data, Req} -> {ok, <<Acc/binary, Data/binary>>, Req};
|
||||
{more, Data, Req} -> read_complete_body(Req, <<Acc/binary, Data/binary>>)
|
||||
end
|
||||
end.
|
||||
|
||||
with_decode(Keys, ReqData, Context, Fun) ->
|
||||
{ok, Body, ReqData1} = read_complete_body(ReqData),
|
||||
with_decode(Keys, Body, ReqData1, Context, Fun).
|
||||
case read_complete_body(ReqData) of
|
||||
{error, Reason} ->
|
||||
bad_request(Reason, ReqData, Context);
|
||||
{ok, Body, ReqData1} ->
|
||||
with_decode(Keys, Body, ReqData1, Context, Fun)
|
||||
end.
|
||||
|
||||
with_decode(Keys, Body, ReqData, Context, Fun) ->
|
||||
case decode(Keys, Body) of
|
||||
|
|
|
@ -84,8 +84,15 @@ all_definitions(ReqData, Context) ->
|
|||
Context).
|
||||
|
||||
accept_json(ReqData0, Context) ->
|
||||
{ok, Body, ReqData} = rabbit_mgmt_util:read_complete_body(ReqData0),
|
||||
accept(Body, ReqData, Context).
|
||||
case rabbit_mgmt_util:read_complete_body(ReqData0) of
|
||||
{error, Reason} ->
|
||||
BodySizeLimit = application:get_env(rabbitmq_management, max_http_body_size, ?MANAGEMENT_DEFAULT_HTTP_MAX_BODY_SIZE),
|
||||
_ = rabbit_log:warning("HTTP API: uploaded definition file exceeded the maximum request body limit of ~p bytes. "
|
||||
"Use the 'management.http.max_body_size' key in rabbitmq.conf to increase the limit if necessary", [BodySizeLimit]),
|
||||
rabbit_mgmt_util:bad_request(Reason, ReqData0, Context);
|
||||
{ok, Body, ReqData} ->
|
||||
accept(Body, ReqData, Context)
|
||||
end.
|
||||
|
||||
vhost_definitions(ReqData, VHost, Context) ->
|
||||
%% rabbit_mgmt_wm_<>:basic/1 filters by VHost if it is available
|
||||
|
|
|
@ -126,6 +126,7 @@ all_tests() -> [
|
|||
get_fail_test,
|
||||
publish_test,
|
||||
publish_large_message_test,
|
||||
publish_large_message_exceeding_http_request_body_size_test,
|
||||
publish_accept_json_test,
|
||||
publish_fail_test,
|
||||
publish_base64_test,
|
||||
|
@ -2644,7 +2645,7 @@ get_fail_test(Config) ->
|
|||
passed.
|
||||
|
||||
|
||||
-define(LARGE_BODY_BYTES, 25000000).
|
||||
-define(LARGE_BODY_BYTES, 5000000).
|
||||
|
||||
publish_test(Config) ->
|
||||
Headers = #{'x-forwarding' => [#{uri => <<"amqp://localhost/%2F/upstream">>}]},
|
||||
|
@ -2687,6 +2688,19 @@ publish_large_message_test(Config) ->
|
|||
http_delete(Config, "/queues/%2F/publish_accept_json_test", {group, '2xx'}),
|
||||
passed.
|
||||
|
||||
-define(EXCESSIVELY_LARGE_BODY_BYTES, 35000000).
|
||||
|
||||
publish_large_message_exceeding_http_request_body_size_test(Config) ->
|
||||
Headers = #{'x-forwarding' => [#{uri => <<"amqp://localhost/%2F/upstream">>}]},
|
||||
Body = binary:copy(<<"a">>, ?EXCESSIVELY_LARGE_BODY_BYTES),
|
||||
Msg = msg(<<"large_message_exceeding_http_request_body_size_test">>, Headers, Body),
|
||||
http_put(Config, "/queues/%2F/large_message_exceeding_http_request_body_size_test", #{}, {group, '2xx'}),
|
||||
%% exceeds the default HTTP API request body size limit
|
||||
http_post_accept_json(Config, "/exchanges/%2F/amq.default/publish",
|
||||
Msg, ?BAD_REQUEST),
|
||||
http_delete(Config, "/queues/%2F/large_message_exceeding_http_request_body_size_test", {group, '2xx'}),
|
||||
passed.
|
||||
|
||||
publish_accept_json_test(Config) ->
|
||||
Headers = #{'x-forwarding' => [#{uri => <<"amqp://localhost/%2F/upstream">>}]},
|
||||
Msg = msg(<<"publish_accept_json_test">>, Headers, <<"Hello world">>),
|
||||
|
|
Loading…
Reference in New Issue