diff options
| -rw-r--r-- | src/http.lua | 109 |
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 |
| 19 | Public.PORT = 80 | 19 | Public.PORT = 80 |
| 20 | -- user agent field sent in request | 20 | -- user agent field sent in request |
| 21 | Public.USERAGENT = "LuaSocket 1.4" | 21 | Public.USERAGENT = "LuaSocket 1.5" |
| 22 | -- block size used in transfers | 22 | -- block size used in transfers |
| 23 | Public.BLOCKSIZE = 8192 | 23 | Public.BLOCKSIZE = 8192 |
| 24 | 24 | ||
| 25 | ----------------------------------------------------------------------------- | 25 | ----------------------------------------------------------------------------- |
| 26 | -- Required libraries | ||
| 27 | ----------------------------------------------------------------------------- | ||
| 28 | dofile "concat.lua" | ||
| 29 | dofile "url.lua" | ||
| 30 | dofile "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 | ----------------------------------------------------------------------------- |
| 85 | function Private.receive_status(sock) | 78 | function 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 |
| 90 | end | 83 | end |
| 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 | |||
| 202 | function Private.receivebody_bylength(sock, length, receive_cb) | 195 | function 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 | |||
| 230 | function Private.receivebody_untilclosed(sock, receive_cb) | 223 | function 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 |
| 272 | end | 265 | end |
| 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 | ----------------------------------------------------------------------------- |
| 282 | function Private.drop_body(sock, headers) | 275 | function 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) |
| 284 | end | 277 | end |
| 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") |
| 333 | end | 326 | end |
| 334 | 327 | ||
| 335 | ----------------------------------------------------------------------------- | 328 | ----------------------------------------------------------------------------- |
| @@ -346,7 +339,7 @@ end | |||
| 346 | function Private.send_request(sock, method, uri, headers, body_cb) | 339 | function 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 |
| 369 | end | 362 | end |
| 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) |
| 446 | end | 439 | end |
| 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 | |||
| 544 | function Public.request_cb(request, response) | 537 | function 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 | ----------------------------------------------------------------------------- |
| 648 | function Public.get(url_or_request) | 649 | function 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 |
| 654 | end | 655 | end |
| @@ -669,10 +670,10 @@ end | |||
| 669 | -- error: error message, or nil if successfull | 670 | -- error: error message, or nil if successfull |
| 670 | ----------------------------------------------------------------------------- | 671 | ----------------------------------------------------------------------------- |
| 671 | function Public.post(url_or_request, body) | 672 | function 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 |
| 678 | end | 679 | end |
