aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorDiego Nehab <diego@tecgraf.puc-rio.br>2004-06-16 21:56:23 +0000
committerDiego Nehab <diego@tecgraf.puc-rio.br>2004-06-16 21:56:23 +0000
commit574708380f19b15bd19419bfd64ccbe422f2d924 (patch)
treedeb5030132ca370193d1d64bd57fbcce4c7ce8eb /src
parentba2f0b8c6ba7fb3a26fa6d9676ee1aefe6d873cc (diff)
downloadluasocket-574708380f19b15bd19419bfd64ccbe422f2d924.tar.gz
luasocket-574708380f19b15bd19419bfd64ccbe422f2d924.tar.bz2
luasocket-574708380f19b15bd19419bfd64ccbe422f2d924.zip
Simplified HTTP module.
Diffstat (limited to 'src')
-rw-r--r--src/http.lua138
-rw-r--r--src/url.lua2
2 files changed, 67 insertions, 73 deletions
diff --git a/src/http.lua b/src/http.lua
index 8f3fdb9..e0c4c27 100644
--- a/src/http.lua
+++ b/src/http.lua
@@ -143,117 +143,111 @@ local function adjustheaders(headers, host)
143 return lower 143 return lower
144end 144end
145 145
146local default = {
147 host = "",
148 port = PORT,
149 path ="/",
150 scheme = "http"
151}
152
146local function adjustrequest(reqt) 153local function adjustrequest(reqt)
147 -- parse url with default fields 154 -- parse url if provided
148 local parsed = url.parse(reqt.url or "", { 155 if reqt.url then
149 host = "", 156 local parsed = url.parse(reqt.url, default)
150 port = PORT, 157 -- explicit components override url
151 path ="/", 158 for i,v in parsed do reqt[i] = reqt[i] or v end
152 scheme = "http" 159 end
153 }) 160 socket.try(reqt.host, "invalid host '" .. tostring(reqt.host) .. "'")
154 -- explicit info in reqt overrides that given by the URL 161 socket.try(reqt.path, "invalid path '" .. tostring(reqt.path) .. "'")
155 for i,v in reqt do parsed[i] = v end
156 -- compute uri if user hasn't overriden 162 -- compute uri if user hasn't overriden
157 parsed.uri = parsed.uri or uri(parsed) 163 reqt.uri = reqt.uri or uri(reqt)
158 -- adjust headers in request 164 -- adjust headers in request
159 parsed.headers = adjustheaders(parsed.headers, parsed.host) 165 reqt.headers = adjustheaders(reqt.headers, reqt.host)
160 return parsed 166 return reqt
161end 167end
162 168
163local function shouldredirect(reqt, respt) 169local function shouldredirect(reqt, code)
164 return (reqt.redirect ~= false) and 170 return (reqt.redirect ~= false) and
165 (respt.code == 301 or respt.code == 302) and 171 (code == 301 or code == 302) and
166 (not reqt.method or reqt.method == "GET" or reqt.method == "HEAD") 172 (not reqt.method or reqt.method == "GET" or reqt.method == "HEAD")
167 and (not reqt.nredirects or reqt.nredirects < 5) 173 and (not reqt.nredirects or reqt.nredirects < 5)
168end 174end
169 175
170local function shouldauthorize(reqt, respt) 176local function shouldauthorize(reqt, code)
171 -- if there has been an authorization attempt, it must have failed 177 -- if there has been an authorization attempt, it must have failed
172 if reqt.headers and reqt.headers["authorization"] then return nil end 178 if reqt.headers and reqt.headers["authorization"] then return nil end
173 -- if last attempt didn't fail due to lack of authentication, 179 -- if last attempt didn't fail due to lack of authentication,
174 -- or we don't have authorization information, we can't retry 180 -- or we don't have authorization information, we can't retry
175 return respt.code == 401 and reqt.user and reqt.password 181 return code == 401 and reqt.user and reqt.password
176end 182end
177 183
178local function shouldreceivebody(reqt, respt) 184local function shouldreceivebody(reqt, code)
179 if reqt.method == "HEAD" then return nil end 185 if reqt.method == "HEAD" then return nil end
180 local code = respt.code
181 if code == 204 or code == 304 then return nil end 186 if code == 204 or code == 304 then return nil end
182 if code >= 100 and code < 200 then return nil end 187 if code >= 100 and code < 200 then return nil end
183 return 1 188 return 1
184end 189end
185 190
186local requestp, authorizep, redirectp 191-- forward declarations
187 192local trequest, tauthorize, tredirect
188function requestp(reqt)
189 local reqt = adjustrequest(reqt)
190 local respt = {}
191 local con = open(reqt.host, reqt.port)
192 con:sendrequestline(reqt.method, reqt.uri)
193 con:sendheaders(reqt.headers)
194 con:sendbody(reqt.headers, reqt.source, reqt.step)
195 respt.code, respt.status = con:receivestatusline()
196 respt.headers = con:receiveheaders()
197 if shouldredirect(reqt, respt) then
198 con:close()
199 return redirectp(reqt, respt)
200 elseif shouldauthorize(reqt, respt) then
201 con:close()
202 return authorizep(reqt, respt)
203 elseif shouldreceivebody(reqt, respt) then
204 con:receivebody(respt.headers, reqt.sink, reqt.step)
205 end
206 con:close()
207 return respt
208end
209 193
210function authorizep(reqt, respt) 194function tauthorize(reqt)
211 local auth = "Basic " .. (mime.b64(reqt.user .. ":" .. reqt.password)) 195 local auth = "Basic " .. (mime.b64(reqt.user .. ":" .. reqt.password))
212 reqt.headers["authorization"] = auth 196 reqt.headers["authorization"] = auth
213 return requestp(reqt) 197 return trequest(reqt)
214end 198end
215 199
216function redirectp(reqt, respt) 200function tredirect(reqt, headers)
217 -- we create a new table to get rid of anything we don't 201 -- the RFC says the redirect URL has to be absolute, but some
218 -- absolutely need, including authentication info 202 -- servers do not respect that
219 local redirt = { 203 return trequest {
220 method = reqt.method, 204 url = url.absolute(reqt, headers["location"]),
221 -- the RFC says the redirect URL has to be absolute, but some
222 -- servers do not respect that
223 url = url.absolute(reqt.url, respt.headers["location"]),
224 source = reqt.source, 205 source = reqt.source,
225 sink = reqt.sink, 206 sink = reqt.sink,
226 headers = reqt.headers, 207 headers = reqt.headers,
227 proxy = reqt.proxy, 208 proxy = reqt.proxy,
228 nredirects = (reqt.nredirects or 0) + 1 209 nredirects = (reqt.nredirects or 0) + 1
229 } 210 }
230 respt = requestp(redirt)
231 -- we pass the location header as a clue we redirected
232 if respt.headers then respt.headers.location = redirt.url end
233 return respt
234end 211end
235 212
236request = socket.protect(requestp) 213function trequest(reqt)
214 reqt = adjustrequest(reqt)
215 local con = open(reqt.host, reqt.port)
216 con:sendrequestline(reqt.method, reqt.uri)
217 con:sendheaders(reqt.headers)
218 con:sendbody(reqt.headers, reqt.source, reqt.step)
219 local code, headers, status
220 code, status = con:receivestatusline()
221 headers = con:receiveheaders()
222 if shouldredirect(reqt, code) then
223 con:close()
224 return tredirect(reqt, headers)
225 elseif shouldauthorize(reqt, code) then
226 con:close()
227 return tauthorize(reqt)
228 elseif shouldreceivebody(reqt, code) then
229 con:receivebody(headers, reqt.sink, reqt.step)
230 end
231 con:close()
232 return 1, code, headers, status
233end
237 234
238get = socket.protect(function(u) 235local function srequest(u, body)
239 local t = {} 236 local t = {}
240 local respt = requestp { 237 local reqt = {
241 url = u, 238 url = u,
242 sink = ltn12.sink.table(t) 239 sink = ltn12.sink.table(t)
243 } 240 }
244 return (table.getn(t) > 0 or nil) and table.concat(t), respt.headers, 241 if body then
245 respt.code 242 reqt.source = ltn12.source.string(body)
246end) 243 reqt.headers = { ["content-length"] = string.len(body) }
244 reqt.method = "POST"
245 end
246 local code, headers, status = socket.skip(1, trequest(reqt))
247 return table.concat(t), code, headers, status
248end
247 249
248post = socket.protect(function(u, body) 250request = socket.protect(function(reqt, body)
249 local t = {} 251 if type(reqt) == "string" then return srequest(reqt, body)
250 local respt = requestp { 252 else return trequest(reqt) end
251 url = u,
252 method = "POST",
253 source = ltn12.source.string(body),
254 sink = ltn12.sink.table(t),
255 headers = { ["content-length"] = string.len(body) }
256 }
257 return (table.getn(t) > 0 or nil) and table.concat(t),
258 respt.headers, respt.code
259end) 253end)
diff --git a/src/url.lua b/src/url.lua
index 960a248..ec26e62 100644
--- a/src/url.lua
+++ b/src/url.lua
@@ -190,7 +190,7 @@ end
190-- corresponding absolute url 190-- corresponding absolute url
191----------------------------------------------------------------------------- 191-----------------------------------------------------------------------------
192function absolute(base_url, relative_url) 192function absolute(base_url, relative_url)
193 local base = parse(base_url) 193 local base = type(base_url) == "table" and base_url or parse(base_url)
194 local relative = parse(relative_url) 194 local relative = parse(relative_url)
195 if not base then return relative_url 195 if not base then return relative_url
196 elseif not relative then return base_url 196 elseif not relative then return base_url