aboutsummaryrefslogtreecommitdiff
path: root/src/http.lua
diff options
context:
space:
mode:
Diffstat (limited to 'src/http.lua')
-rw-r--r--src/http.lua28
1 files changed, 23 insertions, 5 deletions
diff --git a/src/http.lua b/src/http.lua
index 9d739a4..3a386a6 100644
--- a/src/http.lua
+++ b/src/http.lua
@@ -142,7 +142,12 @@ function metat.__index:sendbody(headers, source, step)
142end 142end
143 143
144function metat.__index:receivestatusline() 144function metat.__index:receivestatusline()
145 local status = self.try(self.c:receive()) 145 local status = self.try(self.c:receive(5))
146 -- identify HTTP/0.9 responses, which do not contain a status line
147 -- this is just a heuristic, but is what the RFC recommends
148 if status ~= "HTTP/" then return nil, status end
149 -- otherwise proceed reading a status line
150 status = self.try(self.c:receive("*l", status))
146 local code = socket.skip(2, string.find(status, "HTTP/%d*%.%d* (%d%d%d)")) 151 local code = socket.skip(2, string.find(status, "HTTP/%d*%.%d* (%d%d%d)"))
147 return self.try(base.tonumber(code), status) 152 return self.try(base.tonumber(code), status)
148end 153end
@@ -163,6 +168,12 @@ function metat.__index:receivebody(headers, sink, step)
163 sink, step)) 168 sink, step))
164end 169end
165 170
171function metat.__index:receive09body(status, sink, step)
172 local source = ltn12.source.rewind(socket.source("until-closed", self.c))
173 source(status)
174 return self.try(ltn12.pump.all(source, sink, step))
175end
176
166function metat.__index:close() 177function metat.__index:close()
167 return self.c:close() 178 return self.c:close()
168end 179end
@@ -271,6 +282,7 @@ function tredirect(reqt, location)
271 create = reqt.create 282 create = reqt.create
272 } 283 }
273 -- pass location header back as a hint we redirected 284 -- pass location header back as a hint we redirected
285 headers = headers or {}
274 headers.location = headers.location or location 286 headers.location = headers.location or location
275 return result, code, headers, status 287 return result, code, headers, status
276end 288end
@@ -283,17 +295,23 @@ function trequest(reqt)
283 -- send request line and headers 295 -- send request line and headers
284 h:sendrequestline(nreqt.method, nreqt.uri) 296 h:sendrequestline(nreqt.method, nreqt.uri)
285 h:sendheaders(nreqt.headers) 297 h:sendheaders(nreqt.headers)
286 local code = 100 298 -- if there is a body, send it
287 local headers, status
288 -- if there is a body, check for server status
289 if nreqt.source then 299 if nreqt.source then
290 h:sendbody(nreqt.headers, nreqt.source, nreqt.step) 300 h:sendbody(nreqt.headers, nreqt.source, nreqt.step)
291 end 301 end
302 local code, status = h:receivestatusline()
303 -- if it is an HTTP/0.9 server, simply get the body and we are done
304 if not code then
305 h:receive09body(status, nreqt.sink, nreqt.step)
306 return 1, 200
307 end
308 local headers
292 -- ignore any 100-continue messages 309 -- ignore any 100-continue messages
293 while code == 100 do 310 while code == 100 do
294 code, status = h:receivestatusline()
295 headers = h:receiveheaders() 311 headers = h:receiveheaders()
312 code, status = h:receivestatusline()
296 end 313 end
314 headers = h:receiveheaders()
297 -- at this point we should have a honest reply from the server 315 -- at this point we should have a honest reply from the server
298 -- we can't redirect if we already used the source, so we report the error 316 -- we can't redirect if we already used the source, so we report the error
299 if shouldredirect(nreqt, code, headers) and not nreqt.source then 317 if shouldredirect(nreqt, code, headers) and not nreqt.source then