Mercurial > prosody-hg
comparison net/httpserver.lua @ 3497:e9159b325e33
net.httpserver: Removed old HTTP parser, and updated to use util.httpstream.
| author | Waqas Hussain <waqas20@gmail.com> |
|---|---|
| date | Fri, 17 Sep 2010 04:06:07 +0500 |
| parents | 84fe4d5ac2ed |
| children | bc139431830b |
comparison
equal
deleted
inserted
replaced
| 3496:9408d1e10e17 | 3497:e9159b325e33 |
|---|---|
| 8 | 8 |
| 9 | 9 |
| 10 local socket = require "socket" | 10 local socket = require "socket" |
| 11 local server = require "net.server" | 11 local server = require "net.server" |
| 12 local url_parse = require "socket.url".parse; | 12 local url_parse = require "socket.url".parse; |
| 13 local httpstream_new = require "util.httpstream".new; | |
| 13 | 14 |
| 14 local connlisteners_start = require "net.connlisteners".start; | 15 local connlisteners_start = require "net.connlisteners".start; |
| 15 local connlisteners_get = require "net.connlisteners".get; | 16 local connlisteners_get = require "net.connlisteners".get; |
| 16 local listener; | 17 local listener; |
| 17 | 18 |
| 112 end | 113 end |
| 113 end | 114 end |
| 114 end | 115 end |
| 115 | 116 |
| 116 local function request_reader(request, data, startpos) | 117 local function request_reader(request, data, startpos) |
| 117 if not data then | 118 if not request.parser then |
| 118 if request.body then | 119 local function success_cb(r) |
| 120 for k,v in pairs(r) do request[k] = v; end | |
| 121 request.url = url_parse(request.path); | |
| 122 request.body = { request.body }; | |
| 119 call_callback(request); | 123 call_callback(request); |
| 120 else | 124 end |
| 121 -- Error.. connection was closed prematurely | 125 local function error_cb(r) |
| 122 call_callback(request, "connection-closed"); | 126 call_callback(request, r or "connection-closed"); |
| 123 end | 127 destroy_request(request); |
| 124 -- Here we force a destroy... the connection is gone, so we can't reply later | 128 end |
| 125 destroy_request(request); | 129 request.parser = httpstream_new(success_cb, error_cb); |
| 126 return; | 130 end |
| 127 end | 131 request.parser:feed(data); |
| 128 if request.state == "body" then | |
| 129 log("debug", "Reading body...") | |
| 130 if not request.body then request.body = {}; request.havebodylength, request.bodylength = 0, tonumber(request.headers["content-length"]); end | |
| 131 if startpos then | |
| 132 data = data:sub(startpos, -1) | |
| 133 end | |
| 134 t_insert(request.body, data); | |
| 135 if request.bodylength then | |
| 136 request.havebodylength = request.havebodylength + #data; | |
| 137 if request.havebodylength >= request.bodylength then | |
| 138 -- We have the body | |
| 139 call_callback(request); | |
| 140 end | |
| 141 end | |
| 142 elseif request.state == "headers" then | |
| 143 log("debug", "Reading headers...") | |
| 144 local pos = startpos; | |
| 145 local headers, headers_complete = request.headers; | |
| 146 if not headers then | |
| 147 headers = {}; | |
| 148 request.headers = headers; | |
| 149 end | |
| 150 | |
| 151 for line in data:gmatch("(.-)\r\n") do | |
| 152 startpos = (startpos or 1) + #line + 2; | |
| 153 local k, v = line:match("(%S+): (.+)"); | |
| 154 if k and v then | |
| 155 k = k:lower(); | |
| 156 if headers[k] then | |
| 157 headers[k] = headers[k]..", "..v; | |
| 158 else | |
| 159 headers[k] = v; | |
| 160 end | |
| 161 --log("debug", "Header: '"..k:lower().."' = '"..v.."'"); | |
| 162 elseif #line == 0 then | |
| 163 headers_complete = true; | |
| 164 break; | |
| 165 else | |
| 166 log("debug", "Unhandled header line: "..line); | |
| 167 end | |
| 168 end | |
| 169 | |
| 170 if not headers_complete then return; end | |
| 171 | |
| 172 if not expectbody(request) then | |
| 173 call_callback(request); | |
| 174 return; | |
| 175 end | |
| 176 | |
| 177 -- Reached the end of the headers | |
| 178 request.state = "body"; | |
| 179 if #data > startpos then | |
| 180 return request_reader(request, data:sub(startpos, -1)); | |
| 181 end | |
| 182 elseif request.state == "request" then | |
| 183 log("debug", "Reading request line...") | |
| 184 local method, path, http, linelen = data:match("^(%S+) (%S+) HTTP/(%S+)\r\n()", startpos); | |
| 185 if not method then | |
| 186 log("warn", "Invalid HTTP status line, telling callback then closing"); | |
| 187 local ret = call_callback(request, "invalid-status-line"); | |
| 188 request:destroy(); | |
| 189 return ret; | |
| 190 end | |
| 191 | |
| 192 request.method, request.path, request.httpversion = method, path, http; | |
| 193 | |
| 194 request.url = url_parse(request.path); | |
| 195 | |
| 196 log("debug", method.." request for "..tostring(request.path) .. " on port "..request.handler:serverport()); | |
| 197 | |
| 198 if request.onlystatus then | |
| 199 if not call_callback(request) then | |
| 200 return; | |
| 201 end | |
| 202 end | |
| 203 | |
| 204 request.state = "headers"; | |
| 205 | |
| 206 if #data > linelen then | |
| 207 return request_reader(request, data:sub(linelen, -1)); | |
| 208 end | |
| 209 end | |
| 210 end | 132 end |
| 211 | 133 |
| 212 -- The default handler for requests | 134 -- The default handler for requests |
| 213 default_handler = function (method, body, request) | 135 default_handler = function (method, body, request) |
| 214 log("debug", method.." request for "..tostring(request.path) .. " on port "..request.handler:serverport()); | 136 log("debug", method.." request for "..tostring(request.path) .. " on port "..request.handler:serverport()); |
