blob: 48dca8b0d6ac2d78ada34a405468a6494974168a [file]
#
# Licensed to the Apache Software Foundation (ASF) under one or more
# contributor license agreements. See the NOTICE file distributed with
# this work for additional information regarding copyright ownership.
# The ASF licenses this file to You under the Apache License, Version 2.0
# (the "License"); you may not use this file except in compliance with
# the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
use t::APISIX;
my $nginx_binary = $ENV{'TEST_NGINX_BINARY'} || 'nginx';
my $version = eval { `$nginx_binary -V 2>&1` };
if ($version !~ m/\/apisix-nginx-module/) {
plan(skip_all => "apisix-nginx-module not installed");
} else {
plan('no_plan');
}
repeat_each(1);
log_level('info');
no_root_location();
no_long_string();
no_shuffle();
add_block_preprocessor(sub {
my ($block) = @_;
});
run_tests();
__DATA__
=== TEST 1: sanity
--- config
location /t {
content_by_lua_block {
local t = require("lib.test_admin").test
local json = require("toolkit.json")
local code, body = t('/apisix/admin/routes/1',
ngx.HTTP_PUT,
[[{
"uri": "/hello",
"upstream": {
"type": "roundrobin",
"nodes": {
"127.0.0.1:1980": 1
}
},
"plugins": {
"client-control": {
"max_body_size": 5
}
}
}]]
)
if code >= 300 then
ngx.status = code
end
ngx.say(body)
}
}
--- request
GET /t
--- response_body
passed
=== TEST 2: hit, failed
--- request
POST /hello
123456
--- error_code: 413
=== TEST 3: hit, failed with chunked
--- more_headers
Transfer-Encoding: chunked
--- request eval
qq{POST /hello
6\r
Hello \r
0\r
\r
}
--- error_code: 413
--- error_log
client intended to send too large chunked body
=== TEST 4: hit
--- request
POST /hello
12345
=== TEST 5: bad body size
--- config
location /t {
content_by_lua_block {
local t = require("lib.test_admin").test
local json = require("toolkit.json")
local code, body = t('/apisix/admin/routes/1',
ngx.HTTP_PUT,
[[{
"uri": "/hello",
"upstream": {
"type": "roundrobin",
"nodes": {
"127.0.0.1:1980": 1
}
},
"plugins": {
"client-control": {
"max_body_size": -1
}
}
}]]
)
if code >= 300 then
ngx.status = code
end
ngx.print(body)
}
}
--- request
GET /t
--- error_code: 400
--- response_body
{"error_msg":"failed to check the configuration of plugin client-control err: property \"max_body_size\" validation failed: expected -1 to be at least 0"}
=== TEST 6: 0 means no limit
--- config
location /t {
content_by_lua_block {
local t = require("lib.test_admin").test
local json = require("toolkit.json")
local code, body = t('/apisix/admin/routes/1',
ngx.HTTP_PUT,
[[{
"uri": "/hello",
"upstream": {
"type": "roundrobin",
"nodes": {
"127.0.0.1:1980": 1
}
},
"plugins": {
"client-control": {
"max_body_size": 0
}
}
}]]
)
if code >= 300 then
ngx.status = code
end
ngx.say(body)
}
}
--- request
GET /t
--- response_body
passed
=== TEST 7: hit
--- request
POST /hello
1
=== TEST 8: setup global rule with body reader and route with client-control
The global rule reads the body in access phase (simulates a logger with
include_req_body). The route has client-control raising the body size limit
above test-nginx's hardcoded 30M so the body read succeeds.
--- upstream_server_config
client_max_body_size 0;
--- config
location /t {
content_by_lua_block {
local t = require("lib.test_admin").test
-- global rule: read body in access phase
local code, body = t('/apisix/admin/global_rules/1',
ngx.HTTP_PUT,
[[{
"plugins": {
"serverless-post-function": {
"phase": "access",
"functions": ["return function(conf, ctx) ngx.req.read_body() end"]
}
}
}]]
)
if code >= 300 then
ngx.status = code
ngx.say(body)
return
end
-- route with client-control raising the limit above 30M
code, body = t('/apisix/admin/routes/1',
ngx.HTTP_PUT,
[[{
"uri": "/hello",
"upstream": {
"type": "roundrobin",
"nodes": {
"127.0.0.1:1980": 1
}
},
"plugins": {
"client-control": {
"max_body_size": 52428800
}
}
}]]
)
if code >= 300 then
ngx.status = code
ngx.say(body)
return
end
ngx.say("passed")
}
}
--- request
GET /t
--- response_body
passed
=== TEST 9: client-control should override body limit before global rule reads body
With the global rules phase split, client-control runs in route rewrite
(setting FFI override to 50MB) before the global rule access phase reads
the body. The body exceeds test-nginx's hardcoded 30M but is within the
50MB override, so the request should succeed.
--- upstream_server_config
client_max_body_size 0;
--- request eval
"POST /hello\n" . "A" x (31 * 1024 * 1024)
--- error_code: 200
--- timeout: 30
=== TEST 10: remove client-control from route
--- upstream_server_config
client_max_body_size 0;
--- config
location /t {
content_by_lua_block {
local t = require("lib.test_admin").test
local code, body = t('/apisix/admin/routes/1',
ngx.HTTP_PUT,
[[{
"uri": "/hello",
"upstream": {
"type": "roundrobin",
"nodes": {
"127.0.0.1:1980": 1
}
}
}]]
)
if code >= 300 then
ngx.status = code
ngx.say(body)
return
end
ngx.say("passed")
}
}
--- request
GET /t
--- response_body
passed
=== TEST 11: without client-control, body exceeds hardcoded 30M limit
Without client-control the FFI override is not set, so the global rule's
read_body() triggers the hardcoded 30M body size check. The same body
that succeeded in TEST 9 now gets rejected with 413.
--- upstream_server_config
client_max_body_size 0;
--- request eval
"POST /hello\n" . "A" x (31 * 1024 * 1024)
--- error_code: 413
--- error_log
client intended to send too large body
--- timeout: 30
=== TEST 12: cleanup global rules
--- upstream_server_config
client_max_body_size 0;
--- config
location /t {
content_by_lua_block {
local t = require("lib.test_admin").test
local code, body = t('/apisix/admin/global_rules/1', ngx.HTTP_DELETE)
ngx.say(body)
}
}
--- request
GET /t
--- response_body
passed