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 | ||