aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDiego Nehab <diego@tecgraf.puc-rio.br>2002-07-08 21:01:18 +0000
committerDiego Nehab <diego@tecgraf.puc-rio.br>2002-07-08 21:01:18 +0000
commit60e7bf48b077377c11022f34e24bbbfb596397bf (patch)
treed534436cdd12f492e39a947a4b26799aa39bb24d
parent9d7f43768aaa6d9f4b604c7e837a33755078ae15 (diff)
downloadluasocket-60e7bf48b077377c11022f34e24bbbfb596397bf.tar.gz
luasocket-60e7bf48b077377c11022f34e24bbbfb596397bf.tar.bz2
luasocket-60e7bf48b077377c11022f34e24bbbfb596397bf.zip
Updated for Lua 4.1-w3.
Dealing with 100 response codes.
-rw-r--r--src/http.lua109
1 files changed, 55 insertions, 54 deletions
diff --git a/src/http.lua b/src/http.lua
index e4c756f..9832a6b 100644
--- a/src/http.lua
+++ b/src/http.lua
@@ -1,6 +1,6 @@
1----------------------------------------------------------------------------- 1-----------------------------------------------------------------------------
2-- HTTP/1.1 client support for the Lua language. 2-- HTTP/1.1 client support for the Lua language.
3-- LuaSocket 1.4 toolkit. 3-- LuaSocket 1.5 toolkit.
4-- Author: Diego Nehab 4-- Author: Diego Nehab
5-- Date: 26/12/2000 5-- Date: 26/12/2000
6-- Conforming to: RFC 2616, LTN7 6-- Conforming to: RFC 2616, LTN7
@@ -18,18 +18,11 @@ Public.TIMEOUT = 60
18-- default port for document retrieval 18-- default port for document retrieval
19Public.PORT = 80 19Public.PORT = 80
20-- user agent field sent in request 20-- user agent field sent in request
21Public.USERAGENT = "LuaSocket 1.4" 21Public.USERAGENT = "LuaSocket 1.5"
22-- block size used in transfers 22-- block size used in transfers
23Public.BLOCKSIZE = 8192 23Public.BLOCKSIZE = 8192
24 24
25----------------------------------------------------------------------------- 25-----------------------------------------------------------------------------
26-- Required libraries
27-----------------------------------------------------------------------------
28dofile "concat.lua"
29dofile "url.lua"
30dofile "code.lua"
31
32-----------------------------------------------------------------------------
33-- Tries to get a pattern from the server and closes socket on error 26-- Tries to get a pattern from the server and closes socket on error
34-- sock: socket connected to the server 27-- sock: socket connected to the server
35-- ...: pattern to receive 28-- ...: pattern to receive
@@ -84,8 +77,8 @@ end
84----------------------------------------------------------------------------- 77-----------------------------------------------------------------------------
85function Private.receive_status(sock) 78function Private.receive_status(sock)
86 local line, err 79 local line, err
87 line, err = %Private.try_receive(sock) 80 line, err = Private.try_receive(sock)
88 if not err then return %Private.get_statuscode(line), line 81 if not err then return Private.get_statuscode(line), line
89 else return nil, nil, err end 82 else return nil, nil, err end
90end 83end
91 84
@@ -104,7 +97,7 @@ function Private.receive_headers(sock, headers)
104 local line, err 97 local line, err
105 local name, value, _ 98 local name, value, _
106 -- get first line 99 -- get first line
107 line, err = %Private.try_receive(sock) 100 line, err = Private.try_receive(sock)
108 if err then return nil, err end 101 if err then return nil, err end
109 -- headers go until a blank line is found 102 -- headers go until a blank line is found
110 while line ~= "" do 103 while line ~= "" do
@@ -116,12 +109,12 @@ function Private.receive_headers(sock, headers)
116 end 109 end
117 name = strlower(name) 110 name = strlower(name)
118 -- get next line (value might be folded) 111 -- get next line (value might be folded)
119 line, err = %Private.try_receive(sock) 112 line, err = Private.try_receive(sock)
120 if err then return nil, err end 113 if err then return nil, err end
121 -- unfold any folded values 114 -- unfold any folded values
122 while not err and strfind(line, "^%s") do 115 while not err and strfind(line, "^%s") do
123 value = value .. line 116 value = value .. line
124 line, err = %Private.try_receive(sock) 117 line, err = Private.try_receive(sock)
125 if err then return nil, err end 118 if err then return nil, err end
126 end 119 end
127 -- save pair in table 120 -- save pair in table
@@ -144,7 +137,7 @@ function Private.receivebody_bychunks(sock, headers, receive_cb)
144 local chunk, size, line, err, go, uerr, _ 137 local chunk, size, line, err, go, uerr, _
145 while 1 do 138 while 1 do
146 -- get chunk size, skip extention 139 -- get chunk size, skip extention
147 line, err = %Private.try_receive(sock) 140 line, err = Private.try_receive(sock)
148 if err then 141 if err then
149 local go, uerr = receive_cb(nil, err) 142 local go, uerr = receive_cb(nil, err)
150 return uerr or err 143 return uerr or err
@@ -159,7 +152,7 @@ function Private.receivebody_bychunks(sock, headers, receive_cb)
159 -- was it the last chunk? 152 -- was it the last chunk?
160 if size <= 0 then break end 153 if size <= 0 then break end
161 -- get chunk 154 -- get chunk
162 chunk, err = %Private.try_receive(sock, size) 155 chunk, err = Private.try_receive(sock, size)
163 if err then 156 if err then
164 go, uerr = receive_cb(nil, err) 157 go, uerr = receive_cb(nil, err)
165 return uerr or err 158 return uerr or err
@@ -171,7 +164,7 @@ function Private.receivebody_bychunks(sock, headers, receive_cb)
171 return uerr or "aborted by callback" 164 return uerr or "aborted by callback"
172 end 165 end
173 -- skip CRLF on end of chunk 166 -- skip CRLF on end of chunk
174 _, err = %Private.try_receive(sock) 167 _, err = Private.try_receive(sock)
175 if err then 168 if err then
176 go, uerr = receive_cb(nil, err) 169 go, uerr = receive_cb(nil, err)
177 return uerr or err 170 return uerr or err
@@ -180,7 +173,7 @@ function Private.receivebody_bychunks(sock, headers, receive_cb)
180 -- the server should not send trailer headers because we didn't send a 173 -- the server should not send trailer headers because we didn't send a
181 -- header informing it we know how to deal with them. we do not risk 174 -- header informing it we know how to deal with them. we do not risk
182 -- being caught unprepaired. 175 -- being caught unprepaired.
183 headers, err = %Private.receive_headers(sock, headers) 176 headers, err = Private.receive_headers(sock, headers)
184 if err then 177 if err then
185 go, uerr = receive_cb(nil, err) 178 go, uerr = receive_cb(nil, err)
186 return uerr or err 179 return uerr or err
@@ -202,7 +195,7 @@ end
202function Private.receivebody_bylength(sock, length, receive_cb) 195function Private.receivebody_bylength(sock, length, receive_cb)
203 local uerr, go 196 local uerr, go
204 while length > 0 do 197 while length > 0 do
205 local size = min(%Public.BLOCKSIZE, length) 198 local size = min(Public.BLOCKSIZE, length)
206 local chunk, err = sock:receive(size) 199 local chunk, err = sock:receive(size)
207 if err then 200 if err then
208 go, uerr = receive_cb(nil, err) 201 go, uerr = receive_cb(nil, err)
@@ -230,7 +223,7 @@ end
230function Private.receivebody_untilclosed(sock, receive_cb) 223function Private.receivebody_untilclosed(sock, receive_cb)
231 local err, go, uerr 224 local err, go, uerr
232 while 1 do 225 while 1 do
233 local chunk, err = sock:receive(%Public.BLOCKSIZE) 226 local chunk, err = sock:receive(Public.BLOCKSIZE)
234 if err == "closed" or not err then 227 if err == "closed" or not err then
235 go, uerr = receive_cb(chunk) 228 go, uerr = receive_cb(chunk)
236 if not go then 229 if not go then
@@ -260,14 +253,14 @@ function Private.receive_body(sock, headers, receive_cb)
260 local te = headers["transfer-encoding"] 253 local te = headers["transfer-encoding"]
261 if te and te ~= "identity" then 254 if te and te ~= "identity" then
262 -- get by chunked transfer-coding of message body 255 -- get by chunked transfer-coding of message body
263 return %Private.receivebody_bychunks(sock, headers, receive_cb) 256 return Private.receivebody_bychunks(sock, headers, receive_cb)
264 elseif tonumber(headers["content-length"]) then 257 elseif tonumber(headers["content-length"]) then
265 -- get by content-length 258 -- get by content-length
266 local length = tonumber(headers["content-length"]) 259 local length = tonumber(headers["content-length"])
267 return %Private.receivebody_bylength(sock, length, receive_cb) 260 return Private.receivebody_bylength(sock, length, receive_cb)
268 else 261 else
269 -- get it all until connection closes 262 -- get it all until connection closes
270 return %Private.receivebody_untilclosed(sock, receive_cb) 263 return Private.receivebody_untilclosed(sock, receive_cb)
271 end 264 end
272end 265end
273 266
@@ -280,7 +273,7 @@ end
280-- nil if successfull or an error message in case of error 273-- nil if successfull or an error message in case of error
281----------------------------------------------------------------------------- 274-----------------------------------------------------------------------------
282function Private.drop_body(sock, headers) 275function Private.drop_body(sock, headers)
283 return %Private.receive_body(sock, headers, function (c, e) return 1 end) 276 return Private.receive_body(sock, headers, function (c, e) return 1 end)
284end 277end
285 278
286----------------------------------------------------------------------------- 279-----------------------------------------------------------------------------
@@ -325,11 +318,11 @@ function Private.send_headers(sock, headers)
325 headers = headers or {} 318 headers = headers or {}
326 -- send request headers 319 -- send request headers
327 for i, v in headers do 320 for i, v in headers do
328 err = %Private.try_send(sock, i .. ": " .. v .. "\r\n") 321 err = Private.try_send(sock, i .. ": " .. v .. "\r\n")
329 if err then return err end 322 if err then return err end
330 end 323 end
331 -- mark end of request headers 324 -- mark end of request headers
332 return %Private.try_send(sock, "\r\n") 325 return Private.try_send(sock, "\r\n")
333end 326end
334 327
335----------------------------------------------------------------------------- 328-----------------------------------------------------------------------------
@@ -346,7 +339,7 @@ end
346function Private.send_request(sock, method, uri, headers, body_cb) 339function Private.send_request(sock, method, uri, headers, body_cb)
347 local chunk, size, done, err 340 local chunk, size, done, err
348 -- send request line 341 -- send request line
349 err = %Private.try_send(sock, method .. " " .. uri .. " HTTP/1.1\r\n") 342 err = Private.try_send(sock, method .. " " .. uri .. " HTTP/1.1\r\n")
350 if err then return err end 343 if err then return err end
351 -- if there is a request message body, add content-length header 344 -- if there is a request message body, add content-length header
352 if body_cb then 345 if body_cb then
@@ -360,11 +353,11 @@ function Private.send_request(sock, method, uri, headers, body_cb)
360 end 353 end
361 end 354 end
362 -- send request headers 355 -- send request headers
363 err = %Private.send_headers(sock, headers) 356 err = Private.send_headers(sock, headers)
364 if err then return err end 357 if err then return err end
365 -- send request message body, if any 358 -- send request message body, if any
366 if body_cb then 359 if body_cb then
367 return %Private.send_indirect(sock, body_cb, chunk, size) 360 return Private.send_indirect(sock, body_cb, chunk, size)
368 end 361 end
369end 362end
370 363
@@ -395,7 +388,7 @@ function Private.fill_headers(headers, parsed)
395 local lower = {} 388 local lower = {}
396 headers = headers or {} 389 headers = headers or {}
397 -- set default headers 390 -- set default headers
398 lower["user-agent"] = %Public.USERAGENT 391 lower["user-agent"] = Public.USERAGENT
399 -- override with user values 392 -- override with user values
400 for i,v in headers do 393 for i,v in headers do
401 lower[strlower(i)] = v 394 lower[strlower(i)] = v
@@ -442,7 +435,7 @@ function Private.authorize(request, parsed, response)
442 body_cb = request.body_cb, 435 body_cb = request.body_cb,
443 headers = request.headers 436 headers = request.headers
444 } 437 }
445 return %Public.request_cb(authorize, response) 438 return Public.request_cb(authorize, response)
446end 439end
447 440
448----------------------------------------------------------------------------- 441-----------------------------------------------------------------------------
@@ -482,7 +475,7 @@ function Private.redirect(request, response)
482 body_cb = request.body_cb, 475 body_cb = request.body_cb,
483 headers = request.headers 476 headers = request.headers
484 } 477 }
485 local response = %Public.request_cb(redirect, response) 478 local response = Public.request_cb(redirect, response)
486 -- we pass the location header as a clue we tried to redirect 479 -- we pass the location header as a clue we tried to redirect
487 if response.headers then response.headers.location = redirect.url end 480 if response.headers then response.headers.location = redirect.url end
488 return response 481 return response
@@ -544,7 +537,7 @@ end
544function Public.request_cb(request, response) 537function Public.request_cb(request, response)
545 local parsed = URL.parse_url(request.url, { 538 local parsed = URL.parse_url(request.url, {
546 host = "", 539 host = "",
547 port = %Public.PORT, 540 port = Public.PORT,
548 path ="/", 541 path ="/",
549 scheme = "http" 542 scheme = "http"
550 }) 543 })
@@ -558,35 +551,43 @@ function Public.request_cb(request, response)
558 -- default method 551 -- default method
559 request.method = request.method or "GET" 552 request.method = request.method or "GET"
560 -- fill default headers 553 -- fill default headers
561 request.headers = %Private.fill_headers(request.headers, parsed) 554 request.headers = Private.fill_headers(request.headers, parsed)
562 -- try to connect to server 555 -- try to connect to server
563 local sock 556 local sock
564 sock, response.error = connect(parsed.host, parsed.port) 557 sock, response.error = connect(parsed.host, parsed.port)
565 if not sock then return response end 558 if not sock then return response end
566 -- set connection timeout so that we do not hang forever 559 -- set connection timeout so that we do not hang forever
567 sock:timeout(%Public.TIMEOUT) 560 sock:timeout(Public.TIMEOUT)
568 -- send request message 561 -- send request message
569 response.error = %Private.send_request(sock, request.method, 562 response.error = Private.send_request(sock, request.method,
570 %Private.request_uri(parsed), request.headers, request.body_cb) 563 Private.request_uri(parsed), request.headers, request.body_cb)
571 if response.error then return response end 564 if response.error then return response end
572 -- get server response message 565 -- get server response message
573 response.code, response.status, response.error = 566 response.code, response.status, response.error =
574 %Private.receive_status(sock) 567 Private.receive_status(sock)
575 if response.error then return response end 568 if response.error then return response end
569 -- deal with 1xx status
570 if response.code == 100 then
571 response.headers, response.error = Private.receive_headers(sock, {})
572 if response.error then return response end
573 response.code, response.status, response.error =
574 Private.receive_status(sock)
575 if response.error then return response end
576 end
576 -- receive all headers 577 -- receive all headers
577 response.headers, response.error = %Private.receive_headers(sock, {}) 578 response.headers, response.error = Private.receive_headers(sock, {})
578 if response.error then return response end 579 if response.error then return response end
579 -- decide what to do based on request and response parameters 580 -- decide what to do based on request and response parameters
580 if %Private.should_redirect(request, response) then 581 if Private.should_redirect(request, response) then
581 %Private.drop_body(sock, response.headers) 582 Private.drop_body(sock, response.headers)
582 sock:close() 583 sock:close()
583 return %Private.redirect(request, response) 584 return Private.redirect(request, response)
584 elseif %Private.should_authorize(request, parsed, response) then 585 elseif Private.should_authorize(request, parsed, response) then
585 %Private.drop_body(sock, response.headers) 586 Private.drop_body(sock, response.headers)
586 sock:close() 587 sock:close()
587 return %Private.authorize(request, parsed, response) 588 return Private.authorize(request, parsed, response)
588 elseif %Private.has_body(request, response) then 589 elseif Private.has_body(request, response) then
589 response.error = %Private.receive_body(sock, response.headers, 590 response.error = Private.receive_body(sock, response.headers,
590 response.body_cb) 591 response.body_cb)
591 if response.error then return response end 592 if response.error then return response end
592 sock:close() 593 sock:close()
@@ -618,15 +619,15 @@ function Public.request(request)
618 local response = {} 619 local response = {}
619 if request.body then 620 if request.body then
620 request.body_cb = function() 621 request.body_cb = function()
621 return %request.body, strlen(%request.body) 622 return request.body, strlen(request.body)
622 end 623 end
623 end 624 end
624 local cat = Concat.create() 625 local cat = Concat.create()
625 response.body_cb = function(chunk, err) 626 response.body_cb = function(chunk, err)
626 if chunk then %cat:addstring(chunk) end 627 if chunk then cat:addstring(chunk) end
627 return 1 628 return 1
628 end 629 end
629 response = %Public.request_cb(request, response) 630 response = Public.request_cb(request, response)
630 response.body = cat:getresult() 631 response.body = cat:getresult()
631 response.body_cb = nil 632 response.body_cb = nil
632 return response 633 return response
@@ -646,9 +647,9 @@ end
646-- error: error message if any 647-- error: error message if any
647----------------------------------------------------------------------------- 648-----------------------------------------------------------------------------
648function Public.get(url_or_request) 649function Public.get(url_or_request)
649 local request = %Private.build_request(url_or_request) 650 local request = Private.build_request(url_or_request)
650 request.method = "GET" 651 request.method = "GET"
651 local response = %Public.request(request) 652 local response = Public.request(request)
652 return response.body, response.headers, 653 return response.body, response.headers,
653 response.code, response.error 654 response.code, response.error
654end 655end
@@ -669,10 +670,10 @@ end
669-- error: error message, or nil if successfull 670-- error: error message, or nil if successfull
670----------------------------------------------------------------------------- 671-----------------------------------------------------------------------------
671function Public.post(url_or_request, body) 672function Public.post(url_or_request, body)
672 local request = %Private.build_request(url_or_request) 673 local request = Private.build_request(url_or_request)
673 request.method = "POST" 674 request.method = "POST"
674 request.body = request.body or body 675 request.body = request.body or body
675 local response = %Public.request(request) 676 local response = Public.request(request)
676 return response.body, response.headers, 677 return response.body, response.headers,
677 response.code, response.error 678 response.code, response.error
678end 679end