aboutsummaryrefslogtreecommitdiff
path: root/src/http.lua
diff options
context:
space:
mode:
Diffstat (limited to 'src/http.lua')
-rw-r--r--src/http.lua69
1 files changed, 51 insertions, 18 deletions
diff --git a/src/http.lua b/src/http.lua
index 1834061..91600e7 100644
--- a/src/http.lua
+++ b/src/http.lua
@@ -15,6 +15,7 @@ local mime = require("mime")
15local string = require("string") 15local string = require("string")
16local base = _G 16local base = _G
17local table = require("table") 17local table = require("table")
18local print = print
18module("socket.http") 19module("socket.http")
19 20
20----------------------------------------------------------------------------- 21-----------------------------------------------------------------------------
@@ -194,16 +195,19 @@ local function adjustproxy(reqt)
194 end 195 end
195end 196end
196 197
197local function adjustheaders(headers, host) 198local function adjustheaders(reqt)
198 -- default headers 199 -- default headers
199 local lower = { 200 local lower = {
200 ["user-agent"] = USERAGENT, 201 ["user-agent"] = USERAGENT,
201 ["host"] = host, 202 ["host"] = reqt.host,
202 ["connection"] = "close, TE", 203 ["connection"] = "close, TE",
203 ["te"] = "trailers" 204 ["te"] = "trailers"
204 } 205 }
206 -- if we are sending a body, tell server to let us know
207 -- if it this is a waste of time
208 if reqt.source then lower["expect"] = "100-continue" end
205 -- override with user headers 209 -- override with user headers
206 for i,v in base.pairs(headers or lower) do 210 for i,v in base.pairs(reqt.headers or lower) do
207 lower[string.lower(i)] = v 211 lower[string.lower(i)] = v
208 end 212 end
209 return lower 213 return lower
@@ -229,7 +233,7 @@ local function adjustrequest(reqt)
229 -- ajust host and port if there is a proxy 233 -- ajust host and port if there is a proxy
230 nreqt.host, nreqt.port = adjustproxy(nreqt) 234 nreqt.host, nreqt.port = adjustproxy(nreqt)
231 -- adjust headers in request 235 -- adjust headers in request
232 nreqt.headers = adjustheaders(nreqt.headers, nreqt.host) 236 nreqt.headers = adjustheaders(nreqt)
233 return nreqt 237 return nreqt
234end 238end
235 239
@@ -257,6 +261,7 @@ local function shouldreceivebody(reqt, code)
257 return 1 261 return 1
258end 262end
259 263
264
260-- forward declarations 265-- forward declarations
261local trequest, tauthorize, tredirect 266local trequest, tauthorize, tredirect
262 267
@@ -274,46 +279,74 @@ function tredirect(reqt, location)
274 source = reqt.source, 279 source = reqt.source,
275 sink = reqt.sink, 280 sink = reqt.sink,
276 headers = reqt.headers, 281 headers = reqt.headers,
277 proxy = reqt.proxy, 282 proxy = reqt.proxy,
278 nredirects = (reqt.nredirects or 0) + 1, 283 nredirects = (reqt.nredirects or 0) + 1,
279 connect = reqt.connect 284 connect = reqt.connect
280 } 285 }
281 -- pass location header back as a hint we redirected 286 -- pass location header back as a hint we redirected
282 headers.location = headers.location or location 287 headers.location = headers.location or location
283 return result, code, headers, status 288 return result, code, headers, status
284end 289end
285 290
286function trequest(reqt) 291function trequest(reqt)
292 -- we loop until we get what we want, or
293 -- until we are sure there is no way to get it
287 reqt = adjustrequest(reqt) 294 reqt = adjustrequest(reqt)
288 local h = open(reqt.host, reqt.port, reqt.create) 295 local h = open(reqt.host, reqt.port, reqt.create)
296 -- send request line and headers
289 h:sendrequestline(reqt.method, reqt.uri) 297 h:sendrequestline(reqt.method, reqt.uri)
290 h:sendheaders(reqt.headers) 298 h:sendheaders(reqt.headers)
291 if reqt.source then h:sendbody(reqt.headers, reqt.source, reqt.step) end 299 local code = 100
292 local code, headers, status 300 local headers, status
293 code, status = h:receivestatusline() 301 -- if there is a body, check for server status
294 headers = h:receiveheaders() 302 if reqt.source then
303 local ready = socket.select({h.c}, nil, TIMEOUT)
304 if ready[h.c] then
305 -- here the server sent us something
306 code, status = h:receivestatusline()
307 headers = h:receiveheaders()
308 end
309 -- if server is happy, send body
310 if code == 100 then
311 h:sendbody(reqt.headers, reqt.source, reqt.step)
312 -- can't send body again!
313 reqt.source = nil
314 end
315 end
316 -- ignore all further 100-continue messages
317 while code == 100 do
318 code, status = h:receivestatusline()
319 headers = h:receiveheaders()
320 end
321 -- at this point we should have a honest reply from the server
295 if shouldredirect(reqt, code, headers) then 322 if shouldredirect(reqt, code, headers) then
296 h:close() 323 h:close()
297 return tredirect(reqt, headers.location) 324 return tredirect(reqt, headers.location)
298 elseif shouldauthorize(reqt, code) then 325 elseif shouldauthorize(reqt, code) then
299 h:close() 326 h:close()
300 return tauthorize(reqt) 327 return tauthorize(reqt)
301 elseif shouldreceivebody(reqt, code) then 328 else
302 h:receivebody(headers, reqt.sink, reqt.step) 329 -- here we are finally done
330 if shouldreceivebody(reqt, code) then
331 h:receivebody(headers, reqt.sink, reqt.step)
332 end
333 h:close()
334 return 1, code, headers, status
303 end 335 end
304 h:close()
305 return 1, code, headers, status
306end 336end
307 337
308local function srequest(u, body) 338local function srequest(u, b, h)
309 local t = {} 339 local t = {}
310 local reqt = { 340 local reqt = {
311 url = u, 341 url = u,
312 sink = ltn12.sink.table(t) 342 sink = ltn12.sink.table(t)
313 } 343 }
314 if body then 344 if b then
315 reqt.source = ltn12.source.string(body) 345 reqt.source = ltn12.source.string(b)
316 reqt.headers = { ["content-length"] = string.len(body) } 346 reqt.headers = h or {}
347 reqt.headers["content-length"] = string.len(b)
348 reqt.headers["content-type"] = reqt.headers["content-type"] or
349 "application/x-www-form-urlencoded"
317 reqt.method = "POST" 350 reqt.method = "POST"
318 end 351 end
319 local code, headers, status = socket.skip(1, trequest(reqt)) 352 local code, headers, status = socket.skip(1, trequest(reqt))