Mercurial > prosody-hg
comparison net/http/server.lua @ 7489:d32406f27efd
net.http.server: Add response method for reading response body from a file handle
| author | Kim Alvefur <zash@zash.se> |
|---|---|
| date | Mon, 11 Jul 2016 11:52:43 +0200 |
| parents | fdbe9ccac17d |
| children | 1d3f9da189b5 |
comparison
equal
deleted
inserted
replaced
| 7487:88a0a947e58c | 7489:d32406f27efd |
|---|---|
| 11 local xpcall = xpcall; | 11 local xpcall = xpcall; |
| 12 local traceback = debug.traceback; | 12 local traceback = debug.traceback; |
| 13 local tostring = tostring; | 13 local tostring = tostring; |
| 14 local cache = require "util.cache"; | 14 local cache = require "util.cache"; |
| 15 local codes = require "net.http.codes"; | 15 local codes = require "net.http.codes"; |
| 16 local blocksize = require "socket".BLOCKSIZE or 2048; | |
| 16 | 17 |
| 17 local _M = {}; | 18 local _M = {}; |
| 18 | 19 |
| 19 local sessions = {}; | 20 local sessions = {}; |
| 21 local incomplete = {}; | |
| 20 local listener = {}; | 22 local listener = {}; |
| 21 local hosts = {}; | 23 local hosts = {}; |
| 22 local default_host; | 24 local default_host; |
| 23 | 25 |
| 24 local function is_wildcard_event(event) | 26 local function is_wildcard_event(event) |
| 138 local open_response = conn._http_open_response; | 140 local open_response = conn._http_open_response; |
| 139 if open_response and open_response.on_destroy then | 141 if open_response and open_response.on_destroy then |
| 140 open_response.finished = true; | 142 open_response.finished = true; |
| 141 open_response:on_destroy(); | 143 open_response:on_destroy(); |
| 142 end | 144 end |
| 145 incomplete[conn] = nil; | |
| 143 sessions[conn] = nil; | 146 sessions[conn] = nil; |
| 144 end | 147 end |
| 145 | 148 |
| 146 function listener.ondetach(conn) | 149 function listener.ondetach(conn) |
| 147 sessions[conn] = nil; | 150 sessions[conn] = nil; |
| 151 incomplete[conn] = nil; | |
| 148 end | 152 end |
| 149 | 153 |
| 150 function listener.onincoming(conn, data) | 154 function listener.onincoming(conn, data) |
| 151 sessions[conn]:feed(data); | 155 sessions[conn]:feed(data); |
| 156 end | |
| 157 | |
| 158 function listener.ondrain(conn) | |
| 159 local response = incomplete[conn]; | |
| 160 if response and response._send_more then | |
| 161 response._send_more(); | |
| 162 end | |
| 152 end | 163 end |
| 153 | 164 |
| 154 local headerfix = setmetatable({}, { | 165 local headerfix = setmetatable({}, { |
| 155 __index = function(t, k) | 166 __index = function(t, k) |
| 156 local v = "\r\n"..k:gsub("_", "-"):gsub("%f[%w].", s_upper)..": "; | 167 local v = "\r\n"..k:gsub("_", "-"):gsub("%f[%w].", s_upper)..": "; |
| 188 status_code = 200; | 199 status_code = 200; |
| 189 headers = { date = date_header, connection = response_conn_header }; | 200 headers = { date = date_header, connection = response_conn_header }; |
| 190 persistent = persistent; | 201 persistent = persistent; |
| 191 conn = conn; | 202 conn = conn; |
| 192 send = _M.send_response; | 203 send = _M.send_response; |
| 204 send_file = _M.send_file; | |
| 193 done = _M.finish_response; | 205 done = _M.finish_response; |
| 194 finish_cb = finish_cb; | 206 finish_cb = finish_cb; |
| 195 }; | 207 }; |
| 196 conn._http_open_response = response; | 208 conn._http_open_response = response; |
| 197 | 209 |
| 270 local output = prepare_header(response); | 282 local output = prepare_header(response); |
| 271 t_insert(output, body); | 283 t_insert(output, body); |
| 272 response.conn:write(t_concat(output)); | 284 response.conn:write(t_concat(output)); |
| 273 response:done(); | 285 response:done(); |
| 274 end | 286 end |
| 287 function _M.send_file(response, f) | |
| 288 if response.finished then return; end | |
| 289 local chunked = not response.headers.content_length; | |
| 290 if chunked then response.headers.transfer_encoding = "chunked"; end | |
| 291 incomplete[response.conn] = response; | |
| 292 response._send_more = function () | |
| 293 if response.finished then | |
| 294 incomplete[response.conn] = nil; | |
| 295 return; | |
| 296 end | |
| 297 local chunk = f:read(blocksize); | |
| 298 if chunk then | |
| 299 if chunked then | |
| 300 chunk = ("%x\r\n%s\r\n"):format(#chunk, chunk); | |
| 301 end | |
| 302 -- io.write("."); io.flush(); | |
| 303 response.conn:write(chunk); | |
| 304 else | |
| 305 if chunked then | |
| 306 response.conn:write("0\r\n\r\n"); | |
| 307 end | |
| 308 -- io.write("\n"); | |
| 309 if f.close then f:close(); end | |
| 310 incomplete[response.conn] = nil; | |
| 311 return response:done(); | |
| 312 end | |
| 313 end | |
| 314 response.conn:write(t_concat(prepare_header(response))); | |
| 315 return true; | |
| 316 end | |
| 275 function _M.finish_response(response) | 317 function _M.finish_response(response) |
| 276 if response.finished then return; end | 318 if response.finished then return; end |
| 277 response.finished = true; | 319 response.finished = true; |
| 278 response.conn._http_open_response = nil; | 320 response.conn._http_open_response = nil; |
| 279 if response.on_destroy then | 321 if response.on_destroy then |
