Skip to content

Commit

Permalink
cosocket: bugfix: fixed a minor inconsistency in the reading iterator…
Browse files Browse the repository at this point in the history
… returned from sock:receiveuntil when the "size" argument is specified. also added some (passing) tests for a true multipart parser.
  • Loading branch information
agentzh committed Jan 23, 2012
1 parent 54a6f75 commit 7a4cbfb
Show file tree
Hide file tree
Showing 3 changed files with 268 additions and 10 deletions.
10 changes: 1 addition & 9 deletions src/ngx_http_lua_socket.c
Expand Up @@ -2243,15 +2243,7 @@ ngx_http_lua_socket_read_until(void *data, ssize_t bytes)
b->pos += i;

if (u->length) {
if (u->rest != u->length) {
dd("setting state to -1");
cp->state = -1;

} else {
dd("setting state to 0");
cp->state = 0;
u->luabuf_inited = 0;
}
cp->state = -1;

} else {
cp->state = 0;
Expand Down
3 changes: 2 additions & 1 deletion t/066-socket-receiveuntil.t
Expand Up @@ -885,7 +885,7 @@ close: nil closed
local reader = sock:receiveuntil("--abc")
for i = 1, 6 do
for i = 1, 7 do
line, err, part = reader(4)
if line then
ngx.say("read: ", line)
Expand Down Expand Up @@ -913,6 +913,7 @@ read: hell
read: o, w
read: orld
read: --
read:
failed to read a line: nil [nil]
failed to read a line: closed [
]
Expand Down
265 changes: 265 additions & 0 deletions t/067-req-socket.t
Expand Up @@ -52,3 +52,268 @@ failed to receive: closed [d]
--- no_error_log
[error]
=== TEST 2: multipart rfc sample (just partial streaming)
--- config
location /t {
content_by_lua '
local sock, err = ngx.req.socket()
if sock then
ngx.say("got the request socket")
else
ngx.say("failed to get the request socket: ", err)
end
local boundary
local header = ngx.var.http_content_type
local m = ngx.re.match(header, [[; +boundary=(?:"(.*?)"|(\\w+))]], "jo")
if m then
boundary = m[1] or m[2]
else
ngx.say("invalid content-type header")
return
end
local read_to_boundary = sock:receiveuntil("\\r\\n--" .. boundary)
local read_line = sock:receiveuntil("\\r\\n")
local data, err, part = read_to_boundary()
if data then
ngx.say("preamble: [" .. data .. "]")
else
ngx.say("failed to read the first boundary: ", err)
return
end
local i = 1
while true do
local line, err = read_line()
if not line then
ngx.say("failed to read post-boundary line: ", err)
return
end
m = ngx.re.match(line, "--$", "jo")
if m then
ngx.say("found the end of the stream")
return
end
while true do
local line, err = read_line()
if not line then
ngx.say("failed to read part ", i, " header: ", err)
return
end
if line == "" then
-- the header part completes
break
end
ngx.say("part ", i, " header: [", line, "]")
end
local data, err, part = read_to_boundary()
if data then
ngx.say("part ", i, " body: [" .. data .. "]")
else
ngx.say("failed to read part ", i + 1, " boundary: ", err)
return
end
i = i + 1
end
';
}
--- request eval
"POST /t
This is the preamble. It is to be ignored, though it
is a handy place for mail composers to include an
explanatory note to non-MIME compliant readers.\r
--simple boundary\r
\r
This is implicitly typed plain ASCII text.
It does NOT end with a linebreak.\r
--simple boundary\r
Content-type: text/plain; charset=us-ascii\r
\r
This is explicitly typed plain ASCII text.
It DOES end with a linebreak.
\r
--simple boundary--\r
This is the epilogue. It is also to be ignored.
"
--- more_headers
Content-Type: multipart/mixed; boundary="simple boundary"
--- response_body
got the request socket
preamble: [This is the preamble. It is to be ignored, though it
is a handy place for mail composers to include an
explanatory note to non-MIME compliant readers.]
part 1 body: [This is implicitly typed plain ASCII text.
It does NOT end with a linebreak.]
part 2 header: [Content-type: text/plain; charset=us-ascii]
part 2 body: [This is explicitly typed plain ASCII text.
It DOES end with a linebreak.
]
found the end of the stream
--- no_error_log
[error]
=== TEST 3: multipart rfc sample (completely streaming)
--- config
location /t {
content_by_lua '
local sock, err = ngx.req.socket()
if sock then
ngx.say("got the request socket")
else
ngx.say("failed to get the request socket: ", err)
end
local boundary
local header = ngx.var.http_content_type
local m = ngx.re.match(header, [[; +boundary=(?:"(.*?)"|(\\w+))]], "jo")
if m then
boundary = m[1] or m[2]
else
ngx.say("invalid content-type header")
return
end
local read_to_boundary = sock:receiveuntil("\\r\\n--" .. boundary)
local read_line = sock:receiveuntil("\\r\\n")
local preamble = ""
while true do
local data, err, part = read_to_boundary(1)
if data then
preamble = preamble .. data
elseif not err then
break
else
ngx.say("failed to read the first boundary: ", err)
return
end
end
ngx.say("preamble: [" .. preamble .. "]")
local i = 1
while true do
local line, err = read_line(50)
if not line and err then
ngx.say("1: failed to read post-boundary line: ", err)
return
end
if line then
local dummy
dummy, err = read_line(1)
if err then
ngx.say("2: failed to read post-boundary line: ", err)
return
end
if dummy then
ngx.say("bad post-boundary line: ", dummy)
return
end
m = ngx.re.match(line, "--$", "jo")
if m then
ngx.say("found the end of the stream")
return
end
end
while true do
local line, err = read_line(50)
if not line and err then
ngx.say("failed to read part ", i, " header: ", err)
return
end
if line then
local line, err = read_line(1)
if line or err then
ngx.say("error")
return
end
end
if line == "" then
-- the header part completes
break
end
ngx.say("part ", i, " header: [", line, "]")
end
local body = ""
while true do
local data, err, part = read_to_boundary(1)
if data then
body = body .. data
elseif err then
ngx.say("failed to read part ", i + 1, " boundary: ", err)
return
else
break
end
end
ngx.say("part ", i, " body: [" .. body .. "]")
i = i + 1
end
';
}
--- request eval
"POST /t
This is the preamble. It is to be ignored, though it
is a handy place for mail composers to include an
explanatory note to non-MIME compliant readers.\r
--simple boundary\r
\r
This is implicitly typed plain ASCII text.
It does NOT end with a linebreak.\r
--simple boundary\r
Content-type: text/plain; charset=us-ascii\r
\r
This is explicitly typed plain ASCII text.
It DOES end with a linebreak.
\r
--simple boundary--\r
This is the epilogue. It is also to be ignored.
"
--- more_headers
Content-Type: multipart/mixed; boundary="simple boundary"
--- response_body
got the request socket
preamble: [This is the preamble. It is to be ignored, though it
is a handy place for mail composers to include an
explanatory note to non-MIME compliant readers.]
part 1 body: [This is implicitly typed plain ASCII text.
It does NOT end with a linebreak.]
part 2 header: [Content-type: text/plain; charset=us-ascii]
part 2 body: [This is explicitly typed plain ASCII text.
It DOES end with a linebreak.
]
found the end of the stream
--- no_error_log
[error]

0 comments on commit 7a4cbfb

Please sign in to comment.