diff options
Diffstat (limited to 'src/http.lua')
-rw-r--r-- | src/http.lua | 69 |
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") | |||
15 | local string = require("string") | 15 | local string = require("string") |
16 | local base = _G | 16 | local base = _G |
17 | local table = require("table") | 17 | local table = require("table") |
18 | local print = print | ||
18 | module("socket.http") | 19 | module("socket.http") |
19 | 20 | ||
20 | ----------------------------------------------------------------------------- | 21 | ----------------------------------------------------------------------------- |
@@ -194,16 +195,19 @@ local function adjustproxy(reqt) | |||
194 | end | 195 | end |
195 | end | 196 | end |
196 | 197 | ||
197 | local function adjustheaders(headers, host) | 198 | local 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 |
234 | end | 238 | end |
235 | 239 | ||
@@ -257,6 +261,7 @@ local function shouldreceivebody(reqt, code) | |||
257 | return 1 | 261 | return 1 |
258 | end | 262 | end |
259 | 263 | ||
264 | |||
260 | -- forward declarations | 265 | -- forward declarations |
261 | local trequest, tauthorize, tredirect | 266 | local 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 |
284 | end | 289 | end |
285 | 290 | ||
286 | function trequest(reqt) | 291 | function 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 | ||
306 | end | 336 | end |
307 | 337 | ||
308 | local function srequest(u, body) | 338 | local 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)) |