Skip to content

Commit 7a4cbfb

Browse files
committed
cosocket: bugfix: fixed a minor inconsistency in the reading iterator returned from sock:receiveuntil when the "size" argument is specified. also added some (passing) tests for a true multipart parser.
1 parent 54a6f75 commit 7a4cbfb

File tree

3 files changed

+268
-10
lines changed

3 files changed

+268
-10
lines changed

src/ngx_http_lua_socket.c

Lines changed: 1 addition & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2243,15 +2243,7 @@ ngx_http_lua_socket_read_until(void *data, ssize_t bytes)
22432243
b->pos += i;
22442244

22452245
if (u->length) {
2246-
if (u->rest != u->length) {
2247-
dd("setting state to -1");
2248-
cp->state = -1;
2249-
2250-
} else {
2251-
dd("setting state to 0");
2252-
cp->state = 0;
2253-
u->luabuf_inited = 0;
2254-
}
2246+
cp->state = -1;
22552247

22562248
} else {
22572249
cp->state = 0;

t/066-socket-receiveuntil.t

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -885,7 +885,7 @@ close: nil closed
885885
886886
local reader = sock:receiveuntil("--abc")
887887
888-
for i = 1, 6 do
888+
for i = 1, 7 do
889889
line, err, part = reader(4)
890890
if line then
891891
ngx.say("read: ", line)
@@ -913,6 +913,7 @@ read: hell
913913
read: o, w
914914
read: orld
915915
read: --
916+
read:
916917
failed to read a line: nil [nil]
917918
failed to read a line: closed [
918919
]

t/067-req-socket.t

Lines changed: 265 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,3 +52,268 @@ failed to receive: closed [d]
5252
--- no_error_log
5353
[error]
5454

55+
56+
57+
=== TEST 2: multipart rfc sample (just partial streaming)
58+
--- config
59+
location /t {
60+
content_by_lua '
61+
local sock, err = ngx.req.socket()
62+
if sock then
63+
ngx.say("got the request socket")
64+
else
65+
ngx.say("failed to get the request socket: ", err)
66+
end
67+
68+
local boundary
69+
local header = ngx.var.http_content_type
70+
local m = ngx.re.match(header, [[; +boundary=(?:"(.*?)"|(\\w+))]], "jo")
71+
if m then
72+
boundary = m[1] or m[2]
73+
74+
else
75+
ngx.say("invalid content-type header")
76+
return
77+
end
78+
79+
local read_to_boundary = sock:receiveuntil("\\r\\n--" .. boundary)
80+
local read_line = sock:receiveuntil("\\r\\n")
81+
82+
local data, err, part = read_to_boundary()
83+
if data then
84+
ngx.say("preamble: [" .. data .. "]")
85+
else
86+
ngx.say("failed to read the first boundary: ", err)
87+
return
88+
end
89+
90+
local i = 1
91+
while true do
92+
local line, err = read_line()
93+
94+
if not line then
95+
ngx.say("failed to read post-boundary line: ", err)
96+
return
97+
end
98+
99+
m = ngx.re.match(line, "--$", "jo")
100+
if m then
101+
ngx.say("found the end of the stream")
102+
return
103+
end
104+
105+
while true do
106+
local line, err = read_line()
107+
if not line then
108+
ngx.say("failed to read part ", i, " header: ", err)
109+
return
110+
end
111+
112+
if line == "" then
113+
-- the header part completes
114+
break
115+
end
116+
117+
ngx.say("part ", i, " header: [", line, "]")
118+
end
119+
120+
local data, err, part = read_to_boundary()
121+
if data then
122+
ngx.say("part ", i, " body: [" .. data .. "]")
123+
else
124+
ngx.say("failed to read part ", i + 1, " boundary: ", err)
125+
return
126+
end
127+
128+
i = i + 1
129+
end
130+
';
131+
}
132+
--- request eval
133+
"POST /t
134+
This is the preamble. It is to be ignored, though it
135+
is a handy place for mail composers to include an
136+
explanatory note to non-MIME compliant readers.\r
137+
--simple boundary\r
138+
\r
139+
This is implicitly typed plain ASCII text.
140+
It does NOT end with a linebreak.\r
141+
--simple boundary\r
142+
Content-type: text/plain; charset=us-ascii\r
143+
\r
144+
This is explicitly typed plain ASCII text.
145+
It DOES end with a linebreak.
146+
\r
147+
--simple boundary--\r
148+
This is the epilogue. It is also to be ignored.
149+
"
150+
--- more_headers
151+
Content-Type: multipart/mixed; boundary="simple boundary"
152+
--- response_body
153+
got the request socket
154+
preamble: [This is the preamble. It is to be ignored, though it
155+
is a handy place for mail composers to include an
156+
explanatory note to non-MIME compliant readers.]
157+
part 1 body: [This is implicitly typed plain ASCII text.
158+
It does NOT end with a linebreak.]
159+
part 2 header: [Content-type: text/plain; charset=us-ascii]
160+
part 2 body: [This is explicitly typed plain ASCII text.
161+
It DOES end with a linebreak.
162+
]
163+
found the end of the stream
164+
--- no_error_log
165+
[error]
166+
167+
168+
169+
=== TEST 3: multipart rfc sample (completely streaming)
170+
--- config
171+
location /t {
172+
content_by_lua '
173+
local sock, err = ngx.req.socket()
174+
if sock then
175+
ngx.say("got the request socket")
176+
else
177+
ngx.say("failed to get the request socket: ", err)
178+
end
179+
180+
local boundary
181+
local header = ngx.var.http_content_type
182+
local m = ngx.re.match(header, [[; +boundary=(?:"(.*?)"|(\\w+))]], "jo")
183+
if m then
184+
boundary = m[1] or m[2]
185+
186+
else
187+
ngx.say("invalid content-type header")
188+
return
189+
end
190+
191+
local read_to_boundary = sock:receiveuntil("\\r\\n--" .. boundary)
192+
local read_line = sock:receiveuntil("\\r\\n")
193+
194+
local preamble = ""
195+
while true do
196+
local data, err, part = read_to_boundary(1)
197+
if data then
198+
preamble = preamble .. data
199+
200+
elseif not err then
201+
break
202+
203+
else
204+
ngx.say("failed to read the first boundary: ", err)
205+
return
206+
end
207+
end
208+
209+
ngx.say("preamble: [" .. preamble .. "]")
210+
211+
local i = 1
212+
while true do
213+
local line, err = read_line(50)
214+
215+
if not line and err then
216+
ngx.say("1: failed to read post-boundary line: ", err)
217+
return
218+
end
219+
220+
if line then
221+
local dummy
222+
dummy, err = read_line(1)
223+
if err then
224+
ngx.say("2: failed to read post-boundary line: ", err)
225+
return
226+
end
227+
228+
if dummy then
229+
ngx.say("bad post-boundary line: ", dummy)
230+
return
231+
end
232+
233+
m = ngx.re.match(line, "--$", "jo")
234+
if m then
235+
ngx.say("found the end of the stream")
236+
return
237+
end
238+
end
239+
240+
while true do
241+
local line, err = read_line(50)
242+
if not line and err then
243+
ngx.say("failed to read part ", i, " header: ", err)
244+
return
245+
end
246+
247+
if line then
248+
local line, err = read_line(1)
249+
if line or err then
250+
ngx.say("error")
251+
return
252+
end
253+
end
254+
255+
if line == "" then
256+
-- the header part completes
257+
break
258+
end
259+
260+
ngx.say("part ", i, " header: [", line, "]")
261+
end
262+
263+
local body = ""
264+
265+
while true do
266+
local data, err, part = read_to_boundary(1)
267+
if data then
268+
body = body .. data
269+
270+
elseif err then
271+
ngx.say("failed to read part ", i + 1, " boundary: ", err)
272+
return
273+
274+
else
275+
break
276+
end
277+
end
278+
279+
ngx.say("part ", i, " body: [" .. body .. "]")
280+
281+
i = i + 1
282+
end
283+
';
284+
}
285+
--- request eval
286+
"POST /t
287+
This is the preamble. It is to be ignored, though it
288+
is a handy place for mail composers to include an
289+
explanatory note to non-MIME compliant readers.\r
290+
--simple boundary\r
291+
\r
292+
This is implicitly typed plain ASCII text.
293+
It does NOT end with a linebreak.\r
294+
--simple boundary\r
295+
Content-type: text/plain; charset=us-ascii\r
296+
\r
297+
This is explicitly typed plain ASCII text.
298+
It DOES end with a linebreak.
299+
\r
300+
--simple boundary--\r
301+
This is the epilogue. It is also to be ignored.
302+
"
303+
--- more_headers
304+
Content-Type: multipart/mixed; boundary="simple boundary"
305+
--- response_body
306+
got the request socket
307+
preamble: [This is the preamble. It is to be ignored, though it
308+
is a handy place for mail composers to include an
309+
explanatory note to non-MIME compliant readers.]
310+
part 1 body: [This is implicitly typed plain ASCII text.
311+
It does NOT end with a linebreak.]
312+
part 2 header: [Content-type: text/plain; charset=us-ascii]
313+
part 2 body: [This is explicitly typed plain ASCII text.
314+
It DOES end with a linebreak.
315+
]
316+
found the end of the stream
317+
--- no_error_log
318+
[error]
319+

0 commit comments

Comments
 (0)