diff options
| author | Diego Nehab <diego@tecgraf.puc-rio.br> | 2004-06-18 08:02:09 +0000 |
|---|---|---|
| committer | Diego Nehab <diego@tecgraf.puc-rio.br> | 2004-06-18 08:02:09 +0000 |
| commit | ac4aac0909da26befaaeb6b415f66cf35b6980e0 (patch) | |
| tree | 3d3289e6192508484dcbefa10e2d862c5cc06d64 /src/http.lua | |
| parent | 62799a416d2b29d8058331f3d8725fb67c75d261 (diff) | |
| download | luasocket-ac4aac0909da26befaaeb6b415f66cf35b6980e0.tar.gz luasocket-ac4aac0909da26befaaeb6b415f66cf35b6980e0.tar.bz2 luasocket-ac4aac0909da26befaaeb6b415f66cf35b6980e0.zip | |
Implemented safe exceptions. This looks preeety good.
Diffstat (limited to 'src/http.lua')
| -rw-r--r-- | src/http.lua | 55 |
1 files changed, 28 insertions, 27 deletions
diff --git a/src/http.lua b/src/http.lua index 3bd4d6a..d8889e1 100644 --- a/src/http.lua +++ b/src/http.lua | |||
| @@ -31,24 +31,25 @@ BLOCKSIZE = 2048 | |||
| 31 | local metat = { __index = {} } | 31 | local metat = { __index = {} } |
| 32 | 32 | ||
| 33 | function open(host, port) | 33 | function open(host, port) |
| 34 | local con = socket.try(socket.tcp()) | 34 | local c = socket.try(socket.tcp()) |
| 35 | socket.try(con:settimeout(TIMEOUT)) | 35 | -- make sure the connection gets closed on exception |
| 36 | port = port or PORT | 36 | local try = socket.newtry(function() c:close() end) |
| 37 | socket.try(con:connect(host, port)) | 37 | try(c:settimeout(TIMEOUT)) |
| 38 | return setmetatable({ con = con }, metat) | 38 | try(c:connect(host, port or PORT)) |
| 39 | return setmetatable({ c = c, try = try }, metat) | ||
| 39 | end | 40 | end |
| 40 | 41 | ||
| 41 | function metat.__index:sendrequestline(method, uri) | 42 | function metat.__index:sendrequestline(method, uri) |
| 42 | local reqline = string.format("%s %s HTTP/1.1\r\n", method or "GET", uri) | 43 | local reqline = string.format("%s %s HTTP/1.1\r\n", method or "GET", uri) |
| 43 | return socket.try(self.con:send(reqline)) | 44 | return self.try(self.c:send(reqline)) |
| 44 | end | 45 | end |
| 45 | 46 | ||
| 46 | function metat.__index:sendheaders(headers) | 47 | function metat.__index:sendheaders(headers) |
| 47 | for i, v in pairs(headers) do | 48 | for i, v in pairs(headers) do |
| 48 | socket.try(self.con:send(i .. ": " .. v .. "\r\n")) | 49 | self.try(self.c:send(i .. ": " .. v .. "\r\n")) |
| 49 | end | 50 | end |
| 50 | -- mark end of request headers | 51 | -- mark end of request headers |
| 51 | socket.try(self.con:send("\r\n")) | 52 | self.try(self.c:send("\r\n")) |
| 52 | return 1 | 53 | return 1 |
| 53 | end | 54 | end |
| 54 | 55 | ||
| @@ -59,32 +60,32 @@ function metat.__index:sendbody(headers, source, step) | |||
| 59 | local mode | 60 | local mode |
| 60 | if headers["content-length"] then mode = "keep-open" | 61 | if headers["content-length"] then mode = "keep-open" |
| 61 | else mode = "http-chunked" end | 62 | else mode = "http-chunked" end |
| 62 | return socket.try(ltn12.pump.all(source, socket.sink(mode, self.con), step)) | 63 | return self.try(ltn12.pump.all(source, socket.sink(mode, self.c), step)) |
| 63 | end | 64 | end |
| 64 | 65 | ||
| 65 | function metat.__index:receivestatusline() | 66 | function metat.__index:receivestatusline() |
| 66 | local status = socket.try(self.con:receive()) | 67 | local status = self.try(self.c:receive()) |
| 67 | local code = socket.skip(2, string.find(status, "HTTP/%d*%.%d* (%d%d%d)")) | 68 | local code = socket.skip(2, string.find(status, "HTTP/%d*%.%d* (%d%d%d)")) |
| 68 | return socket.try(tonumber(code), status) | 69 | return self.try(tonumber(code), status) |
| 69 | end | 70 | end |
| 70 | 71 | ||
| 71 | function metat.__index:receiveheaders() | 72 | function metat.__index:receiveheaders() |
| 72 | local line, name, value | 73 | local line, name, value |
| 73 | local headers = {} | 74 | local headers = {} |
| 74 | -- get first line | 75 | -- get first line |
| 75 | line = socket.try(self.con:receive()) | 76 | line = self.try(self.c:receive()) |
| 76 | -- headers go until a blank line is found | 77 | -- headers go until a blank line is found |
| 77 | while line ~= "" do | 78 | while line ~= "" do |
| 78 | -- get field-name and value | 79 | -- get field-name and value |
| 79 | name, value = socket.skip(2, string.find(line, "^(.-):%s*(.*)")) | 80 | name, value = socket.skip(2, string.find(line, "^(.-):%s*(.*)")) |
| 80 | socket.try(name and value, "malformed reponse headers") | 81 | self.try(name and value, "malformed reponse headers") |
| 81 | name = string.lower(name) | 82 | name = string.lower(name) |
| 82 | -- get next line (value might be folded) | 83 | -- get next line (value might be folded) |
| 83 | line = socket.try(self.con:receive()) | 84 | line = self.try(self.c:receive()) |
| 84 | -- unfold any folded values | 85 | -- unfold any folded values |
| 85 | while string.find(line, "^%s") do | 86 | while string.find(line, "^%s") do |
| 86 | value = value .. line | 87 | value = value .. line |
| 87 | line = socket.try(self.con:receive()) | 88 | line = self.try(self.c:receive()) |
| 88 | end | 89 | end |
| 89 | -- save pair in table | 90 | -- save pair in table |
| 90 | if headers[name] then headers[name] = headers[name] .. ", " .. value | 91 | if headers[name] then headers[name] = headers[name] .. ", " .. value |
| @@ -102,12 +103,12 @@ function metat.__index:receivebody(headers, sink, step) | |||
| 102 | if TE and TE ~= "identity" then mode = "http-chunked" | 103 | if TE and TE ~= "identity" then mode = "http-chunked" |
| 103 | elseif tonumber(headers["content-length"]) then mode = "by-length" | 104 | elseif tonumber(headers["content-length"]) then mode = "by-length" |
| 104 | else mode = "default" end | 105 | else mode = "default" end |
| 105 | return socket.try(ltn12.pump.all(socket.source(mode, self.con, length), | 106 | return self.try(ltn12.pump.all(socket.source(mode, self.c, length), |
| 106 | sink, step)) | 107 | sink, step)) |
| 107 | end | 108 | end |
| 108 | 109 | ||
| 109 | function metat.__index:close() | 110 | function metat.__index:close() |
| 110 | return self.con:close() | 111 | return self.c:close() |
| 111 | end | 112 | end |
| 112 | 113 | ||
| 113 | ----------------------------------------------------------------------------- | 114 | ----------------------------------------------------------------------------- |
| @@ -204,23 +205,23 @@ end | |||
| 204 | 205 | ||
| 205 | function trequest(reqt) | 206 | function trequest(reqt) |
| 206 | reqt = adjustrequest(reqt) | 207 | reqt = adjustrequest(reqt) |
| 207 | local con = open(reqt.host, reqt.port) | 208 | local h = open(reqt.host, reqt.port) |
| 208 | con:sendrequestline(reqt.method, reqt.uri) | 209 | h:sendrequestline(reqt.method, reqt.uri) |
| 209 | con:sendheaders(reqt.headers) | 210 | h:sendheaders(reqt.headers) |
| 210 | con:sendbody(reqt.headers, reqt.source, reqt.step) | 211 | h:sendbody(reqt.headers, reqt.source, reqt.step) |
| 211 | local code, headers, status | 212 | local code, headers, status |
| 212 | code, status = con:receivestatusline() | 213 | code, status = h:receivestatusline() |
| 213 | headers = con:receiveheaders() | 214 | headers = h:receiveheaders() |
| 214 | if shouldredirect(reqt, code) then | 215 | if shouldredirect(reqt, code) then |
| 215 | con:close() | 216 | h:close() |
| 216 | return tredirect(reqt, headers) | 217 | return tredirect(reqt, headers) |
| 217 | elseif shouldauthorize(reqt, code) then | 218 | elseif shouldauthorize(reqt, code) then |
| 218 | con:close() | 219 | h:close() |
| 219 | return tauthorize(reqt) | 220 | return tauthorize(reqt) |
| 220 | elseif shouldreceivebody(reqt, code) then | 221 | elseif shouldreceivebody(reqt, code) then |
| 221 | con:receivebody(headers, reqt.sink, reqt.step) | 222 | h:receivebody(headers, reqt.sink, reqt.step) |
| 222 | end | 223 | end |
| 223 | con:close() | 224 | h:close() |
| 224 | return 1, code, headers, status | 225 | return 1, code, headers, status |
| 225 | end | 226 | end |
| 226 | 227 | ||
