aboutsummaryrefslogtreecommitdiff
path: root/src/http.lua
diff options
context:
space:
mode:
authorDiego Nehab <diego@tecgraf.puc-rio.br>2004-03-16 06:42:53 +0000
committerDiego Nehab <diego@tecgraf.puc-rio.br>2004-03-16 06:42:53 +0000
commitbcc0c2a9f0be2ca796ef5206a78e283fe15e6186 (patch)
tree65c269d4854aa5ff4a0b2c8eede5cdb18d716033 /src/http.lua
parentb6edaac2841137cf0ef5105f75358bbab4570d87 (diff)
downloadluasocket-bcc0c2a9f0be2ca796ef5206a78e283fe15e6186.tar.gz
luasocket-bcc0c2a9f0be2ca796ef5206a78e283fe15e6186.tar.bz2
luasocket-bcc0c2a9f0be2ca796ef5206a78e283fe15e6186.zip
New filter scheme.
ltn12 and mime updated. smtp/ftp broken.
Diffstat (limited to 'src/http.lua')
-rw-r--r--src/http.lua219
1 files changed, 104 insertions, 115 deletions
diff --git a/src/http.lua b/src/http.lua
index 74c29ba..629bf65 100644
--- a/src/http.lua
+++ b/src/http.lua
@@ -10,12 +10,11 @@ if not LUASOCKET_LIBNAME then error('module requires LuaSocket') end
10-- get LuaSocket namespace 10-- get LuaSocket namespace
11local socket = _G[LUASOCKET_LIBNAME] 11local socket = _G[LUASOCKET_LIBNAME]
12if not socket then error('module requires LuaSocket') end 12if not socket then error('module requires LuaSocket') end
13-- create smtp namespace inside LuaSocket namespace 13-- create namespace inside LuaSocket namespace
14local http = socket.http or {} 14socket.http = socket.http or {}
15socket.http = http 15-- make all module globals fall into namespace
16-- make all module globals fall into smtp namespace 16setmetatable(socket.http, { __index = _G })
17setmetatable(http, { __index = _G }) 17setfenv(1, socket.http)
18setfenv(1, http)
19 18
20----------------------------------------------------------------------------- 19-----------------------------------------------------------------------------
21-- Program constants 20-- Program constants
@@ -27,7 +26,18 @@ PORT = 80
27-- user agent field sent in request 26-- user agent field sent in request
28USERAGENT = socket.version 27USERAGENT = socket.version
29-- block size used in transfers 28-- block size used in transfers
30BLOCKSIZE = 8192 29BLOCKSIZE = 2048
30
31-----------------------------------------------------------------------------
32-- Function return value selectors
33-----------------------------------------------------------------------------
34local function second(a, b)
35 return b
36end
37
38local function third(a, b, c)
39 return c
40end
31 41
32----------------------------------------------------------------------------- 42-----------------------------------------------------------------------------
33-- Tries to get a pattern from the server and closes socket on error 43-- Tries to get a pattern from the server and closes socket on error
@@ -47,7 +57,7 @@ end
47----------------------------------------------------------------------------- 57-----------------------------------------------------------------------------
48-- Tries to send data to the server and closes socket on error 58-- Tries to send data to the server and closes socket on error
49-- sock: socket connected to the server 59-- sock: socket connected to the server
50-- data: data to send 60-- ...: data to send
51-- Returns 61-- Returns
52-- err: error message if any, nil if successfull 62-- err: error message if any, nil if successfull
53----------------------------------------------------------------------------- 63-----------------------------------------------------------------------------
@@ -68,11 +78,9 @@ end
68-- err: error message if any 78-- err: error message if any
69----------------------------------------------------------------------------- 79-----------------------------------------------------------------------------
70local function receive_status(sock) 80local function receive_status(sock)
71 local line, err 81 local line, err = try_receiving(sock)
72 line, err = try_receiving(sock)
73 if not err then 82 if not err then
74 local code, _ 83 local code = third(string.find(line, "HTTP/%d*%.%d* (%d%d%d)"))
75 _, _, code = string.find(line, "HTTP/%d*%.%d* (%d%d%d)")
76 return tonumber(code), line 84 return tonumber(code), line
77 else return nil, nil, err end 85 else return nil, nil, err end
78end 86end
@@ -121,7 +129,7 @@ local function receive_headers(sock, headers)
121end 129end
122 130
123----------------------------------------------------------------------------- 131-----------------------------------------------------------------------------
124-- Aborts a receive callback 132-- Aborts a sink with an error message
125-- Input 133-- Input
126-- cb: callback function 134-- cb: callback function
127-- err: error message to pass to callback 135-- err: error message to pass to callback
@@ -129,8 +137,8 @@ end
129-- callback return or if nil err 137-- callback return or if nil err
130----------------------------------------------------------------------------- 138-----------------------------------------------------------------------------
131local function abort(cb, err) 139local function abort(cb, err)
132 local go, err_or_f = cb(nil, err) 140 local go, cb_err = cb(nil, err)
133 return err_or_f or err 141 return cb_err or err
134end 142end
135 143
136----------------------------------------------------------------------------- 144-----------------------------------------------------------------------------
@@ -138,41 +146,36 @@ end
138-- Input 146-- Input
139-- sock: socket connected to the server 147-- sock: socket connected to the server
140-- headers: header set in which to include trailer headers 148-- headers: header set in which to include trailer headers
141-- receive_cb: function to receive chunks 149-- sink: response message body sink
142-- Returns 150-- Returns
143-- nil if successfull or an error message in case of error 151-- nil if successfull or an error message in case of error
144----------------------------------------------------------------------------- 152-----------------------------------------------------------------------------
145local function receive_body_bychunks(sock, headers, receive_cb) 153local function receive_body_bychunks(sock, headers, sink)
146 local chunk, size, line, err, go, err_or_f, _ 154 local chunk, size, line, err, go
147 while 1 do 155 while 1 do
148 -- get chunk size, skip extention 156 -- get chunk size, skip extention
149 line, err = try_receiving(sock) 157 line, err = try_receiving(sock)
150 if err then return abort(receive_cb, err) end 158 if err then return abort(sink, err) end
151 size = tonumber(string.gsub(line, ";.*", ""), 16) 159 size = tonumber(string.gsub(line, ";.*", ""), 16)
152 if not size then return abort(receive_cb, "invalid chunk size") end 160 if not size then return abort(sink, "invalid chunk size") end
153 -- was it the last chunk? 161 -- was it the last chunk?
154 if size <= 0 then break end 162 if size <= 0 then break end
155 -- get chunk 163 -- get chunk
156 chunk, err = try_receiving(sock, size) 164 chunk, err = try_receiving(sock, size)
157 if err then return abort(receive_cb, err) end 165 if err then return abort(sink, err) end
158 -- pass chunk to callback 166 -- pass chunk to callback
159 go, err_or_f = receive_cb(chunk) 167 go, err = sink(chunk)
160 -- see if callback needs to be replaced
161 receive_cb = err_or_f or receive_cb
162 -- see if callback aborted 168 -- see if callback aborted
163 if not go then return err_or_f or "aborted by callback" end 169 if not go then return err or "aborted by callback" end
164 -- skip CRLF on end of chunk 170 -- skip CRLF on end of chunk
165 _, err = try_receiving(sock) 171 err = second(try_receiving(sock))
166 if err then return abort(receive_cb, err) end 172 if err then return abort(sink, err) end
167 end 173 end
168 -- the server should not send trailer headers because we didn't send a 174 -- servers shouldn't send trailer headers, but who trusts them?
169 -- header informing it we know how to deal with them. we do not risk 175 err = second(receive_headers(sock, headers))
170 -- being caught unprepaired. 176 if err then return abort(sink, err) end
171 _, err = receive_headers(sock, headers)
172 if err then return abort(receive_cb, err) end
173 -- let callback know we are done 177 -- let callback know we are done
174 _, err_or_f = receive_cb("") 178 return second(sink(nil))
175 return err_or_f
176end 179end
177 180
178----------------------------------------------------------------------------- 181-----------------------------------------------------------------------------
@@ -180,94 +183,84 @@ end
180-- Input 183-- Input
181-- sock: socket connected to the server 184-- sock: socket connected to the server
182-- length: message body length 185-- length: message body length
183-- receive_cb: function to receive chunks 186-- sink: response message body sink
184-- Returns 187-- Returns
185-- nil if successfull or an error message in case of error 188-- nil if successfull or an error message in case of error
186----------------------------------------------------------------------------- 189-----------------------------------------------------------------------------
187local function receive_body_bylength(sock, length, receive_cb) 190local function receive_body_bylength(sock, length, sink)
188 while length > 0 do 191 while length > 0 do
189 local size = math.min(BLOCKSIZE, length) 192 local size = math.min(BLOCKSIZE, length)
190 local chunk, err = sock:receive(size) 193 local chunk, err = sock:receive(size)
191 local go, err_or_f = receive_cb(chunk) 194 local go, cb_err = sink(chunk)
192 length = length - string.len(chunk) 195 length = length - string.len(chunk)
193 -- see if callback aborted 196 -- see if callback aborted
194 if not go then return err_or_f or "aborted by callback" end 197 if not go then return cb_err or "aborted by callback" end
195 -- see if callback needs to be replaced
196 receive_cb = err_or_f or receive_cb
197 -- see if there was an error 198 -- see if there was an error
198 if err and length > 0 then return abort(receive_cb, err) end 199 if err and length > 0 then return abort(sink, err) end
199 end 200 end
200 local _, err_or_f = receive_cb("") 201 return second(sink(nil))
201 return err_or_f
202end 202end
203 203
204----------------------------------------------------------------------------- 204-----------------------------------------------------------------------------
205-- Receives a message body by content-length 205-- Receives a message body until the conection is closed
206-- Input 206-- Input
207-- sock: socket connected to the server 207-- sock: socket connected to the server
208-- receive_cb: function to receive chunks 208-- sink: response message body sink
209-- Returns 209-- Returns
210-- nil if successfull or an error message in case of error 210-- nil if successfull or an error message in case of error
211----------------------------------------------------------------------------- 211-----------------------------------------------------------------------------
212local function receive_body_untilclosed(sock, receive_cb) 212local function receive_body_untilclosed(sock, sink)
213 while 1 do 213 while 1 do
214 local chunk, err = sock:receive(BLOCKSIZE) 214 local chunk, err = sock:receive(BLOCKSIZE)
215 local go, err_or_f = receive_cb(chunk) 215 local go, cb_err = sink(chunk)
216 -- see if callback aborted 216 -- see if callback aborted
217 if not go then return err_or_f or "aborted by callback" end 217 if not go then return cb_err or "aborted by callback" end
218 -- see if callback needs to be replaced
219 receive_cb = err_or_f or receive_cb
220 -- see if we are done 218 -- see if we are done
221 if err == "closed" then 219 if err == "closed" then return chunk and second(sink(nil)) end
222 if chunk ~= "" then
223 go, err_or_f = receive_cb("")
224 return err_or_f
225 end
226 end
227 -- see if there was an error 220 -- see if there was an error
228 if err then return abort(receive_cb, err) end 221 if err then return abort(sink, err) end
229 end 222 end
230end 223end
231 224
232----------------------------------------------------------------------------- 225-----------------------------------------------------------------------------
233-- Receives HTTP response body 226-- Receives the HTTP response body
234-- Input 227-- Input
235-- sock: socket connected to the server 228-- sock: socket connected to the server
236-- headers: response header fields 229-- headers: response header fields
237-- receive_cb: function to receive chunks 230-- sink: response message body sink
238-- Returns 231-- Returns
239-- nil if successfull or an error message in case of error 232-- nil if successfull or an error message in case of error
240----------------------------------------------------------------------------- 233-----------------------------------------------------------------------------
241local function receive_body(sock, headers, receive_cb) 234local function receive_body(sock, headers, sink)
235 -- make sure sink is not fancy
236 sink = ltn12.sink.simplify(sink)
242 local te = headers["transfer-encoding"] 237 local te = headers["transfer-encoding"]
243 if te and te ~= "identity" then 238 if te and te ~= "identity" then
244 -- get by chunked transfer-coding of message body 239 -- get by chunked transfer-coding of message body
245 return receive_body_bychunks(sock, headers, receive_cb) 240 return receive_body_bychunks(sock, headers, sink)
246 elseif tonumber(headers["content-length"]) then 241 elseif tonumber(headers["content-length"]) then
247 -- get by content-length 242 -- get by content-length
248 local length = tonumber(headers["content-length"]) 243 local length = tonumber(headers["content-length"])
249 return receive_body_bylength(sock, length, receive_cb) 244 return receive_body_bylength(sock, length, sink)
250 else 245 else
251 -- get it all until connection closes 246 -- get it all until connection closes
252 return receive_body_untilclosed(sock, receive_cb) 247 return receive_body_untilclosed(sock, sink)
253 end 248 end
254end 249end
255 250
256----------------------------------------------------------------------------- 251-----------------------------------------------------------------------------
257-- Sends data comming from a callback 252-- Sends the HTTP request message body in chunks
258-- Input 253-- Input
259-- data: data connection 254-- data: data connection
260-- send_cb: callback to produce file contents 255-- source: request message body source
261-- Returns 256-- Returns
262-- nil if successfull, or an error message in case of error 257-- nil if successfull, or an error message in case of error
263----------------------------------------------------------------------------- 258-----------------------------------------------------------------------------
264local function send_body_bychunks(data, send_cb) 259local function send_body_bychunks(data, source)
265 while 1 do 260 while 1 do
266 local chunk, err_or_f = send_cb() 261 local chunk, cb_err = source()
267 -- check if callback aborted 262 -- check if callback aborted
268 if not chunk then return err_or_f or "aborted by callback" end 263 if not chunk then return cb_err or "aborted by callback" end
269 -- check if callback should be replaced
270 send_cb = err_or_f or send_cb
271 -- if we are done, send last-chunk 264 -- if we are done, send last-chunk
272 if chunk == "" then return try_sending(data, "0\r\n\r\n") end 265 if chunk == "" then return try_sending(data, "0\r\n\r\n") end
273 -- else send middle chunk 266 -- else send middle chunk
@@ -281,22 +274,18 @@ local function send_body_bychunks(data, send_cb)
281end 274end
282 275
283----------------------------------------------------------------------------- 276-----------------------------------------------------------------------------
284-- Sends data comming from a callback 277-- Sends the HTTP request message body
285-- Input 278-- Input
286-- data: data connection 279-- data: data connection
287-- send_cb: callback to produce body contents 280-- source: request message body source
288-- Returns 281-- Returns
289-- nil if successfull, or an error message in case of error 282-- nil if successfull, or an error message in case of error
290----------------------------------------------------------------------------- 283-----------------------------------------------------------------------------
291local function send_body_bylength(data, send_cb) 284local function send_body(data, source)
292 while 1 do 285 while 1 do
293 local chunk, err_or_f = send_cb() 286 local chunk, cb_err = source()
294 -- check if callback aborted
295 if not chunk then return err_or_f or "aborted by callback" end
296 -- check if callback should be replaced
297 send_cb = err_or_f or send_cb
298 -- check if callback is done 287 -- check if callback is done
299 if chunk == "" then return end 288 if not chunk then return cb_err end
300 -- send data 289 -- send data
301 local err = try_sending(data, chunk) 290 local err = try_sending(data, chunk)
302 if err then return err end 291 if err then return err end
@@ -304,10 +293,10 @@ local function send_body_bylength(data, send_cb)
304end 293end
305 294
306----------------------------------------------------------------------------- 295-----------------------------------------------------------------------------
307-- Sends mime headers 296-- Sends request headers
308-- Input 297-- Input
309-- sock: server socket 298-- sock: server socket
310-- headers: table with mime headers to be sent 299-- headers: table with headers to be sent
311-- Returns 300-- Returns
312-- err: error message if any 301-- err: error message if any
313----------------------------------------------------------------------------- 302-----------------------------------------------------------------------------
@@ -330,27 +319,29 @@ end
330-- method: request method to be used 319-- method: request method to be used
331-- uri: request uri 320-- uri: request uri
332-- headers: request headers to be sent 321-- headers: request headers to be sent
333-- body_cb: callback to send request message body 322-- source: request message body source
334-- Returns 323-- Returns
335-- err: nil in case of success, error message otherwise 324-- err: nil in case of success, error message otherwise
336----------------------------------------------------------------------------- 325-----------------------------------------------------------------------------
337local function send_request(sock, method, uri, headers, body_cb) 326local function send_request(sock, method, uri, headers, source)
338 local chunk, size, done, err 327 local chunk, size, done, err
339 -- send request line 328 -- send request line
340 err = try_sending(sock, method .. " " .. uri .. " HTTP/1.1\r\n") 329 err = try_sending(sock, method .. " " .. uri .. " HTTP/1.1\r\n")
341 if err then return err end 330 if err then return err end
342 if body_cb and not headers["content-length"] then 331 if source and not headers["content-length"] then
343 headers["transfer-encoding"] = "chunked" 332 headers["transfer-encoding"] = "chunked"
344 end 333 end
345 -- send request headers 334 -- send request headers
346 err = send_headers(sock, headers) 335 err = send_headers(sock, headers)
347 if err then return err end 336 if err then return err end
348 -- send request message body, if any 337 -- send request message body, if any
349 if body_cb then 338 if source then
350 if not headers["content-length"] then 339 -- make sure source is not fancy
351 return send_body_bychunks(sock, body_cb) 340 source = ltn12.source.simplify(source)
341 if headers["content-length"] then
342 return send_body(sock, source)
352 else 343 else
353 return send_body_bylength(sock, body_cb) 344 return send_body_bychunks(sock, source)
354 end 345 end
355 end 346 end
356end 347end
@@ -415,23 +406,23 @@ end
415-- Input 406-- Input
416-- reqt: a table with the original request information 407-- reqt: a table with the original request information
417-- parsed: parsed request URL 408-- parsed: parsed request URL
418-- respt: a table with the server response information
419-- Returns 409-- Returns
420-- respt: result of target authorization 410-- respt: result of target authorization
421----------------------------------------------------------------------------- 411-----------------------------------------------------------------------------
422local function authorize(reqt, parsed, respt) 412local function authorize(reqt, parsed)
423 reqt.headers["authorization"] = "Basic " .. 413 reqt.headers["authorization"] = "Basic " ..
424 (socket.mime.b64(parsed.user .. ":" .. parsed.password)) 414 (mime.b64(parsed.user .. ":" .. parsed.password))
425 local autht = { 415 local autht = {
426 nredirects = reqt.nredirects, 416 nredirects = reqt.nredirects,
427 method = reqt.method, 417 method = reqt.method,
428 url = reqt.url, 418 url = reqt.url,
429 body_cb = reqt.body_cb, 419 source = reqt.source,
420 sink = reqt.sink,
430 headers = reqt.headers, 421 headers = reqt.headers,
431 timeout = reqt.timeout, 422 timeout = reqt.timeout,
432 proxy = reqt.proxy, 423 proxy = reqt.proxy,
433 } 424 }
434 return request_cb(autht, respt) 425 return request_cb(autht)
435end 426end
436 427
437----------------------------------------------------------------------------- 428-----------------------------------------------------------------------------
@@ -443,8 +434,8 @@ end
443-- 1 if we should redirect, nil otherwise 434-- 1 if we should redirect, nil otherwise
444----------------------------------------------------------------------------- 435-----------------------------------------------------------------------------
445local function should_redirect(reqt, respt) 436local function should_redirect(reqt, respt)
446 return (reqt.redirect ~= false) and 437 return (reqt.redirect ~= false) and
447 (respt.code == 301 or respt.code == 302) and 438 (respt.code == 301 or respt.code == 302) and
448 (reqt.method == "GET" or reqt.method == "HEAD") and 439 (reqt.method == "GET" or reqt.method == "HEAD") and
449 not (reqt.nredirects and reqt.nredirects >= 5) 440 not (reqt.nredirects and reqt.nredirects >= 5)
450end 441end
@@ -453,8 +444,7 @@ end
453-- Returns the result of a request following a server redirect message. 444-- Returns the result of a request following a server redirect message.
454-- Input 445-- Input
455-- reqt: a table with the original request information 446-- reqt: a table with the original request information
456-- respt: a table with the following fields: 447-- respt: response table of previous attempt
457-- body_cb: response method body receive-callback
458-- Returns 448-- Returns
459-- respt: result of target redirection 449-- respt: result of target redirection
460----------------------------------------------------------------------------- 450-----------------------------------------------------------------------------
@@ -467,12 +457,13 @@ local function redirect(reqt, respt)
467 -- the RFC says the redirect URL has to be absolute, but some 457 -- the RFC says the redirect URL has to be absolute, but some
468 -- servers do not respect that 458 -- servers do not respect that
469 url = socket.url.absolute(reqt.url, respt.headers["location"]), 459 url = socket.url.absolute(reqt.url, respt.headers["location"]),
470 body_cb = reqt.body_cb, 460 source = reqt.source,
461 sink = reqt.sink,
471 headers = reqt.headers, 462 headers = reqt.headers,
472 timeout = reqt.timeout, 463 timeout = reqt.timeout,
473 proxy = reqt.proxy 464 proxy = reqt.proxy
474 } 465 }
475 respt = request_cb(redirt, respt) 466 respt = request_cb(redirt)
476 -- we pass the location header as a clue we tried to redirect 467 -- we pass the location header as a clue we tried to redirect
477 if respt.headers then respt.headers.location = redirt.url end 468 if respt.headers then respt.headers.location = redirt.url end
478 return respt 469 return respt
@@ -562,10 +553,9 @@ end
562-- url: target uniform resource locator 553-- url: target uniform resource locator
563-- user, password: authentication information 554-- user, password: authentication information
564-- headers: request headers to send, or nil if none 555-- headers: request headers to send, or nil if none
565-- body_cb: request message body send-callback, or nil if none 556-- source: request message body source, or nil if none
557-- sink: response message body sink
566-- redirect: should we refrain from following a server redirect message? 558-- redirect: should we refrain from following a server redirect message?
567-- respt: a table with the following fields:
568-- body_cb: response method body receive-callback
569-- Returns 559-- Returns
570-- respt: a table with the following fields: 560-- respt: a table with the following fields:
571-- headers: response header fields received, or nil if failed 561-- headers: response header fields received, or nil if failed
@@ -573,7 +563,7 @@ end
573-- code: server status code, or nil if failed 563-- code: server status code, or nil if failed
574-- error: error message, or nil if successfull 564-- error: error message, or nil if successfull
575----------------------------------------------------------------------------- 565-----------------------------------------------------------------------------
576function request_cb(reqt, respt) 566function request_cb(reqt)
577 local sock, ret 567 local sock, ret
578 local parsed = socket.url.parse(reqt.url, { 568 local parsed = socket.url.parse(reqt.url, {
579 host = "", 569 host = "",
@@ -581,6 +571,7 @@ function request_cb(reqt, respt)
581 path ="/", 571 path ="/",
582 scheme = "http" 572 scheme = "http"
583 }) 573 })
574 local respt = {}
584 if parsed.scheme ~= "http" then 575 if parsed.scheme ~= "http" then
585 respt.error = string.format("unknown scheme '%s'", parsed.scheme) 576 respt.error = string.format("unknown scheme '%s'", parsed.scheme)
586 return respt 577 return respt
@@ -597,7 +588,7 @@ function request_cb(reqt, respt)
597 if not sock then return respt end 588 if not sock then return respt end
598 -- send request message 589 -- send request message
599 respt.error = send_request(sock, reqt.method, 590 respt.error = send_request(sock, reqt.method,
600 request_uri(reqt, parsed), reqt.headers, reqt.body_cb) 591 request_uri(reqt, parsed), reqt.headers, reqt.source)
601 if respt.error then 592 if respt.error then
602 sock:close() 593 sock:close()
603 return respt 594 return respt
@@ -619,18 +610,18 @@ function request_cb(reqt, respt)
619 -- decide what to do based on request and response parameters 610 -- decide what to do based on request and response parameters
620 if should_redirect(reqt, respt) then 611 if should_redirect(reqt, respt) then
621 -- drop the body 612 -- drop the body
622 receive_body(sock, respt.headers, function (c, e) return 1 end) 613 receive_body(sock, respt.headers, ltn12.sink.null())
623 -- we are done with this connection 614 -- we are done with this connection
624 sock:close() 615 sock:close()
625 return redirect(reqt, respt) 616 return redirect(reqt, respt)
626 elseif should_authorize(reqt, parsed, respt) then 617 elseif should_authorize(reqt, parsed, respt) then
627 -- drop the body 618 -- drop the body
628 receive_body(sock, respt.headers, function (c, e) return 1 end) 619 receive_body(sock, respt.headers, ltn12.sink.null())
629 -- we are done with this connection 620 -- we are done with this connection
630 sock:close() 621 sock:close()
631 return authorize(reqt, parsed, respt) 622 return authorize(reqt, parsed, respt)
632 elseif should_receive_body(reqt, respt) then 623 elseif should_receive_body(reqt, respt) then
633 respt.error = receive_body(sock, respt.headers, respt.body_cb) 624 respt.error = receive_body(sock, respt.headers, reqt.sink)
634 if respt.error then return respt end 625 if respt.error then return respt end
635 sock:close() 626 sock:close()
636 return respt 627 return respt
@@ -658,13 +649,11 @@ end
658-- error: error message if any 649-- error: error message if any
659----------------------------------------------------------------------------- 650-----------------------------------------------------------------------------
660function request(reqt) 651function request(reqt)
661 local respt = {} 652 reqt.source = reqt.body and ltn12.source.string(reqt.body)
662 reqt.body_cb = socket.callback.send.string(reqt.body) 653 local t = {}
663 local concat = socket.concat.create() 654 reqt.sink = ltn12.sink.table(t)
664 respt.body_cb = socket.callback.receive.concat(concat) 655 local respt = request_cb(reqt)
665 respt = request_cb(reqt, respt) 656 if table.getn(t) > 0 then respt.body = table.concat(t) end
666 respt.body = concat:getresult()
667 respt.body_cb = nil
668 return respt 657 return respt
669end 658end
670 659
@@ -713,4 +702,4 @@ function post(url_or_request, body)
713 return respt.body, respt.headers, respt.code, respt.error 702 return respt.body, respt.headers, respt.code, respt.error
714end 703end
715 704
716return http 705return socket.http