567 lines
13 KiB
Perl
567 lines
13 KiB
Perl
![]() |
# vim:set ft= ts=4 sw=4 et:
|
||
|
|
||
|
use Test::Nginx::Socket;
|
||
|
use Cwd qw(cwd);
|
||
|
|
||
|
plan tests => repeat_each() * (blocks() * 4) - 1;
|
||
|
|
||
|
my $pwd = cwd();
|
||
|
|
||
|
our $HttpConfig = qq{
|
||
|
lua_package_path "$pwd/lib/?.lua;;";
|
||
|
};
|
||
|
|
||
|
$ENV{TEST_NGINX_RESOLVER} = '8.8.8.8';
|
||
|
|
||
|
no_long_string();
|
||
|
#no_diff();
|
||
|
|
||
|
run_tests();
|
||
|
|
||
|
__DATA__
|
||
|
=== TEST 1: Chunked streaming body reader returns the right content length.
|
||
|
--- http_config eval: $::HttpConfig
|
||
|
--- config
|
||
|
location = /a {
|
||
|
content_by_lua '
|
||
|
local http = require "resty.http"
|
||
|
local httpc = http.new()
|
||
|
httpc:connect("127.0.0.1", ngx.var.server_port)
|
||
|
|
||
|
local res, err = httpc:request{
|
||
|
path = "/b",
|
||
|
}
|
||
|
|
||
|
local chunks = {}
|
||
|
repeat
|
||
|
local chunk = res.body_reader()
|
||
|
if chunk then
|
||
|
table.insert(chunks, chunk)
|
||
|
end
|
||
|
until not chunk
|
||
|
|
||
|
local body = table.concat(chunks)
|
||
|
ngx.say(#body)
|
||
|
ngx.say(res.headers["Transfer-Encoding"])
|
||
|
|
||
|
httpc:close()
|
||
|
';
|
||
|
}
|
||
|
location = /b {
|
||
|
content_by_lua '
|
||
|
local len = 32768
|
||
|
local t = {}
|
||
|
for i=1,len do
|
||
|
t[i] = 0
|
||
|
end
|
||
|
ngx.print(table.concat(t))
|
||
|
';
|
||
|
}
|
||
|
--- request
|
||
|
GET /a
|
||
|
--- response_body
|
||
|
32768
|
||
|
chunked
|
||
|
--- no_error_log
|
||
|
[error]
|
||
|
[warn]
|
||
|
|
||
|
|
||
|
=== TEST 2: Non-Chunked streaming body reader returns the right content length.
|
||
|
--- http_config eval: $::HttpConfig
|
||
|
--- config
|
||
|
location = /a {
|
||
|
content_by_lua '
|
||
|
local http = require "resty.http"
|
||
|
local httpc = http.new()
|
||
|
httpc:connect("127.0.0.1", ngx.var.server_port)
|
||
|
|
||
|
local res, err = httpc:request{
|
||
|
path = "/b",
|
||
|
}
|
||
|
|
||
|
local chunks = {}
|
||
|
repeat
|
||
|
local chunk = res.body_reader()
|
||
|
if chunk then
|
||
|
table.insert(chunks, chunk)
|
||
|
end
|
||
|
until not chunk
|
||
|
|
||
|
local body = table.concat(chunks)
|
||
|
ngx.say(#body)
|
||
|
ngx.say(res.headers["Transfer-Encoding"])
|
||
|
ngx.say(#chunks)
|
||
|
|
||
|
httpc:close()
|
||
|
';
|
||
|
}
|
||
|
location = /b {
|
||
|
chunked_transfer_encoding off;
|
||
|
content_by_lua '
|
||
|
local len = 32768
|
||
|
local t = {}
|
||
|
for i=1,len do
|
||
|
t[i] = 0
|
||
|
end
|
||
|
ngx.print(table.concat(t))
|
||
|
';
|
||
|
}
|
||
|
--- request
|
||
|
GET /a
|
||
|
--- response_body
|
||
|
32768
|
||
|
nil
|
||
|
1
|
||
|
--- no_error_log
|
||
|
[error]
|
||
|
[warn]
|
||
|
|
||
|
|
||
|
=== TEST 2b: Non-Chunked streaming body reader, buffer size becomes nil
|
||
|
--- http_config eval: $::HttpConfig
|
||
|
--- config
|
||
|
location = /a {
|
||
|
content_by_lua '
|
||
|
local http = require "resty.http"
|
||
|
local httpc = http.new()
|
||
|
httpc:connect("127.0.0.1", ngx.var.server_port)
|
||
|
|
||
|
local res, err = httpc:request{
|
||
|
path = "/b",
|
||
|
}
|
||
|
|
||
|
local chunks = {}
|
||
|
local buffer_size = 16384
|
||
|
repeat
|
||
|
local chunk = res.body_reader(buffer_size)
|
||
|
if chunk then
|
||
|
table.insert(chunks, chunk)
|
||
|
end
|
||
|
|
||
|
buffer_size = nil
|
||
|
until not chunk
|
||
|
|
||
|
local body = table.concat(chunks)
|
||
|
ngx.say(res.headers["Transfer-Encoding"])
|
||
|
|
||
|
httpc:close()
|
||
|
';
|
||
|
}
|
||
|
location = /b {
|
||
|
chunked_transfer_encoding off;
|
||
|
content_by_lua '
|
||
|
local len = 32768
|
||
|
local t = {}
|
||
|
for i=1,len do
|
||
|
t[i] = 0
|
||
|
end
|
||
|
ngx.print(table.concat(t))
|
||
|
';
|
||
|
}
|
||
|
--- request
|
||
|
GET /a
|
||
|
--- response_body
|
||
|
nil
|
||
|
--- error_log
|
||
|
Buffer size not specified, bailing
|
||
|
|
||
|
|
||
|
=== TEST 3: HTTP 1.0 body reader with no max size returns the right content length.
|
||
|
--- http_config eval: $::HttpConfig
|
||
|
--- config
|
||
|
location = /a {
|
||
|
content_by_lua '
|
||
|
local http = require "resty.http"
|
||
|
local httpc = http.new()
|
||
|
httpc:connect("127.0.0.1", ngx.var.server_port)
|
||
|
|
||
|
local res, err = httpc:request{
|
||
|
path = "/b",
|
||
|
version = 1.0,
|
||
|
}
|
||
|
|
||
|
local chunks = {}
|
||
|
repeat
|
||
|
local chunk = res.body_reader()
|
||
|
if chunk then
|
||
|
table.insert(chunks, chunk)
|
||
|
end
|
||
|
until not chunk
|
||
|
|
||
|
local body = table.concat(chunks)
|
||
|
ngx.say(#body)
|
||
|
ngx.say(res.headers["Transfer-Encoding"])
|
||
|
ngx.say(#chunks)
|
||
|
|
||
|
httpc:close()
|
||
|
';
|
||
|
}
|
||
|
location = /b {
|
||
|
chunked_transfer_encoding off;
|
||
|
content_by_lua '
|
||
|
local len = 32768
|
||
|
local t = {}
|
||
|
for i=1,len do
|
||
|
t[i] = 0
|
||
|
end
|
||
|
ngx.print(table.concat(t))
|
||
|
';
|
||
|
}
|
||
|
--- request
|
||
|
GET /a
|
||
|
--- response_body
|
||
|
32768
|
||
|
nil
|
||
|
1
|
||
|
--- no_error_log
|
||
|
[error]
|
||
|
[warn]
|
||
|
|
||
|
|
||
|
=== TEST 4: HTTP 1.0 body reader with max chunk size returns the right content length.
|
||
|
--- http_config eval: $::HttpConfig
|
||
|
--- config
|
||
|
location = /a {
|
||
|
content_by_lua '
|
||
|
local http = require "resty.http"
|
||
|
local httpc = http.new()
|
||
|
httpc:connect("127.0.0.1", ngx.var.server_port)
|
||
|
|
||
|
local res, err = httpc:request{
|
||
|
path = "/b",
|
||
|
version = 1.0,
|
||
|
}
|
||
|
|
||
|
local chunks = {}
|
||
|
local size = 8192
|
||
|
repeat
|
||
|
local chunk = res.body_reader(size)
|
||
|
if chunk then
|
||
|
table.insert(chunks, chunk)
|
||
|
end
|
||
|
size = size + size
|
||
|
until not chunk
|
||
|
|
||
|
local body = table.concat(chunks)
|
||
|
ngx.say(#body)
|
||
|
ngx.say(res.headers["Transfer-Encoding"])
|
||
|
ngx.say(#chunks)
|
||
|
|
||
|
httpc:close()
|
||
|
';
|
||
|
}
|
||
|
location = /b {
|
||
|
chunked_transfer_encoding off;
|
||
|
content_by_lua '
|
||
|
local len = 32769
|
||
|
local t = {}
|
||
|
for i=1,len do
|
||
|
t[i] = 0
|
||
|
end
|
||
|
ngx.print(table.concat(t))
|
||
|
';
|
||
|
}
|
||
|
--- request
|
||
|
GET /a
|
||
|
--- response_body
|
||
|
32769
|
||
|
nil
|
||
|
3
|
||
|
--- no_error_log
|
||
|
[error]
|
||
|
[warn]
|
||
|
|
||
|
|
||
|
=== TEST 4b: HTTP 1.0 body reader with no content length, stream works as expected.
|
||
|
--- http_config eval: $::HttpConfig
|
||
|
--- config
|
||
|
location = /a {
|
||
|
content_by_lua '
|
||
|
local http = require "resty.http"
|
||
|
local httpc = http.new()
|
||
|
httpc:connect("127.0.0.1", ngx.var.server_port)
|
||
|
|
||
|
local res, err = httpc:request{
|
||
|
path = "/b",
|
||
|
version = 1.0,
|
||
|
}
|
||
|
|
||
|
local chunks = {}
|
||
|
local size = 8192
|
||
|
repeat
|
||
|
local chunk = res.body_reader(size)
|
||
|
if chunk then
|
||
|
table.insert(chunks, chunk)
|
||
|
end
|
||
|
size = size + size
|
||
|
until not chunk
|
||
|
|
||
|
local body = table.concat(chunks)
|
||
|
ngx.say(#body)
|
||
|
ngx.say(#chunks)
|
||
|
|
||
|
httpc:close()
|
||
|
';
|
||
|
}
|
||
|
location = /b {
|
||
|
content_by_lua '
|
||
|
ngx.req.read_body()
|
||
|
local sock, err = ngx.req.socket(true)
|
||
|
if not sock then
|
||
|
ngx.say(err)
|
||
|
end
|
||
|
|
||
|
local res = {}
|
||
|
table.insert(res, "HTTP/1.0 200 OK")
|
||
|
table.insert(res, "Date: " .. ngx.http_time(ngx.time()))
|
||
|
table.insert(res, "")
|
||
|
|
||
|
local len = 32769
|
||
|
local t = {}
|
||
|
for i=1,len do
|
||
|
t[i] = 0
|
||
|
end
|
||
|
table.insert(res, table.concat(t))
|
||
|
sock:send(table.concat(res, "\\r\\n"))
|
||
|
';
|
||
|
}
|
||
|
--- request
|
||
|
GET /a
|
||
|
--- response_body
|
||
|
32769
|
||
|
3
|
||
|
--- no_error_log
|
||
|
[error]
|
||
|
[warn]
|
||
|
|
||
|
|
||
|
=== TEST 5: Chunked streaming body reader with max chunk size returns the right content length.
|
||
|
--- http_config eval: $::HttpConfig
|
||
|
--- config
|
||
|
location = /a {
|
||
|
content_by_lua '
|
||
|
local http = require "resty.http"
|
||
|
local httpc = http.new()
|
||
|
httpc:connect("127.0.0.1", ngx.var.server_port)
|
||
|
|
||
|
local res, err = httpc:request{
|
||
|
path = "/b",
|
||
|
}
|
||
|
|
||
|
local chunks = {}
|
||
|
local size = 8192
|
||
|
repeat
|
||
|
local chunk = res.body_reader(size)
|
||
|
if chunk then
|
||
|
table.insert(chunks, chunk)
|
||
|
end
|
||
|
size = size + size
|
||
|
until not chunk
|
||
|
|
||
|
local body = table.concat(chunks)
|
||
|
ngx.say(#body)
|
||
|
ngx.say(res.headers["Transfer-Encoding"])
|
||
|
ngx.say(#chunks)
|
||
|
|
||
|
httpc:close()
|
||
|
';
|
||
|
}
|
||
|
location = /b {
|
||
|
content_by_lua '
|
||
|
local len = 32768
|
||
|
local t = {}
|
||
|
for i=1,len do
|
||
|
t[i] = 0
|
||
|
end
|
||
|
ngx.print(table.concat(t))
|
||
|
';
|
||
|
}
|
||
|
--- request
|
||
|
GET /a
|
||
|
--- response_body
|
||
|
32768
|
||
|
chunked
|
||
|
3
|
||
|
--- no_error_log
|
||
|
[error]
|
||
|
[warn]
|
||
|
|
||
|
|
||
|
=== TEST 6: Request reader correctly reads body
|
||
|
--- http_config eval: $::HttpConfig
|
||
|
--- config
|
||
|
location = /a {
|
||
|
lua_need_request_body off;
|
||
|
content_by_lua '
|
||
|
local http = require "resty.http"
|
||
|
local httpc = http.new()
|
||
|
|
||
|
local reader, err = httpc:get_client_body_reader(8192)
|
||
|
|
||
|
repeat
|
||
|
local chunk, err = reader()
|
||
|
if chunk then
|
||
|
ngx.print(chunk)
|
||
|
end
|
||
|
until chunk == nil
|
||
|
|
||
|
';
|
||
|
}
|
||
|
|
||
|
--- request
|
||
|
POST /a
|
||
|
foobarbazfoobarbazfoobarbazfoobarbazfoobarbazfoobarbazfoobarbazfoobarbazfoobarbazfoobarbazfoobarbazfoobarbaz
|
||
|
--- response_body: foobarbazfoobarbazfoobarbazfoobarbazfoobarbazfoobarbazfoobarbazfoobarbazfoobarbazfoobarbazfoobarbazfoobarbaz
|
||
|
--- no_error_log
|
||
|
[error]
|
||
|
[warn]
|
||
|
|
||
|
=== TEST 7: Request reader correctly reads body in chunks
|
||
|
--- http_config eval: $::HttpConfig
|
||
|
--- config
|
||
|
location = /a {
|
||
|
lua_need_request_body off;
|
||
|
content_by_lua '
|
||
|
local http = require "resty.http"
|
||
|
local httpc = http.new()
|
||
|
|
||
|
local reader, err = httpc:get_client_body_reader(64)
|
||
|
|
||
|
local chunks = 0
|
||
|
repeat
|
||
|
chunks = chunks +1
|
||
|
local chunk, err = reader()
|
||
|
if chunk then
|
||
|
ngx.print(chunk)
|
||
|
end
|
||
|
until chunk == nil
|
||
|
ngx.say("\\n"..chunks)
|
||
|
';
|
||
|
}
|
||
|
|
||
|
--- request
|
||
|
POST /a
|
||
|
foobarbazfoobarbazfoobarbazfoobarbazfoobarbazfoobarbazfoobarbazfoobarbazfoobarbazfoobarbazfoobarbazfoobarbaz
|
||
|
--- response_body
|
||
|
foobarbazfoobarbazfoobarbazfoobarbazfoobarbazfoobarbazfoobarbazfoobarbazfoobarbazfoobarbazfoobarbazfoobarbaz
|
||
|
3
|
||
|
--- no_error_log
|
||
|
[error]
|
||
|
[warn]
|
||
|
|
||
|
|
||
|
=== TEST 8: Request reader passes into client
|
||
|
--- http_config eval: $::HttpConfig
|
||
|
--- config
|
||
|
location = /a {
|
||
|
lua_need_request_body off;
|
||
|
content_by_lua '
|
||
|
local http = require "resty.http"
|
||
|
local httpc = http.new()
|
||
|
httpc:connect("127.0.0.1", ngx.var.server_port)
|
||
|
|
||
|
local reader, err = httpc:get_client_body_reader(64)
|
||
|
|
||
|
local res, err = httpc:request{
|
||
|
method = POST,
|
||
|
path = "/b",
|
||
|
body = reader,
|
||
|
headers = ngx.req.get_headers(100, true),
|
||
|
}
|
||
|
|
||
|
local body = res:read_body()
|
||
|
ngx.say(body)
|
||
|
httpc:close()
|
||
|
|
||
|
';
|
||
|
}
|
||
|
|
||
|
location = /b {
|
||
|
content_by_lua '
|
||
|
ngx.req.read_body()
|
||
|
local body, err = ngx.req.get_body_data()
|
||
|
ngx.print(body)
|
||
|
';
|
||
|
}
|
||
|
|
||
|
--- request
|
||
|
POST /a
|
||
|
foobarbazfoobarbazfoobarbazfoobarbazfoobarbazfoobarbazfoobarbazfoobarbazfoobarbazfoobarbazfoobarbazfoobarbaz
|
||
|
--- response_body
|
||
|
foobarbazfoobarbazfoobarbazfoobarbazfoobarbazfoobarbazfoobarbazfoobarbazfoobarbazfoobarbazfoobarbazfoobarbaz
|
||
|
--- no_error_log
|
||
|
[error]
|
||
|
[warn]
|
||
|
|
||
|
|
||
|
=== TEST 9: Body reader is a function returning nil when no body is present.
|
||
|
--- http_config eval: $::HttpConfig
|
||
|
--- config
|
||
|
location = /a {
|
||
|
content_by_lua '
|
||
|
local http = require "resty.http"
|
||
|
local httpc = http.new()
|
||
|
httpc:connect("127.0.0.1", ngx.var.server_port)
|
||
|
|
||
|
local res, err = httpc:request{
|
||
|
path = "/b",
|
||
|
method = "HEAD",
|
||
|
}
|
||
|
|
||
|
repeat
|
||
|
local chunk = res.body_reader()
|
||
|
until not chunk
|
||
|
|
||
|
httpc:close()
|
||
|
';
|
||
|
}
|
||
|
location = /b {
|
||
|
content_by_lua '
|
||
|
ngx.exit(200)
|
||
|
';
|
||
|
}
|
||
|
--- request
|
||
|
GET /a
|
||
|
--- no_error_log
|
||
|
[error]
|
||
|
[warn]
|
||
|
|
||
|
|
||
|
=== TEST 10: Issue a notice (but do not error) if trying to read the request body in a subrequest
|
||
|
--- http_config eval: $::HttpConfig
|
||
|
--- config
|
||
|
location = /a {
|
||
|
echo_location /b;
|
||
|
}
|
||
|
location = /b {
|
||
|
lua_need_request_body off;
|
||
|
content_by_lua '
|
||
|
local http = require "resty.http"
|
||
|
local httpc = http.new()
|
||
|
|
||
|
local reader, err = httpc:get_client_body_reader(8192)
|
||
|
if not reader then
|
||
|
ngx.log(ngx.NOTICE, err)
|
||
|
return
|
||
|
end
|
||
|
|
||
|
repeat
|
||
|
local chunk, err = reader()
|
||
|
if chunk then
|
||
|
ngx.print(chunk)
|
||
|
end
|
||
|
until chunk == nil
|
||
|
';
|
||
|
}
|
||
|
|
||
|
--- request
|
||
|
POST /a
|
||
|
foobarbazfoobarbazfoobarbazfoobarbazfoobarbazfoobarbazfoobarbazfoobarbazfoobarbazfoobarbazfoobarbazfoobarbaz
|
||
|
--- response_body:
|
||
|
--- no_error_log
|
||
|
[error]
|
||
|
[warn]
|
||
|
--- error_log
|
||
|
attempt to read the request body in a subrequest
|