aboutsummaryrefslogtreecommitdiff
path: root/src/http.lua
diff options
context:
space:
mode:
authorDiego Nehab <diego@tecgraf.puc-rio.br>2004-06-18 08:02:09 +0000
committerDiego Nehab <diego@tecgraf.puc-rio.br>2004-06-18 08:02:09 +0000
commitac4aac0909da26befaaeb6b415f66cf35b6980e0 (patch)
tree3d3289e6192508484dcbefa10e2d862c5cc06d64 /src/http.lua
parent62799a416d2b29d8058331f3d8725fb67c75d261 (diff)
downloadluasocket-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.lua55
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
31local metat = { __index = {} } 31local metat = { __index = {} }
32 32
33function open(host, port) 33function 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)
39end 40end
40 41
41function metat.__index:sendrequestline(method, uri) 42function 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))
44end 45end
45 46
46function metat.__index:sendheaders(headers) 47function 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
53end 54end
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))
63end 64end
64 65
65function metat.__index:receivestatusline() 66function 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)
69end 70end
70 71
71function metat.__index:receiveheaders() 72function 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))
107end 108end
108 109
109function metat.__index:close() 110function metat.__index:close()
110 return self.con:close() 111 return self.c:close()
111end 112end
112 113
113----------------------------------------------------------------------------- 114-----------------------------------------------------------------------------
@@ -204,23 +205,23 @@ end
204 205
205function trequest(reqt) 206function 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
225end 226end
226 227