Software /
code /
prosody
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 |
parent | 7084:fdbe9ccac17d |
child | 7541: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 |