Software / code / prosody
Comparison
net/http.lua @ 3569:f30da46e0add
net.http: Removed old HTTP parser, and updated to use util.httpstream.
| author | Waqas Hussain <waqas20@gmail.com> |
|---|---|
| date | Sat, 06 Nov 2010 03:46:00 +0500 |
| parent | 3540:bc139431830b |
| child | 4338:5d5d6c6d121a |
comparison
equal
deleted
inserted
replaced
| 3568:51d5578965a5 | 3569:f30da46e0add |
|---|---|
| 8 | 8 |
| 9 | 9 |
| 10 local socket = require "socket" | 10 local socket = require "socket" |
| 11 local mime = require "mime" | 11 local mime = require "mime" |
| 12 local url = require "socket.url" | 12 local url = require "socket.url" |
| 13 local httpstream_new = require "util.httpstream".new; | |
| 13 | 14 |
| 14 local server = require "net.server" | 15 local server = require "net.server" |
| 15 | 16 |
| 16 local connlisteners_get = require "net.connlisteners".get; | 17 local connlisteners_get = require "net.connlisteners".get; |
| 17 local listener = connlisteners_get("httpclient") or error("No httpclient listener!"); | 18 local listener = connlisteners_get("httpclient") or error("No httpclient listener!"); |
| 43 t_insert(result, _formencodepart(field.name).."=".._formencodepart(field.value)); | 44 t_insert(result, _formencodepart(field.name).."=".._formencodepart(field.value)); |
| 44 end | 45 end |
| 45 return t_concat(result, "&"); | 46 return t_concat(result, "&"); |
| 46 end | 47 end |
| 47 | 48 |
| 48 local function expectbody(reqt, code) | |
| 49 if reqt.method == "HEAD" then return nil end | |
| 50 if code == 204 or code == 304 or code == 301 then return nil end | |
| 51 if code >= 100 and code < 200 then return nil end | |
| 52 return 1 | |
| 53 end | |
| 54 | |
| 55 local function request_reader(request, data, startpos) | 49 local function request_reader(request, data, startpos) |
| 56 if not data then | 50 if not request.parser then |
| 57 if request.body then | 51 local function success_cb(r) |
| 58 log("debug", "Connection closed, but we have data, calling callback..."); | |
| 59 request.callback(t_concat(request.body), request.code, request); | |
| 60 elseif request.state ~= "completed" then | |
| 61 -- Error.. connection was closed prematurely | |
| 62 request.callback("connection-closed", 0, request); | |
| 63 return; | |
| 64 end | |
| 65 destroy_request(request); | |
| 66 request.body = nil; | |
| 67 request.state = "completed"; | |
| 68 return; | |
| 69 end | |
| 70 if request.state == "body" and request.state ~= "completed" then | |
| 71 log("debug", "Reading body...") | |
| 72 if not request.body then request.body = {}; request.havebodylength, request.bodylength = 0, tonumber(request.responseheaders["content-length"]); end | |
| 73 if startpos then | |
| 74 data = data:sub(startpos, -1) | |
| 75 end | |
| 76 t_insert(request.body, data); | |
| 77 if request.bodylength then | |
| 78 request.havebodylength = request.havebodylength + #data; | |
| 79 if request.havebodylength >= request.bodylength then | |
| 80 -- We have the body | |
| 81 log("debug", "Have full body, calling callback"); | |
| 82 if request.callback then | |
| 83 request.callback(t_concat(request.body), request.code, request); | |
| 84 end | |
| 85 request.body = nil; | |
| 86 request.state = "completed"; | |
| 87 else | |
| 88 log("debug", "Have "..request.havebodylength.." bytes out of "..request.bodylength); | |
| 89 end | |
| 90 end | |
| 91 elseif request.state == "headers" then | |
| 92 log("debug", "Reading headers...") | |
| 93 local pos = startpos; | |
| 94 local headers, headers_complete = request.responseheaders; | |
| 95 if not headers then | |
| 96 headers = {}; | |
| 97 request.responseheaders = headers; | |
| 98 end | |
| 99 for line in data:sub(startpos, -1):gmatch("(.-)\r\n") do | |
| 100 startpos = startpos + #line + 2; | |
| 101 local k, v = line:match("(%S+): (.+)"); | |
| 102 if k and v then | |
| 103 headers[k:lower()] = v; | |
| 104 --log("debug", "Header: "..k:lower().." = "..v); | |
| 105 elseif #line == 0 then | |
| 106 headers_complete = true; | |
| 107 break; | |
| 108 else | |
| 109 log("warn", "Unhandled header line: "..line); | |
| 110 end | |
| 111 end | |
| 112 if not headers_complete then return; end | |
| 113 -- Reached the end of the headers | |
| 114 if not expectbody(request, request.code) then | |
| 115 request.callback(nil, request.code, request); | |
| 116 return; | |
| 117 end | |
| 118 request.state = "body"; | |
| 119 if #data > startpos then | |
| 120 return request_reader(request, data, startpos); | |
| 121 end | |
| 122 elseif request.state == "status" then | |
| 123 log("debug", "Reading status...") | |
| 124 local http, code, text, linelen = data:match("^HTTP/(%S+) (%d+) (.-)\r\n()", startpos); | |
| 125 code = tonumber(code); | |
| 126 if not code then | |
| 127 log("warn", "Invalid HTTP status line, telling callback then closing"); | |
| 128 local ret = request.callback("invalid-status-line", 0, request); | |
| 129 destroy_request(request); | |
| 130 return ret; | |
| 131 end | |
| 132 | |
| 133 request.code, request.responseversion = code, http; | |
| 134 | |
| 135 if request.onlystatus then | |
| 136 if request.callback then | 52 if request.callback then |
| 137 request.callback(nil, code, request); | 53 for k,v in pairs(r) do request[k] = v; end |
| 54 request.callback(r.body, r.code, request); | |
| 55 request.callback = nil; | |
| 138 end | 56 end |
| 139 destroy_request(request); | 57 destroy_request(request); |
| 140 return; | |
| 141 end | 58 end |
| 142 | 59 local function error_cb(r) |
| 143 request.state = "headers"; | 60 if request.callback then |
| 144 | 61 request.callback(r or "connection-closed", 0, request); |
| 145 if #data > linelen then | 62 request.callback = nil; |
| 146 return request_reader(request, data, linelen); | 63 end |
| 64 destroy_request(request); | |
| 147 end | 65 end |
| 66 local function options_cb() | |
| 67 return request; | |
| 68 end | |
| 69 request.parser = httpstream_new(success_cb, error_cb, "client", options_cb); | |
| 148 end | 70 end |
| 71 request.parser:feed(data); | |
| 149 end | 72 end |
| 150 | 73 |
| 151 local function handleerr(err) log("error", "Traceback[http]: %s: %s", tostring(err), debug_traceback()); end | 74 local function handleerr(err) log("error", "Traceback[http]: %s: %s", tostring(err), debug_traceback()); end |
| 152 function request(u, ex, callback) | 75 function request(u, ex, callback) |
| 153 local req = url.parse(u); | 76 local req = url.parse(u); |