net/http/server.lua
author Kim Alvefur <zash@zash.se>
Sat, 23 Mar 2024 20:48:19 +0100
changeset 13465 c673ff1075bd
parent 13384 d53dd83a9944
permissions -rw-r--r--
mod_posix: Move everything to util.startup This allows greater control over the order of events. Notably, the internal ordering between daemonization, initialization of libunbound and setup of signal handling is sensitive. libunbound starts a separate thread for processing DNS requests. If this thread is started before signal handling has been set up, it will not inherit the signal handlers and instead behave as it would have before signal handlers were set up, i.e. cause the whole process to immediately exit. libunbound is usually initialized on the first DNS request, usually triggered by an outgoing s2s connection attempt. If daemonization happens before signals have been set up, signals may not be processed at all.
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
4631
fc5d3b053454 net.http.{server|codes|parser}: Initial commit.
Waqas Hussain <waqas20@gmail.com>
parents:
diff changeset
     1
11375
73f7acf8a61f net.http.server: Enable async during HTTP request handling (fixes #1487)
Kim Alvefur <zash@zash.se>
parents: 11164
diff changeset
     2
local t_insert, t_concat = table.insert, table.concat;
12978
ba409c67353b net: Prefix module imports with prosody namespace
Kim Alvefur <zash@zash.se>
parents: 12890
diff changeset
     3
local parser_new = require "prosody.net.http.parser".new;
ba409c67353b net: Prefix module imports with prosody namespace
Kim Alvefur <zash@zash.se>
parents: 12890
diff changeset
     4
local events = require "prosody.util.events".new();
ba409c67353b net: Prefix module imports with prosody namespace
Kim Alvefur <zash@zash.se>
parents: 12890
diff changeset
     5
local addserver = require "prosody.net.server".addserver;
13105
c975dafa4303 net.http.server: Assign each request its own log source
Kim Alvefur <zash@zash.se>
parents: 13104
diff changeset
     6
local logger = require "prosody.util.logger";
c975dafa4303 net.http.server: Assign each request its own log source
Kim Alvefur <zash@zash.se>
parents: 13104
diff changeset
     7
local log = logger.init("http.server");
4631
fc5d3b053454 net.http.{server|codes|parser}: Initial commit.
Waqas Hussain <waqas20@gmail.com>
parents:
diff changeset
     8
local os_date = os.date;
fc5d3b053454 net.http.{server|codes|parser}: Initial commit.
Waqas Hussain <waqas20@gmail.com>
parents:
diff changeset
     9
local pairs = pairs;
fc5d3b053454 net.http.{server|codes|parser}: Initial commit.
Waqas Hussain <waqas20@gmail.com>
parents:
diff changeset
    10
local s_upper = string.upper;
fc5d3b053454 net.http.{server|codes|parser}: Initial commit.
Waqas Hussain <waqas20@gmail.com>
parents:
diff changeset
    11
local setmetatable = setmetatable;
12978
ba409c67353b net: Prefix module imports with prosody namespace
Kim Alvefur <zash@zash.se>
parents: 12890
diff changeset
    12
local cache = require "prosody.util.cache";
ba409c67353b net: Prefix module imports with prosody namespace
Kim Alvefur <zash@zash.se>
parents: 12890
diff changeset
    13
local codes = require "prosody.net.http.codes";
ba409c67353b net: Prefix module imports with prosody namespace
Kim Alvefur <zash@zash.se>
parents: 12890
diff changeset
    14
local promise = require "prosody.util.promise";
ba409c67353b net: Prefix module imports with prosody namespace
Kim Alvefur <zash@zash.se>
parents: 12890
diff changeset
    15
local errors = require "prosody.util.error";
7544
1d3f9da189b5 net.http.server: Set blocksize for serving data from FDs to 64k (sweet spot of efficiency according to a recent study)
Kim Alvefur <zash@zash.se>
parents: 7492
diff changeset
    16
local blocksize = 2^16;
12978
ba409c67353b net: Prefix module imports with prosody namespace
Kim Alvefur <zash@zash.se>
parents: 12890
diff changeset
    17
local async = require "prosody.util.async";
13104
18ffe7833446 net.http.server: Assign an ID to each request, shared with response
Kim Alvefur <zash@zash.se>
parents: 12978
diff changeset
    18
local id = require"prosody.util.id";
4631
fc5d3b053454 net.http.{server|codes|parser}: Initial commit.
Waqas Hussain <waqas20@gmail.com>
parents:
diff changeset
    19
fc5d3b053454 net.http.{server|codes|parser}: Initial commit.
Waqas Hussain <waqas20@gmail.com>
parents:
diff changeset
    20
local _M = {};
fc5d3b053454 net.http.{server|codes|parser}: Initial commit.
Waqas Hussain <waqas20@gmail.com>
parents:
diff changeset
    21
fc5d3b053454 net.http.{server|codes|parser}: Initial commit.
Waqas Hussain <waqas20@gmail.com>
parents:
diff changeset
    22
local sessions = {};
7492
d32406f27efd net.http.server: Add response method for reading response body from a file handle
Kim Alvefur <zash@zash.se>
parents: 7087
diff changeset
    23
local incomplete = {};
4631
fc5d3b053454 net.http.{server|codes|parser}: Initial commit.
Waqas Hussain <waqas20@gmail.com>
parents:
diff changeset
    24
local listener = {};
4736
3514338c59c3 net.http.server, mod_http: Support http_default_host config option to specify where to direct requests for unknown HTTP vhosts
Matthew Wild <mwild1@gmail.com>
parents: 4735
diff changeset
    25
local hosts = {};
3514338c59c3 net.http.server, mod_http: Support http_default_host config option to specify where to direct requests for unknown HTTP vhosts
Matthew Wild <mwild1@gmail.com>
parents: 4735
diff changeset
    26
local default_host;
7582
d430573fe9f8 net.http.server: Expose way to set http server options
Kim Alvefur <zash@zash.se>
parents: 6592
diff changeset
    27
local options = {};
4631
fc5d3b053454 net.http.{server|codes|parser}: Initial commit.
Waqas Hussain <waqas20@gmail.com>
parents:
diff changeset
    28
4668
cce0c739b0d7 net.http.server: Support for wildcard events (events that end with '/*')
Matthew Wild <mwild1@gmail.com>
parents: 4659
diff changeset
    29
local function is_wildcard_event(event)
cce0c739b0d7 net.http.server: Support for wildcard events (events that end with '/*')
Matthew Wild <mwild1@gmail.com>
parents: 4659
diff changeset
    30
	return event:sub(-2, -1) == "/*";
cce0c739b0d7 net.http.server: Support for wildcard events (events that end with '/*')
Matthew Wild <mwild1@gmail.com>
parents: 4659
diff changeset
    31
end
cce0c739b0d7 net.http.server: Support for wildcard events (events that end with '/*')
Matthew Wild <mwild1@gmail.com>
parents: 4659
diff changeset
    32
local function is_wildcard_match(wildcard_event, event)
cce0c739b0d7 net.http.server: Support for wildcard events (events that end with '/*')
Matthew Wild <mwild1@gmail.com>
parents: 4659
diff changeset
    33
	return wildcard_event:sub(1, -2) == event:sub(1, #wildcard_event-1);
cce0c739b0d7 net.http.server: Support for wildcard events (events that end with '/*')
Matthew Wild <mwild1@gmail.com>
parents: 4659
diff changeset
    34
end
cce0c739b0d7 net.http.server: Support for wildcard events (events that end with '/*')
Matthew Wild <mwild1@gmail.com>
parents: 4659
diff changeset
    35
6953
8ab809358922 net.http.server: Use new util.cache to remember wildcard event handlers
Matthew Wild <mwild1@gmail.com>
parents: 6611
diff changeset
    36
local _handlers = events._handlers;
7585
e080b8b4f3cb net.http.server: Add luacheck annotations
Kim Alvefur <zash@zash.se>
parents: 7584
diff changeset
    37
local recent_wildcard_events = cache.new(10000, function (key, value) -- luacheck: ignore 212/value
6953
8ab809358922 net.http.server: Use new util.cache to remember wildcard event handlers
Matthew Wild <mwild1@gmail.com>
parents: 6611
diff changeset
    38
	rawset(_handlers, key, nil);
8ab809358922 net.http.server: Use new util.cache to remember wildcard event handlers
Matthew Wild <mwild1@gmail.com>
parents: 6611
diff changeset
    39
end);
5503
91052e59375c net.server.http: Ensure that event map cannot grow forever (limit to 10K wildcard-only entries)
Matthew Wild <mwild1@gmail.com>
parents: 5487
diff changeset
    40
4668
cce0c739b0d7 net.http.server: Support for wildcard events (events that end with '/*')
Matthew Wild <mwild1@gmail.com>
parents: 4659
diff changeset
    41
local event_map = events._event_map;
cce0c739b0d7 net.http.server: Support for wildcard events (events that end with '/*')
Matthew Wild <mwild1@gmail.com>
parents: 4659
diff changeset
    42
setmetatable(events._handlers, {
5504
b760b5f0c2b0 net.server.http: Add a comment
Matthew Wild <mwild1@gmail.com>
parents: 5503
diff changeset
    43
	-- Called when firing an event that doesn't exist (but may match a wildcard handler)
4668
cce0c739b0d7 net.http.server: Support for wildcard events (events that end with '/*')
Matthew Wild <mwild1@gmail.com>
parents: 4659
diff changeset
    44
	__index = function (handlers, curr_event)
cce0c739b0d7 net.http.server: Support for wildcard events (events that end with '/*')
Matthew Wild <mwild1@gmail.com>
parents: 4659
diff changeset
    45
		if is_wildcard_event(curr_event) then return; end -- Wildcard events cannot be fired
cce0c739b0d7 net.http.server: Support for wildcard events (events that end with '/*')
Matthew Wild <mwild1@gmail.com>
parents: 4659
diff changeset
    46
		-- Find all handlers that could match this event, sort them
4689
e8c357259993 net.http.server: Small fix to comment
Matthew Wild <mwild1@gmail.com>
parents: 4688
diff changeset
    47
		-- and then put the array into handlers[curr_event] (and return it)
4668
cce0c739b0d7 net.http.server: Support for wildcard events (events that end with '/*')
Matthew Wild <mwild1@gmail.com>
parents: 4659
diff changeset
    48
		local matching_handlers_set = {};
cce0c739b0d7 net.http.server: Support for wildcard events (events that end with '/*')
Matthew Wild <mwild1@gmail.com>
parents: 4659
diff changeset
    49
		local handlers_array = {};
cce0c739b0d7 net.http.server: Support for wildcard events (events that end with '/*')
Matthew Wild <mwild1@gmail.com>
parents: 4659
diff changeset
    50
		for event, handlers_set in pairs(event_map) do
cce0c739b0d7 net.http.server: Support for wildcard events (events that end with '/*')
Matthew Wild <mwild1@gmail.com>
parents: 4659
diff changeset
    51
			if event == curr_event or
cce0c739b0d7 net.http.server: Support for wildcard events (events that end with '/*')
Matthew Wild <mwild1@gmail.com>
parents: 4659
diff changeset
    52
			is_wildcard_event(event) and is_wildcard_match(event, curr_event) then
cce0c739b0d7 net.http.server: Support for wildcard events (events that end with '/*')
Matthew Wild <mwild1@gmail.com>
parents: 4659
diff changeset
    53
				for handler, priority in pairs(handlers_set) do
4704
d6c4e58333cf net.http.server: Lower score of wildcard handlers to ensure specific handlers beat them
Matthew Wild <mwild1@gmail.com>
parents: 4694
diff changeset
    54
					matching_handlers_set[handler] = { (select(2, event:gsub("/", "%1"))), is_wildcard_event(event) and 0 or 1, priority };
4668
cce0c739b0d7 net.http.server: Support for wildcard events (events that end with '/*')
Matthew Wild <mwild1@gmail.com>
parents: 4659
diff changeset
    55
					table.insert(handlers_array, handler);
cce0c739b0d7 net.http.server: Support for wildcard events (events that end with '/*')
Matthew Wild <mwild1@gmail.com>
parents: 4659
diff changeset
    56
				end
cce0c739b0d7 net.http.server: Support for wildcard events (events that end with '/*')
Matthew Wild <mwild1@gmail.com>
parents: 4659
diff changeset
    57
			end
cce0c739b0d7 net.http.server: Support for wildcard events (events that end with '/*')
Matthew Wild <mwild1@gmail.com>
parents: 4659
diff changeset
    58
		end
4726
917a5ffb73f1 net.http.server: Correctly cache results of handler indexing, and also cache failures
Matthew Wild <mwild1@gmail.com>
parents: 4715
diff changeset
    59
		if #handlers_array > 0 then
917a5ffb73f1 net.http.server: Correctly cache results of handler indexing, and also cache failures
Matthew Wild <mwild1@gmail.com>
parents: 4715
diff changeset
    60
			table.sort(handlers_array, function(b, a)
917a5ffb73f1 net.http.server: Correctly cache results of handler indexing, and also cache failures
Matthew Wild <mwild1@gmail.com>
parents: 4715
diff changeset
    61
				local a_score, b_score = matching_handlers_set[a], matching_handlers_set[b];
917a5ffb73f1 net.http.server: Correctly cache results of handler indexing, and also cache failures
Matthew Wild <mwild1@gmail.com>
parents: 4715
diff changeset
    62
				for i = 1, #a_score do
917a5ffb73f1 net.http.server: Correctly cache results of handler indexing, and also cache failures
Matthew Wild <mwild1@gmail.com>
parents: 4715
diff changeset
    63
					if a_score[i] ~= b_score[i] then -- If equal, compare next score value
917a5ffb73f1 net.http.server: Correctly cache results of handler indexing, and also cache failures
Matthew Wild <mwild1@gmail.com>
parents: 4715
diff changeset
    64
						return a_score[i] < b_score[i];
917a5ffb73f1 net.http.server: Correctly cache results of handler indexing, and also cache failures
Matthew Wild <mwild1@gmail.com>
parents: 4715
diff changeset
    65
					end
4668
cce0c739b0d7 net.http.server: Support for wildcard events (events that end with '/*')
Matthew Wild <mwild1@gmail.com>
parents: 4659
diff changeset
    66
				end
4726
917a5ffb73f1 net.http.server: Correctly cache results of handler indexing, and also cache failures
Matthew Wild <mwild1@gmail.com>
parents: 4715
diff changeset
    67
				return false;
917a5ffb73f1 net.http.server: Correctly cache results of handler indexing, and also cache failures
Matthew Wild <mwild1@gmail.com>
parents: 4715
diff changeset
    68
			end);
917a5ffb73f1 net.http.server: Correctly cache results of handler indexing, and also cache failures
Matthew Wild <mwild1@gmail.com>
parents: 4715
diff changeset
    69
		else
917a5ffb73f1 net.http.server: Correctly cache results of handler indexing, and also cache failures
Matthew Wild <mwild1@gmail.com>
parents: 4715
diff changeset
    70
			handlers_array = false;
917a5ffb73f1 net.http.server: Correctly cache results of handler indexing, and also cache failures
Matthew Wild <mwild1@gmail.com>
parents: 4715
diff changeset
    71
		end
917a5ffb73f1 net.http.server: Correctly cache results of handler indexing, and also cache failures
Matthew Wild <mwild1@gmail.com>
parents: 4715
diff changeset
    72
		rawset(handlers, curr_event, handlers_array);
5503
91052e59375c net.server.http: Ensure that event map cannot grow forever (limit to 10K wildcard-only entries)
Matthew Wild <mwild1@gmail.com>
parents: 5487
diff changeset
    73
		if not event_map[curr_event] then -- Only wildcard handlers match, if any
6953
8ab809358922 net.http.server: Use new util.cache to remember wildcard event handlers
Matthew Wild <mwild1@gmail.com>
parents: 6611
diff changeset
    74
			recent_wildcard_events:set(curr_event, true);
5503
91052e59375c net.server.http: Ensure that event map cannot grow forever (limit to 10K wildcard-only entries)
Matthew Wild <mwild1@gmail.com>
parents: 5487
diff changeset
    75
		end
4668
cce0c739b0d7 net.http.server: Support for wildcard events (events that end with '/*')
Matthew Wild <mwild1@gmail.com>
parents: 4659
diff changeset
    76
		return handlers_array;
cce0c739b0d7 net.http.server: Support for wildcard events (events that end with '/*')
Matthew Wild <mwild1@gmail.com>
parents: 4659
diff changeset
    77
	end;
cce0c739b0d7 net.http.server: Support for wildcard events (events that end with '/*')
Matthew Wild <mwild1@gmail.com>
parents: 4659
diff changeset
    78
	__newindex = function (handlers, curr_event, handlers_array)
cce0c739b0d7 net.http.server: Support for wildcard events (events that end with '/*')
Matthew Wild <mwild1@gmail.com>
parents: 4659
diff changeset
    79
		if handlers_array == nil
cce0c739b0d7 net.http.server: Support for wildcard events (events that end with '/*')
Matthew Wild <mwild1@gmail.com>
parents: 4659
diff changeset
    80
		and is_wildcard_event(curr_event) then
4735
474166c08319 net.http.server: Improve comment
Matthew Wild <mwild1@gmail.com>
parents: 4727
diff changeset
    81
			-- Invalidate the indexes of all matching events
4668
cce0c739b0d7 net.http.server: Support for wildcard events (events that end with '/*')
Matthew Wild <mwild1@gmail.com>
parents: 4659
diff changeset
    82
			for event in pairs(handlers) do
cce0c739b0d7 net.http.server: Support for wildcard events (events that end with '/*')
Matthew Wild <mwild1@gmail.com>
parents: 4659
diff changeset
    83
				if is_wildcard_match(curr_event, event) then
cce0c739b0d7 net.http.server: Support for wildcard events (events that end with '/*')
Matthew Wild <mwild1@gmail.com>
parents: 4659
diff changeset
    84
					handlers[event] = nil;
cce0c739b0d7 net.http.server: Support for wildcard events (events that end with '/*')
Matthew Wild <mwild1@gmail.com>
parents: 4659
diff changeset
    85
				end
cce0c739b0d7 net.http.server: Support for wildcard events (events that end with '/*')
Matthew Wild <mwild1@gmail.com>
parents: 4659
diff changeset
    86
			end
cce0c739b0d7 net.http.server: Support for wildcard events (events that end with '/*')
Matthew Wild <mwild1@gmail.com>
parents: 4659
diff changeset
    87
		end
4726
917a5ffb73f1 net.http.server: Correctly cache results of handler indexing, and also cache failures
Matthew Wild <mwild1@gmail.com>
parents: 4715
diff changeset
    88
		rawset(handlers, curr_event, handlers_array);
4668
cce0c739b0d7 net.http.server: Support for wildcard events (events that end with '/*')
Matthew Wild <mwild1@gmail.com>
parents: 4659
diff changeset
    89
	end;
cce0c739b0d7 net.http.server: Support for wildcard events (events that end with '/*')
Matthew Wild <mwild1@gmail.com>
parents: 4659
diff changeset
    90
});
cce0c739b0d7 net.http.server: Support for wildcard events (events that end with '/*')
Matthew Wild <mwild1@gmail.com>
parents: 4659
diff changeset
    91
4631
fc5d3b053454 net.http.{server|codes|parser}: Initial commit.
Waqas Hussain <waqas20@gmail.com>
parents:
diff changeset
    92
local handle_request;
4710
54ca6511e699 net.http.server: Make error handling overrideable via 'http-error' event
Matthew Wild <mwild1@gmail.com>
parents: 4709
diff changeset
    93
54ca6511e699 net.http.server: Make error handling overrideable via 'http-error' event
Matthew Wild <mwild1@gmail.com>
parents: 4709
diff changeset
    94
events.add_handler("http-error", function (error)
54ca6511e699 net.http.server: Make error handling overrideable via 'http-error' event
Matthew Wild <mwild1@gmail.com>
parents: 4709
diff changeset
    95
	return "Error processing request: "..codes[error.code]..". Check your error log for more information.";
54ca6511e699 net.http.server: Make error handling overrideable via 'http-error' event
Matthew Wild <mwild1@gmail.com>
parents: 4709
diff changeset
    96
end, -1);
4631
fc5d3b053454 net.http.{server|codes|parser}: Initial commit.
Waqas Hussain <waqas20@gmail.com>
parents:
diff changeset
    97
11375
73f7acf8a61f net.http.server: Enable async during HTTP request handling (fixes #1487)
Kim Alvefur <zash@zash.se>
parents: 11164
diff changeset
    98
local runner_callbacks = {};
73f7acf8a61f net.http.server: Enable async during HTTP request handling (fixes #1487)
Kim Alvefur <zash@zash.se>
parents: 11164
diff changeset
    99
73f7acf8a61f net.http.server: Enable async during HTTP request handling (fixes #1487)
Kim Alvefur <zash@zash.se>
parents: 11164
diff changeset
   100
function runner_callbacks:ready()
11376
b877bd74d65e net.http.server: Allow storing more than the parser in the session
Kim Alvefur <zash@zash.se>
parents: 11375
diff changeset
   101
	self.data.conn:resume();
11375
73f7acf8a61f net.http.server: Enable async during HTTP request handling (fixes #1487)
Kim Alvefur <zash@zash.se>
parents: 11164
diff changeset
   102
end
73f7acf8a61f net.http.server: Enable async during HTTP request handling (fixes #1487)
Kim Alvefur <zash@zash.se>
parents: 11164
diff changeset
   103
73f7acf8a61f net.http.server: Enable async during HTTP request handling (fixes #1487)
Kim Alvefur <zash@zash.se>
parents: 11164
diff changeset
   104
function runner_callbacks:waiting()
11376
b877bd74d65e net.http.server: Allow storing more than the parser in the session
Kim Alvefur <zash@zash.se>
parents: 11375
diff changeset
   105
	self.data.conn:pause();
11375
73f7acf8a61f net.http.server: Enable async during HTTP request handling (fixes #1487)
Kim Alvefur <zash@zash.se>
parents: 11164
diff changeset
   106
end
73f7acf8a61f net.http.server: Enable async during HTTP request handling (fixes #1487)
Kim Alvefur <zash@zash.se>
parents: 11164
diff changeset
   107
73f7acf8a61f net.http.server: Enable async during HTTP request handling (fixes #1487)
Kim Alvefur <zash@zash.se>
parents: 11164
diff changeset
   108
function runner_callbacks:error(err)
73f7acf8a61f net.http.server: Enable async during HTTP request handling (fixes #1487)
Kim Alvefur <zash@zash.se>
parents: 11164
diff changeset
   109
	log("error", "Traceback[httpserver]: %s", err);
13264
da21185fd026 net.http.server: Support setting Content-Type of uncaught HTTP errors
Kim Alvefur <zash@zash.se>
parents: 13122
diff changeset
   110
	local response = { headers = { content_type = "text/plain" }; body = "" };
da21185fd026 net.http.server: Support setting Content-Type of uncaught HTTP errors
Kim Alvefur <zash@zash.se>
parents: 13122
diff changeset
   111
	response.body = events.fire_event("http-error", { code = 500; private_message = err; response = response });
13384
d53dd83a9944 net.http.server: Fix whitespace-ignoring syntax
Kim Alvefur <zash@zash.se>
parents: 13345
diff changeset
   112
	self.data.conn:write("HTTP/1.0 500 Internal Server Error\r\n\z
d53dd83a9944 net.http.server: Fix whitespace-ignoring syntax
Kim Alvefur <zash@zash.se>
parents: 13345
diff changeset
   113
		X-Content-Type-Options: nosniff\r\n\z
13265
7c62370dee9a net.http.server: Fix typo in previous commit
Kim Alvefur <zash@zash.se>
parents: 13264
diff changeset
   114
		Content-Type: " .. response.headers.content_type .. "\r\n\r\n");
13264
da21185fd026 net.http.server: Support setting Content-Type of uncaught HTTP errors
Kim Alvefur <zash@zash.se>
parents: 13122
diff changeset
   115
	self.data.conn:write(response.body);
11376
b877bd74d65e net.http.server: Allow storing more than the parser in the session
Kim Alvefur <zash@zash.se>
parents: 11375
diff changeset
   116
	self.data.conn:close();
11375
73f7acf8a61f net.http.server: Enable async during HTTP request handling (fixes #1487)
Kim Alvefur <zash@zash.se>
parents: 11164
diff changeset
   117
end
73f7acf8a61f net.http.server: Enable async during HTTP request handling (fixes #1487)
Kim Alvefur <zash@zash.se>
parents: 11164
diff changeset
   118
11377
ad3b5384fc03 net.http.server: Don't pause early streaming uploads
Kim Alvefur <zash@zash.se>
parents: 11376
diff changeset
   119
local function noop() end
4631
fc5d3b053454 net.http.{server|codes|parser}: Initial commit.
Waqas Hussain <waqas20@gmail.com>
parents:
diff changeset
   120
function listener.onconnect(conn)
11376
b877bd74d65e net.http.server: Allow storing more than the parser in the session
Kim Alvefur <zash@zash.se>
parents: 11375
diff changeset
   121
	local session = { conn = conn };
4631
fc5d3b053454 net.http.{server|codes|parser}: Initial commit.
Waqas Hussain <waqas20@gmail.com>
parents:
diff changeset
   122
	local secure = conn:ssl() and true or nil;
11413
d30c44a829c1 net.http.server: Set request.ip so mod_http doesn't have to
Kim Alvefur <zash@zash.se>
parents: 11377
diff changeset
   123
	local ip = conn:ip();
11376
b877bd74d65e net.http.server: Allow storing more than the parser in the session
Kim Alvefur <zash@zash.se>
parents: 11375
diff changeset
   124
	session.thread = async.runner(function (request)
11377
ad3b5384fc03 net.http.server: Don't pause early streaming uploads
Kim Alvefur <zash@zash.se>
parents: 11376
diff changeset
   125
		local wait, done;
ad3b5384fc03 net.http.server: Don't pause early streaming uploads
Kim Alvefur <zash@zash.se>
parents: 11376
diff changeset
   126
		if request.partial == true then
ad3b5384fc03 net.http.server: Don't pause early streaming uploads
Kim Alvefur <zash@zash.se>
parents: 11376
diff changeset
   127
			-- Have the header for a request, we want to receive the rest
ad3b5384fc03 net.http.server: Don't pause early streaming uploads
Kim Alvefur <zash@zash.se>
parents: 11376
diff changeset
   128
			-- when we've decided where the data should go.
ad3b5384fc03 net.http.server: Don't pause early streaming uploads
Kim Alvefur <zash@zash.se>
parents: 11376
diff changeset
   129
			wait, done = noop, noop;
ad3b5384fc03 net.http.server: Don't pause early streaming uploads
Kim Alvefur <zash@zash.se>
parents: 11376
diff changeset
   130
		else -- Got the entire request
ad3b5384fc03 net.http.server: Don't pause early streaming uploads
Kim Alvefur <zash@zash.se>
parents: 11376
diff changeset
   131
			-- Hold off on receiving more incoming requests until this one has been handled.
ad3b5384fc03 net.http.server: Don't pause early streaming uploads
Kim Alvefur <zash@zash.se>
parents: 11376
diff changeset
   132
			wait, done = async.waiter();
ad3b5384fc03 net.http.server: Don't pause early streaming uploads
Kim Alvefur <zash@zash.se>
parents: 11376
diff changeset
   133
		end
11375
73f7acf8a61f net.http.server: Enable async during HTTP request handling (fixes #1487)
Kim Alvefur <zash@zash.se>
parents: 11164
diff changeset
   134
		handle_request(conn, request, done); wait();
11376
b877bd74d65e net.http.server: Allow storing more than the parser in the session
Kim Alvefur <zash@zash.se>
parents: 11375
diff changeset
   135
	end, runner_callbacks, session);
4631
fc5d3b053454 net.http.{server|codes|parser}: Initial commit.
Waqas Hussain <waqas20@gmail.com>
parents:
diff changeset
   136
	local function success_cb(request)
fc5d3b053454 net.http.{server|codes|parser}: Initial commit.
Waqas Hussain <waqas20@gmail.com>
parents:
diff changeset
   137
		--log("debug", "success_cb: %s", request.path);
13104
18ffe7833446 net.http.server: Assign an ID to each request, shared with response
Kim Alvefur <zash@zash.se>
parents: 12978
diff changeset
   138
		request.id = id.short();
13105
c975dafa4303 net.http.server: Assign each request its own log source
Kim Alvefur <zash@zash.se>
parents: 13104
diff changeset
   139
		request.log = logger.init("http." .. request.method .. "-" .. request.id);
11413
d30c44a829c1 net.http.server: Set request.ip so mod_http doesn't have to
Kim Alvefur <zash@zash.se>
parents: 11377
diff changeset
   140
		request.ip = ip;
4631
fc5d3b053454 net.http.{server|codes|parser}: Initial commit.
Waqas Hussain <waqas20@gmail.com>
parents:
diff changeset
   141
		request.secure = secure;
11376
b877bd74d65e net.http.server: Allow storing more than the parser in the session
Kim Alvefur <zash@zash.se>
parents: 11375
diff changeset
   142
		session.thread:run(request);
4631
fc5d3b053454 net.http.{server|codes|parser}: Initial commit.
Waqas Hussain <waqas20@gmail.com>
parents:
diff changeset
   143
	end
fc5d3b053454 net.http.{server|codes|parser}: Initial commit.
Waqas Hussain <waqas20@gmail.com>
parents:
diff changeset
   144
	local function error_cb(err)
fc5d3b053454 net.http.{server|codes|parser}: Initial commit.
Waqas Hussain <waqas20@gmail.com>
parents:
diff changeset
   145
		log("debug", "error_cb: %s", err or "<nil>");
fc5d3b053454 net.http.{server|codes|parser}: Initial commit.
Waqas Hussain <waqas20@gmail.com>
parents:
diff changeset
   146
		-- FIXME don't close immediately, wait until we process current stuff
fc5d3b053454 net.http.{server|codes|parser}: Initial commit.
Waqas Hussain <waqas20@gmail.com>
parents:
diff changeset
   147
		-- FIXME if err, send off a bad-request response
fc5d3b053454 net.http.{server|codes|parser}: Initial commit.
Waqas Hussain <waqas20@gmail.com>
parents:
diff changeset
   148
		conn:close();
fc5d3b053454 net.http.{server|codes|parser}: Initial commit.
Waqas Hussain <waqas20@gmail.com>
parents:
diff changeset
   149
	end
7582
d430573fe9f8 net.http.server: Expose way to set http server options
Kim Alvefur <zash@zash.se>
parents: 6592
diff changeset
   150
	local function options_cb()
d430573fe9f8 net.http.server: Expose way to set http server options
Kim Alvefur <zash@zash.se>
parents: 6592
diff changeset
   151
		return options;
d430573fe9f8 net.http.server: Expose way to set http server options
Kim Alvefur <zash@zash.se>
parents: 6592
diff changeset
   152
	end
11376
b877bd74d65e net.http.server: Allow storing more than the parser in the session
Kim Alvefur <zash@zash.se>
parents: 11375
diff changeset
   153
	session.parser = parser_new(success_cb, error_cb, "server", options_cb);
b877bd74d65e net.http.server: Allow storing more than the parser in the session
Kim Alvefur <zash@zash.se>
parents: 11375
diff changeset
   154
	sessions[conn] = session;
4631
fc5d3b053454 net.http.{server|codes|parser}: Initial commit.
Waqas Hussain <waqas20@gmail.com>
parents:
diff changeset
   155
end
fc5d3b053454 net.http.{server|codes|parser}: Initial commit.
Waqas Hussain <waqas20@gmail.com>
parents:
diff changeset
   156
fc5d3b053454 net.http.{server|codes|parser}: Initial commit.
Waqas Hussain <waqas20@gmail.com>
parents:
diff changeset
   157
function listener.ondisconnect(conn)
4691
a164fc7057ae net.http.server: Support for on_destroy callback on response objects, and a 'finished' flag to say when they are destroyed (responded to or connection closed)
Matthew Wild <mwild1@gmail.com>
parents: 4689
diff changeset
   158
	local open_response = conn._http_open_response;
a164fc7057ae net.http.server: Support for on_destroy callback on response objects, and a 'finished' flag to say when they are destroyed (responded to or connection closed)
Matthew Wild <mwild1@gmail.com>
parents: 4689
diff changeset
   159
	if open_response and open_response.on_destroy then
a164fc7057ae net.http.server: Support for on_destroy callback on response objects, and a 'finished' flag to say when they are destroyed (responded to or connection closed)
Matthew Wild <mwild1@gmail.com>
parents: 4689
diff changeset
   160
		open_response.finished = true;
a164fc7057ae net.http.server: Support for on_destroy callback on response objects, and a 'finished' flag to say when they are destroyed (responded to or connection closed)
Matthew Wild <mwild1@gmail.com>
parents: 4689
diff changeset
   161
		open_response:on_destroy();
a164fc7057ae net.http.server: Support for on_destroy callback on response objects, and a 'finished' flag to say when they are destroyed (responded to or connection closed)
Matthew Wild <mwild1@gmail.com>
parents: 4689
diff changeset
   162
	end
7492
d32406f27efd net.http.server: Add response method for reading response body from a file handle
Kim Alvefur <zash@zash.se>
parents: 7087
diff changeset
   163
	incomplete[conn] = nil;
4631
fc5d3b053454 net.http.{server|codes|parser}: Initial commit.
Waqas Hussain <waqas20@gmail.com>
parents:
diff changeset
   164
	sessions[conn] = nil;
fc5d3b053454 net.http.{server|codes|parser}: Initial commit.
Waqas Hussain <waqas20@gmail.com>
parents:
diff changeset
   165
end
fc5d3b053454 net.http.{server|codes|parser}: Initial commit.
Waqas Hussain <waqas20@gmail.com>
parents:
diff changeset
   166
6380
4220ffb87b22 net.http, net.http.server, mod_c2s, mod_s2s, mod_component, mod_admin_telnet, mod_net_multiplex: Add ondetach to release connection from 'sessions' table (or equivalent)
Matthew Wild <mwild1@gmail.com>
parents: 6360
diff changeset
   167
function listener.ondetach(conn)
4220ffb87b22 net.http, net.http.server, mod_c2s, mod_s2s, mod_component, mod_admin_telnet, mod_net_multiplex: Add ondetach to release connection from 'sessions' table (or equivalent)
Matthew Wild <mwild1@gmail.com>
parents: 6360
diff changeset
   168
	sessions[conn] = nil;
7492
d32406f27efd net.http.server: Add response method for reading response body from a file handle
Kim Alvefur <zash@zash.se>
parents: 7087
diff changeset
   169
	incomplete[conn] = nil;
6380
4220ffb87b22 net.http, net.http.server, mod_c2s, mod_s2s, mod_component, mod_admin_telnet, mod_net_multiplex: Add ondetach to release connection from 'sessions' table (or equivalent)
Matthew Wild <mwild1@gmail.com>
parents: 6360
diff changeset
   170
end
4220ffb87b22 net.http, net.http.server, mod_c2s, mod_s2s, mod_component, mod_admin_telnet, mod_net_multiplex: Add ondetach to release connection from 'sessions' table (or equivalent)
Matthew Wild <mwild1@gmail.com>
parents: 6360
diff changeset
   171
4631
fc5d3b053454 net.http.{server|codes|parser}: Initial commit.
Waqas Hussain <waqas20@gmail.com>
parents:
diff changeset
   172
function listener.onincoming(conn, data)
11376
b877bd74d65e net.http.server: Allow storing more than the parser in the session
Kim Alvefur <zash@zash.se>
parents: 11375
diff changeset
   173
	sessions[conn].parser:feed(data);
4631
fc5d3b053454 net.http.{server|codes|parser}: Initial commit.
Waqas Hussain <waqas20@gmail.com>
parents:
diff changeset
   174
end
fc5d3b053454 net.http.{server|codes|parser}: Initial commit.
Waqas Hussain <waqas20@gmail.com>
parents:
diff changeset
   175
7492
d32406f27efd net.http.server: Add response method for reading response body from a file handle
Kim Alvefur <zash@zash.se>
parents: 7087
diff changeset
   176
function listener.ondrain(conn)
d32406f27efd net.http.server: Add response method for reading response body from a file handle
Kim Alvefur <zash@zash.se>
parents: 7087
diff changeset
   177
	local response = incomplete[conn];
d32406f27efd net.http.server: Add response method for reading response body from a file handle
Kim Alvefur <zash@zash.se>
parents: 7087
diff changeset
   178
	if response and response._send_more then
d32406f27efd net.http.server: Add response method for reading response body from a file handle
Kim Alvefur <zash@zash.se>
parents: 7087
diff changeset
   179
		response._send_more();
d32406f27efd net.http.server: Add response method for reading response body from a file handle
Kim Alvefur <zash@zash.se>
parents: 7087
diff changeset
   180
	end
d32406f27efd net.http.server: Add response method for reading response body from a file handle
Kim Alvefur <zash@zash.se>
parents: 7087
diff changeset
   181
end
d32406f27efd net.http.server: Add response method for reading response body from a file handle
Kim Alvefur <zash@zash.se>
parents: 7087
diff changeset
   182
4631
fc5d3b053454 net.http.{server|codes|parser}: Initial commit.
Waqas Hussain <waqas20@gmail.com>
parents:
diff changeset
   183
local headerfix = setmetatable({}, {
fc5d3b053454 net.http.{server|codes|parser}: Initial commit.
Waqas Hussain <waqas20@gmail.com>
parents:
diff changeset
   184
	__index = function(t, k)
fc5d3b053454 net.http.{server|codes|parser}: Initial commit.
Waqas Hussain <waqas20@gmail.com>
parents:
diff changeset
   185
		local v = "\r\n"..k:gsub("_", "-"):gsub("%f[%w].", s_upper)..": ";
fc5d3b053454 net.http.{server|codes|parser}: Initial commit.
Waqas Hussain <waqas20@gmail.com>
parents:
diff changeset
   186
		t[k] = v;
fc5d3b053454 net.http.{server|codes|parser}: Initial commit.
Waqas Hussain <waqas20@gmail.com>
parents:
diff changeset
   187
		return v;
fc5d3b053454 net.http.{server|codes|parser}: Initial commit.
Waqas Hussain <waqas20@gmail.com>
parents:
diff changeset
   188
	end
fc5d3b053454 net.http.{server|codes|parser}: Initial commit.
Waqas Hussain <waqas20@gmail.com>
parents:
diff changeset
   189
});
fc5d3b053454 net.http.{server|codes|parser}: Initial commit.
Waqas Hussain <waqas20@gmail.com>
parents:
diff changeset
   190
10396
7a95f27ac9d6 net.http.server: Factor out handling of event response for easier reuse
Kim Alvefur <zash@zash.se>
parents: 10330
diff changeset
   191
local function handle_result(request, response, result)
7a95f27ac9d6 net.http.server: Factor out handling of event response for easier reuse
Kim Alvefur <zash@zash.se>
parents: 10330
diff changeset
   192
	if result == nil then
7a95f27ac9d6 net.http.server: Factor out handling of event response for easier reuse
Kim Alvefur <zash@zash.se>
parents: 10330
diff changeset
   193
		result = 404;
7a95f27ac9d6 net.http.server: Factor out handling of event response for easier reuse
Kim Alvefur <zash@zash.se>
parents: 10330
diff changeset
   194
	end
7a95f27ac9d6 net.http.server: Factor out handling of event response for easier reuse
Kim Alvefur <zash@zash.se>
parents: 10330
diff changeset
   195
7a95f27ac9d6 net.http.server: Factor out handling of event response for easier reuse
Kim Alvefur <zash@zash.se>
parents: 10330
diff changeset
   196
	if result == true then
7a95f27ac9d6 net.http.server: Factor out handling of event response for easier reuse
Kim Alvefur <zash@zash.se>
parents: 10330
diff changeset
   197
		return;
7a95f27ac9d6 net.http.server: Factor out handling of event response for easier reuse
Kim Alvefur <zash@zash.se>
parents: 10330
diff changeset
   198
	end
7a95f27ac9d6 net.http.server: Factor out handling of event response for easier reuse
Kim Alvefur <zash@zash.se>
parents: 10330
diff changeset
   199
7a95f27ac9d6 net.http.server: Factor out handling of event response for easier reuse
Kim Alvefur <zash@zash.se>
parents: 10330
diff changeset
   200
	local body;
7a95f27ac9d6 net.http.server: Factor out handling of event response for easier reuse
Kim Alvefur <zash@zash.se>
parents: 10330
diff changeset
   201
	local result_type = type(result);
7a95f27ac9d6 net.http.server: Factor out handling of event response for easier reuse
Kim Alvefur <zash@zash.se>
parents: 10330
diff changeset
   202
	if result_type == "number" then
7a95f27ac9d6 net.http.server: Factor out handling of event response for easier reuse
Kim Alvefur <zash@zash.se>
parents: 10330
diff changeset
   203
		response.status_code = result;
7a95f27ac9d6 net.http.server: Factor out handling of event response for easier reuse
Kim Alvefur <zash@zash.se>
parents: 10330
diff changeset
   204
		if result >= 400 then
7a95f27ac9d6 net.http.server: Factor out handling of event response for easier reuse
Kim Alvefur <zash@zash.se>
parents: 10330
diff changeset
   205
			body = events.fire_event("http-error", { request = request, response = response, code = result });
7a95f27ac9d6 net.http.server: Factor out handling of event response for easier reuse
Kim Alvefur <zash@zash.se>
parents: 10330
diff changeset
   206
		end
7a95f27ac9d6 net.http.server: Factor out handling of event response for easier reuse
Kim Alvefur <zash@zash.se>
parents: 10330
diff changeset
   207
	elseif result_type == "string" then
7a95f27ac9d6 net.http.server: Factor out handling of event response for easier reuse
Kim Alvefur <zash@zash.se>
parents: 10330
diff changeset
   208
		body = result;
10398
955e54e451dc net.http.server: Handle util.error objects from http handlers
Kim Alvefur <zash@zash.se>
parents: 10397
diff changeset
   209
	elseif errors.is_err(result) then
10723
977c9883f625 net.http.server: Use error code from util.error (fixes #1502)
Kim Alvefur <zash@zash.se>
parents: 10505
diff changeset
   210
		response.status_code = result.code or 500;
10505
e8186aba1583 util.error: Move default for numeric error code to net.http.server
Kim Alvefur <zash@zash.se>
parents: 10400
diff changeset
   211
		body = events.fire_event("http-error", { request = request, response = response, code = result.code or 500, error = result });
10399
faa4fcc78b14 net.http.server: Handle promises from http handlers
Kim Alvefur <zash@zash.se>
parents: 10398
diff changeset
   212
	elseif promise.is_promise(result) then
faa4fcc78b14 net.http.server: Handle promises from http handlers
Kim Alvefur <zash@zash.se>
parents: 10398
diff changeset
   213
		result:next(function (ret)
faa4fcc78b14 net.http.server: Handle promises from http handlers
Kim Alvefur <zash@zash.se>
parents: 10398
diff changeset
   214
			handle_result(request, response, ret);
faa4fcc78b14 net.http.server: Handle promises from http handlers
Kim Alvefur <zash@zash.se>
parents: 10398
diff changeset
   215
		end, function (err)
11100
dd1713862c20 net.http.server: Default to HTTP result code 500 when promise is rejected
Matthew Wild <mwild1@gmail.com>
parents: 10956
diff changeset
   216
			response.status_code = 500;
10400
3278f2a31a0a net.http.server: Treat promise rejection without value as a HTTP 500 error
Kim Alvefur <zash@zash.se>
parents: 10399
diff changeset
   217
			handle_result(request, response, err or 500);
10399
faa4fcc78b14 net.http.server: Handle promises from http handlers
Kim Alvefur <zash@zash.se>
parents: 10398
diff changeset
   218
		end);
faa4fcc78b14 net.http.server: Handle promises from http handlers
Kim Alvefur <zash@zash.se>
parents: 10398
diff changeset
   219
		return true;
10396
7a95f27ac9d6 net.http.server: Factor out handling of event response for easier reuse
Kim Alvefur <zash@zash.se>
parents: 10330
diff changeset
   220
	elseif result_type == "table" then
7a95f27ac9d6 net.http.server: Factor out handling of event response for easier reuse
Kim Alvefur <zash@zash.se>
parents: 10330
diff changeset
   221
		for k, v in pairs(result) do
7a95f27ac9d6 net.http.server: Factor out handling of event response for easier reuse
Kim Alvefur <zash@zash.se>
parents: 10330
diff changeset
   222
			if k ~= "headers" then
7a95f27ac9d6 net.http.server: Factor out handling of event response for easier reuse
Kim Alvefur <zash@zash.se>
parents: 10330
diff changeset
   223
				response[k] = v;
7a95f27ac9d6 net.http.server: Factor out handling of event response for easier reuse
Kim Alvefur <zash@zash.se>
parents: 10330
diff changeset
   224
			else
7a95f27ac9d6 net.http.server: Factor out handling of event response for easier reuse
Kim Alvefur <zash@zash.se>
parents: 10330
diff changeset
   225
				for header_name, header_value in pairs(v) do
7a95f27ac9d6 net.http.server: Factor out handling of event response for easier reuse
Kim Alvefur <zash@zash.se>
parents: 10330
diff changeset
   226
					response.headers[header_name] = header_value;
7a95f27ac9d6 net.http.server: Factor out handling of event response for easier reuse
Kim Alvefur <zash@zash.se>
parents: 10330
diff changeset
   227
				end
7a95f27ac9d6 net.http.server: Factor out handling of event response for easier reuse
Kim Alvefur <zash@zash.se>
parents: 10330
diff changeset
   228
			end
7a95f27ac9d6 net.http.server: Factor out handling of event response for easier reuse
Kim Alvefur <zash@zash.se>
parents: 10330
diff changeset
   229
		end
7a95f27ac9d6 net.http.server: Factor out handling of event response for easier reuse
Kim Alvefur <zash@zash.se>
parents: 10330
diff changeset
   230
	end
10397
0ea7b4769096 net.http.server: Tail call because tail call!
Kim Alvefur <zash@zash.se>
parents: 10396
diff changeset
   231
	return response:send(body);
10396
7a95f27ac9d6 net.http.server: Factor out handling of event response for easier reuse
Kim Alvefur <zash@zash.se>
parents: 10330
diff changeset
   232
end
7a95f27ac9d6 net.http.server: Factor out handling of event response for easier reuse
Kim Alvefur <zash@zash.se>
parents: 10330
diff changeset
   233
7585
e080b8b4f3cb net.http.server: Add luacheck annotations
Kim Alvefur <zash@zash.se>
parents: 7584
diff changeset
   234
function _M.hijack_response(response, listener) -- luacheck: ignore
4631
fc5d3b053454 net.http.{server|codes|parser}: Initial commit.
Waqas Hussain <waqas20@gmail.com>
parents:
diff changeset
   235
	error("TODO");
fc5d3b053454 net.http.{server|codes|parser}: Initial commit.
Waqas Hussain <waqas20@gmail.com>
parents:
diff changeset
   236
end
fc5d3b053454 net.http.{server|codes|parser}: Initial commit.
Waqas Hussain <waqas20@gmail.com>
parents:
diff changeset
   237
function handle_request(conn, request, finish_cb)
fc5d3b053454 net.http.{server|codes|parser}: Initial commit.
Waqas Hussain <waqas20@gmail.com>
parents:
diff changeset
   238
	--log("debug", "handler: %s", request.path);
fc5d3b053454 net.http.{server|codes|parser}: Initial commit.
Waqas Hussain <waqas20@gmail.com>
parents:
diff changeset
   239
	local headers = {};
fc5d3b053454 net.http.{server|codes|parser}: Initial commit.
Waqas Hussain <waqas20@gmail.com>
parents:
diff changeset
   240
	for k,v in pairs(request.headers) do headers[k:gsub("-", "_")] = v; end
fc5d3b053454 net.http.{server|codes|parser}: Initial commit.
Waqas Hussain <waqas20@gmail.com>
parents:
diff changeset
   241
	request.headers = headers;
fc5d3b053454 net.http.{server|codes|parser}: Initial commit.
Waqas Hussain <waqas20@gmail.com>
parents:
diff changeset
   242
	request.conn = conn;
fc5d3b053454 net.http.{server|codes|parser}: Initial commit.
Waqas Hussain <waqas20@gmail.com>
parents:
diff changeset
   243
13106
4e112b87543d net.http.server: Log request and response status lines
Kim Alvefur <zash@zash.se>
parents: 13105
diff changeset
   244
	request.log("debug", "%s %s HTTP/%s", request.method, request.path, request.httpversion);
4e112b87543d net.http.server: Log request and response status lines
Kim Alvefur <zash@zash.se>
parents: 13105
diff changeset
   245
4631
fc5d3b053454 net.http.{server|codes|parser}: Initial commit.
Waqas Hussain <waqas20@gmail.com>
parents:
diff changeset
   246
	local date_header = os_date('!%a, %d %b %Y %H:%M:%S GMT'); -- FIXME use
fc5d3b053454 net.http.{server|codes|parser}: Initial commit.
Waqas Hussain <waqas20@gmail.com>
parents:
diff changeset
   247
	local conn_header = request.headers.connection;
5300
fcb1be0b4a5c net.http.server: Properly handle persistent connections
Florian Zeitz <florob@babelmonkeys.de>
parents: 4788
diff changeset
   248
	conn_header = conn_header and ","..conn_header:gsub("[ \t]", ""):lower().."," or ""
fcb1be0b4a5c net.http.server: Properly handle persistent connections
Florian Zeitz <florob@babelmonkeys.de>
parents: 4788
diff changeset
   249
	local httpversion = request.httpversion
5754
dee0f05ccf70 net.http.server: Fix Keep-Alive requests with HTTP 1.0
Kim Alvefur <zash@zash.se>
parents: 5505
diff changeset
   250
	local persistent = conn_header:find(",keep-alive,", 1, true)
5300
fcb1be0b4a5c net.http.server: Properly handle persistent connections
Florian Zeitz <florob@babelmonkeys.de>
parents: 4788
diff changeset
   251
		or (httpversion == "1.1" and not conn_header:find(",close,", 1, true));
fcb1be0b4a5c net.http.server: Properly handle persistent connections
Florian Zeitz <florob@babelmonkeys.de>
parents: 4788
diff changeset
   252
fcb1be0b4a5c net.http.server: Properly handle persistent connections
Florian Zeitz <florob@babelmonkeys.de>
parents: 4788
diff changeset
   253
	local response_conn_header;
fcb1be0b4a5c net.http.server: Properly handle persistent connections
Florian Zeitz <florob@babelmonkeys.de>
parents: 4788
diff changeset
   254
	if persistent then
fcb1be0b4a5c net.http.server: Properly handle persistent connections
Florian Zeitz <florob@babelmonkeys.de>
parents: 4788
diff changeset
   255
		response_conn_header = "Keep-Alive";
fcb1be0b4a5c net.http.server: Properly handle persistent connections
Florian Zeitz <florob@babelmonkeys.de>
parents: 4788
diff changeset
   256
	else
fcb1be0b4a5c net.http.server: Properly handle persistent connections
Florian Zeitz <florob@babelmonkeys.de>
parents: 4788
diff changeset
   257
		response_conn_header = httpversion == "1.1" and "close" or nil
fcb1be0b4a5c net.http.server: Properly handle persistent connections
Florian Zeitz <florob@babelmonkeys.de>
parents: 4788
diff changeset
   258
	end
4631
fc5d3b053454 net.http.{server|codes|parser}: Initial commit.
Waqas Hussain <waqas20@gmail.com>
parents:
diff changeset
   259
10327
73938168681c net.http.server: Ensure HEAD requests are sent with empty body
Kim Alvefur <zash@zash.se>
parents: 9628
diff changeset
   260
	local is_head_request = request.method == "HEAD";
73938168681c net.http.server: Ensure HEAD requests are sent with empty body
Kim Alvefur <zash@zash.se>
parents: 9628
diff changeset
   261
4631
fc5d3b053454 net.http.{server|codes|parser}: Initial commit.
Waqas Hussain <waqas20@gmail.com>
parents:
diff changeset
   262
	local response = {
13104
18ffe7833446 net.http.server: Assign an ID to each request, shared with response
Kim Alvefur <zash@zash.se>
parents: 12978
diff changeset
   263
		id = request.id;
13105
c975dafa4303 net.http.server: Assign each request its own log source
Kim Alvefur <zash@zash.se>
parents: 13104
diff changeset
   264
		log = request.log;
4631
fc5d3b053454 net.http.{server|codes|parser}: Initial commit.
Waqas Hussain <waqas20@gmail.com>
parents:
diff changeset
   265
		request = request;
10327
73938168681c net.http.server: Ensure HEAD requests are sent with empty body
Kim Alvefur <zash@zash.se>
parents: 9628
diff changeset
   266
		is_head_request = is_head_request;
4631
fc5d3b053454 net.http.{server|codes|parser}: Initial commit.
Waqas Hussain <waqas20@gmail.com>
parents:
diff changeset
   267
		status_code = 200;
13122
6b5e92949051 net.http.server: Return request ID in header to aid debugging
Kim Alvefur <zash@zash.se>
parents: 13107
diff changeset
   268
		headers = { date = date_header; connection = response_conn_header; x_request_id = request.id };
5300
fcb1be0b4a5c net.http.server: Properly handle persistent connections
Florian Zeitz <florob@babelmonkeys.de>
parents: 4788
diff changeset
   269
		persistent = persistent;
4631
fc5d3b053454 net.http.{server|codes|parser}: Initial commit.
Waqas Hussain <waqas20@gmail.com>
parents:
diff changeset
   270
		conn = conn;
fc5d3b053454 net.http.{server|codes|parser}: Initial commit.
Waqas Hussain <waqas20@gmail.com>
parents:
diff changeset
   271
		send = _M.send_response;
11531
eaff6e548f12 net.http.server: Split out method for sending only the header
Kim Alvefur <zash@zash.se>
parents: 11413
diff changeset
   272
		write_headers = _M.write_headers;
7492
d32406f27efd net.http.server: Add response method for reading response body from a file handle
Kim Alvefur <zash@zash.se>
parents: 7087
diff changeset
   273
		send_file = _M.send_file;
6071
420c0d3b8583 net.http.server: Add prepare_header() and finish_response() to allow sending chunked responses via the API
Daurnimator <quae@daurnimator.com>
parents: 5776
diff changeset
   274
		done = _M.finish_response;
4631
fc5d3b053454 net.http.{server|codes|parser}: Initial commit.
Waqas Hussain <waqas20@gmail.com>
parents:
diff changeset
   275
		finish_cb = finish_cb;
fc5d3b053454 net.http.{server|codes|parser}: Initial commit.
Waqas Hussain <waqas20@gmail.com>
parents:
diff changeset
   276
	};
4691
a164fc7057ae net.http.server: Support for on_destroy callback on response objects, and a 'finished' flag to say when they are destroyed (responded to or connection closed)
Matthew Wild <mwild1@gmail.com>
parents: 4689
diff changeset
   277
	conn._http_open_response = response;
4631
fc5d3b053454 net.http.{server|codes|parser}: Initial commit.
Waqas Hussain <waqas20@gmail.com>
parents:
diff changeset
   278
10955
f4215f8baa5d net.http.server: Fix reporting of missing Host header
Kim Alvefur <zash@zash.se>
parents: 10954
diff changeset
   279
	local host = request.headers.host;
f4215f8baa5d net.http.server: Fix reporting of missing Host header
Kim Alvefur <zash@zash.se>
parents: 10954
diff changeset
   280
	if host then host = host:gsub(":%d+$",""); end
4736
3514338c59c3 net.http.server, mod_http: Support http_default_host config option to specify where to direct requests for unknown HTTP vhosts
Matthew Wild <mwild1@gmail.com>
parents: 4735
diff changeset
   281
3514338c59c3 net.http.server, mod_http: Support http_default_host config option to specify where to direct requests for unknown HTTP vhosts
Matthew Wild <mwild1@gmail.com>
parents: 4735
diff changeset
   282
	-- Some sanity checking
3514338c59c3 net.http.server, mod_http: Support http_default_host config option to specify where to direct requests for unknown HTTP vhosts
Matthew Wild <mwild1@gmail.com>
parents: 4735
diff changeset
   283
	local err_code, err;
4740
bd9c8bc8036f net.http.server: Try default_host if client sent no host anywhere, otherwise... fail. It's 2012.
Matthew Wild <mwild1@gmail.com>
parents: 4739
diff changeset
   284
	if not request.path then
4736
3514338c59c3 net.http.server, mod_http: Support http_default_host config option to specify where to direct requests for unknown HTTP vhosts
Matthew Wild <mwild1@gmail.com>
parents: 4735
diff changeset
   285
		err_code, err = 400, "Invalid path";
4713
9c15fa5192d3 net.http.server: Fire http-error 400 if request fails sanity checks
Matthew Wild <mwild1@gmail.com>
parents: 4710
diff changeset
   286
	end
5776
bd0ff8ae98a8 Remove all trailing whitespace
Florian Zeitz <florob@babelmonkeys.de>
parents: 5754
diff changeset
   287
4713
9c15fa5192d3 net.http.server: Fire http-error 400 if request fails sanity checks
Matthew Wild <mwild1@gmail.com>
parents: 4710
diff changeset
   288
	if err then
4736
3514338c59c3 net.http.server, mod_http: Support http_default_host config option to specify where to direct requests for unknown HTTP vhosts
Matthew Wild <mwild1@gmail.com>
parents: 4735
diff changeset
   289
		response.status_code = err_code;
8365
c7d6c2558a24 net.http.server: Include response object in most http-error events
Kim Alvefur <zash@zash.se>
parents: 7585
diff changeset
   290
		response:send(events.fire_event("http-error", { code = err_code, message = err, response = response }));
4736
3514338c59c3 net.http.server, mod_http: Support http_default_host config option to specify where to direct requests for unknown HTTP vhosts
Matthew Wild <mwild1@gmail.com>
parents: 4735
diff changeset
   291
		return;
3514338c59c3 net.http.server, mod_http: Support http_default_host config option to specify where to direct requests for unknown HTTP vhosts
Matthew Wild <mwild1@gmail.com>
parents: 4735
diff changeset
   292
	end
3514338c59c3 net.http.server, mod_http: Support http_default_host config option to specify where to direct requests for unknown HTTP vhosts
Matthew Wild <mwild1@gmail.com>
parents: 4735
diff changeset
   293
9378
816591db764d net.http.server: Fire an event without host
Kim Alvefur <zash@zash.se>
parents: 9341
diff changeset
   294
	local global_event = request.method.." "..request.path:match("[^?]*");
9382
866cba3689f4 net.http.server: Delay host checks until after host-less event
Kim Alvefur <zash@zash.se>
parents: 9378
diff changeset
   295
4736
3514338c59c3 net.http.server, mod_http: Support http_default_host config option to specify where to direct requests for unknown HTTP vhosts
Matthew Wild <mwild1@gmail.com>
parents: 4735
diff changeset
   296
	local payload = { request = request, response = response };
9378
816591db764d net.http.server: Fire an event without host
Kim Alvefur <zash@zash.se>
parents: 9341
diff changeset
   297
	local result = events.fire_event(global_event, payload);
10328
3f4c25425589 net.http.server: Re-fire unhandled HEAD requsts as GET events (fixes #1447)
Kim Alvefur <zash@zash.se>
parents: 10327
diff changeset
   298
	if result == nil and is_head_request then
3f4c25425589 net.http.server: Re-fire unhandled HEAD requsts as GET events (fixes #1447)
Kim Alvefur <zash@zash.se>
parents: 10327
diff changeset
   299
		local global_head_event = "GET "..request.path:match("[^?]*");
3f4c25425589 net.http.server: Re-fire unhandled HEAD requsts as GET events (fixes #1447)
Kim Alvefur <zash@zash.se>
parents: 10327
diff changeset
   300
		result = events.fire_event(global_head_event, payload);
3f4c25425589 net.http.server: Re-fire unhandled HEAD requsts as GET events (fixes #1447)
Kim Alvefur <zash@zash.se>
parents: 10327
diff changeset
   301
	end
9378
816591db764d net.http.server: Fire an event without host
Kim Alvefur <zash@zash.se>
parents: 9341
diff changeset
   302
	if result == nil then
9382
866cba3689f4 net.http.server: Delay host checks until after host-less event
Kim Alvefur <zash@zash.se>
parents: 9378
diff changeset
   303
		if not hosts[host] then
866cba3689f4 net.http.server: Delay host checks until after host-less event
Kim Alvefur <zash@zash.se>
parents: 9378
diff changeset
   304
			if hosts[default_host] then
866cba3689f4 net.http.server: Delay host checks until after host-less event
Kim Alvefur <zash@zash.se>
parents: 9378
diff changeset
   305
				host = default_host;
866cba3689f4 net.http.server: Delay host checks until after host-less event
Kim Alvefur <zash@zash.se>
parents: 9378
diff changeset
   306
			elseif host then
866cba3689f4 net.http.server: Delay host checks until after host-less event
Kim Alvefur <zash@zash.se>
parents: 9378
diff changeset
   307
				err_code, err = 404, "Unknown host: "..host;
866cba3689f4 net.http.server: Delay host checks until after host-less event
Kim Alvefur <zash@zash.se>
parents: 9378
diff changeset
   308
			else
866cba3689f4 net.http.server: Delay host checks until after host-less event
Kim Alvefur <zash@zash.se>
parents: 9378
diff changeset
   309
				err_code, err = 400, "Missing or invalid 'Host' header";
866cba3689f4 net.http.server: Delay host checks until after host-less event
Kim Alvefur <zash@zash.se>
parents: 9378
diff changeset
   310
			end
866cba3689f4 net.http.server: Delay host checks until after host-less event
Kim Alvefur <zash@zash.se>
parents: 9378
diff changeset
   311
		end
866cba3689f4 net.http.server: Delay host checks until after host-less event
Kim Alvefur <zash@zash.se>
parents: 9378
diff changeset
   312
866cba3689f4 net.http.server: Delay host checks until after host-less event
Kim Alvefur <zash@zash.se>
parents: 9378
diff changeset
   313
		if err then
866cba3689f4 net.http.server: Delay host checks until after host-less event
Kim Alvefur <zash@zash.se>
parents: 9378
diff changeset
   314
			response.status_code = err_code;
866cba3689f4 net.http.server: Delay host checks until after host-less event
Kim Alvefur <zash@zash.se>
parents: 9378
diff changeset
   315
			response:send(events.fire_event("http-error", { code = err_code, message = err, response = response }));
866cba3689f4 net.http.server: Delay host checks until after host-less event
Kim Alvefur <zash@zash.se>
parents: 9378
diff changeset
   316
			return;
866cba3689f4 net.http.server: Delay host checks until after host-less event
Kim Alvefur <zash@zash.se>
parents: 9378
diff changeset
   317
		end
866cba3689f4 net.http.server: Delay host checks until after host-less event
Kim Alvefur <zash@zash.se>
parents: 9378
diff changeset
   318
9628
cc9dff0212f4 net.http.server: Move event formation to avoid traceback on missing Host header
Matthew Wild <mwild1@gmail.com>
parents: 9565
diff changeset
   319
		local host_event = request.method.." "..host..request.path:match("[^?]*");
9378
816591db764d net.http.server: Fire an event without host
Kim Alvefur <zash@zash.se>
parents: 9341
diff changeset
   320
		result = events.fire_event(host_event, payload);
10328
3f4c25425589 net.http.server: Re-fire unhandled HEAD requsts as GET events (fixes #1447)
Kim Alvefur <zash@zash.se>
parents: 10327
diff changeset
   321
3f4c25425589 net.http.server: Re-fire unhandled HEAD requsts as GET events (fixes #1447)
Kim Alvefur <zash@zash.se>
parents: 10327
diff changeset
   322
		if result == nil and is_head_request then
3f4c25425589 net.http.server: Re-fire unhandled HEAD requsts as GET events (fixes #1447)
Kim Alvefur <zash@zash.se>
parents: 10327
diff changeset
   323
			local host_head_event = "GET "..host..request.path:match("[^?]*");
3f4c25425589 net.http.server: Re-fire unhandled HEAD requsts as GET events (fixes #1447)
Kim Alvefur <zash@zash.se>
parents: 10327
diff changeset
   324
			result = events.fire_event(host_head_event, payload);
4631
fc5d3b053454 net.http.{server|codes|parser}: Initial commit.
Waqas Hussain <waqas20@gmail.com>
parents:
diff changeset
   325
		end
4736
3514338c59c3 net.http.server, mod_http: Support http_default_host config option to specify where to direct requests for unknown HTTP vhosts
Matthew Wild <mwild1@gmail.com>
parents: 4735
diff changeset
   326
	end
4631
fc5d3b053454 net.http.{server|codes|parser}: Initial commit.
Waqas Hussain <waqas20@gmail.com>
parents:
diff changeset
   327
10396
7a95f27ac9d6 net.http.server: Factor out handling of event response for easier reuse
Kim Alvefur <zash@zash.se>
parents: 10330
diff changeset
   328
	return handle_result(request, response, result);
4631
fc5d3b053454 net.http.{server|codes|parser}: Initial commit.
Waqas Hussain <waqas20@gmail.com>
parents:
diff changeset
   329
end
10396
7a95f27ac9d6 net.http.server: Factor out handling of event response for easier reuse
Kim Alvefur <zash@zash.se>
parents: 10330
diff changeset
   330
6071
420c0d3b8583 net.http.server: Add prepare_header() and finish_response() to allow sending chunked responses via the API
Daurnimator <quae@daurnimator.com>
parents: 5776
diff changeset
   331
local function prepare_header(response)
4631
fc5d3b053454 net.http.{server|codes|parser}: Initial commit.
Waqas Hussain <waqas20@gmail.com>
parents:
diff changeset
   332
	local status_line = "HTTP/"..response.request.httpversion.." "..(response.status or codes[response.status_code]);
13106
4e112b87543d net.http.server: Log request and response status lines
Kim Alvefur <zash@zash.se>
parents: 13105
diff changeset
   333
	response.log("debug", "%s", status_line);
4631
fc5d3b053454 net.http.{server|codes|parser}: Initial commit.
Waqas Hussain <waqas20@gmail.com>
parents:
diff changeset
   334
	local headers = response.headers;
fc5d3b053454 net.http.{server|codes|parser}: Initial commit.
Waqas Hussain <waqas20@gmail.com>
parents:
diff changeset
   335
	local output = { status_line };
fc5d3b053454 net.http.{server|codes|parser}: Initial commit.
Waqas Hussain <waqas20@gmail.com>
parents:
diff changeset
   336
	for k,v in pairs(headers) do
fc5d3b053454 net.http.{server|codes|parser}: Initial commit.
Waqas Hussain <waqas20@gmail.com>
parents:
diff changeset
   337
		t_insert(output, headerfix[k]..v);
fc5d3b053454 net.http.{server|codes|parser}: Initial commit.
Waqas Hussain <waqas20@gmail.com>
parents:
diff changeset
   338
	end
fc5d3b053454 net.http.{server|codes|parser}: Initial commit.
Waqas Hussain <waqas20@gmail.com>
parents:
diff changeset
   339
	t_insert(output, "\r\n\r\n");
6071
420c0d3b8583 net.http.server: Add prepare_header() and finish_response() to allow sending chunked responses via the API
Daurnimator <quae@daurnimator.com>
parents: 5776
diff changeset
   340
	return output;
420c0d3b8583 net.http.server: Add prepare_header() and finish_response() to allow sending chunked responses via the API
Daurnimator <quae@daurnimator.com>
parents: 5776
diff changeset
   341
end
420c0d3b8583 net.http.server: Add prepare_header() and finish_response() to allow sending chunked responses via the API
Daurnimator <quae@daurnimator.com>
parents: 5776
diff changeset
   342
_M.prepare_header = prepare_header;
11531
eaff6e548f12 net.http.server: Split out method for sending only the header
Kim Alvefur <zash@zash.se>
parents: 11413
diff changeset
   343
function _M.write_headers(response)
10327
73938168681c net.http.server: Ensure HEAD requests are sent with empty body
Kim Alvefur <zash@zash.se>
parents: 9628
diff changeset
   344
	if response.finished then return; end
73938168681c net.http.server: Ensure HEAD requests are sent with empty body
Kim Alvefur <zash@zash.se>
parents: 9628
diff changeset
   345
	local output = prepare_header(response);
73938168681c net.http.server: Ensure HEAD requests are sent with empty body
Kim Alvefur <zash@zash.se>
parents: 9628
diff changeset
   346
	response.conn:write(t_concat(output));
11531
eaff6e548f12 net.http.server: Split out method for sending only the header
Kim Alvefur <zash@zash.se>
parents: 11413
diff changeset
   347
end
eaff6e548f12 net.http.server: Split out method for sending only the header
Kim Alvefur <zash@zash.se>
parents: 11413
diff changeset
   348
function _M.send_head_response(response)
eaff6e548f12 net.http.server: Split out method for sending only the header
Kim Alvefur <zash@zash.se>
parents: 11413
diff changeset
   349
	if response.finished then return; end
eaff6e548f12 net.http.server: Split out method for sending only the header
Kim Alvefur <zash@zash.se>
parents: 11413
diff changeset
   350
	_M.write_headers(response);
10327
73938168681c net.http.server: Ensure HEAD requests are sent with empty body
Kim Alvefur <zash@zash.se>
parents: 9628
diff changeset
   351
	response:done();
73938168681c net.http.server: Ensure HEAD requests are sent with empty body
Kim Alvefur <zash@zash.se>
parents: 9628
diff changeset
   352
end
6071
420c0d3b8583 net.http.server: Add prepare_header() and finish_response() to allow sending chunked responses via the API
Daurnimator <quae@daurnimator.com>
parents: 5776
diff changeset
   353
function _M.send_response(response, body)
420c0d3b8583 net.http.server: Add prepare_header() and finish_response() to allow sending chunked responses via the API
Daurnimator <quae@daurnimator.com>
parents: 5776
diff changeset
   354
	if response.finished then return; end
420c0d3b8583 net.http.server: Add prepare_header() and finish_response() to allow sending chunked responses via the API
Daurnimator <quae@daurnimator.com>
parents: 5776
diff changeset
   355
	body = body or response.body or "";
11163
de76f566159e net.http.server: Don't send Content-Length on 1xx/204 responses, per RFC (fixes #1596)
Matthew Wild <mwild1@gmail.com>
parents: 10955
diff changeset
   356
	-- Per RFC 7230, informational (1xx) and 204 (no content) should have no c-l header
de76f566159e net.http.server: Don't send Content-Length on 1xx/204 responses, per RFC (fixes #1596)
Matthew Wild <mwild1@gmail.com>
parents: 10955
diff changeset
   357
	if response.status_code > 199 and response.status_code ~= 204 then
11164
e9eeaefa09a7 Merge 0.11->trunk
Matthew Wild <mwild1@gmail.com>
parents: 11100 11163
diff changeset
   358
		response.headers.content_length = ("%d"):format(#body);
e9eeaefa09a7 Merge 0.11->trunk
Matthew Wild <mwild1@gmail.com>
parents: 11100 11163
diff changeset
   359
	end
10327
73938168681c net.http.server: Ensure HEAD requests are sent with empty body
Kim Alvefur <zash@zash.se>
parents: 9628
diff changeset
   360
	if response.is_head_request then
73938168681c net.http.server: Ensure HEAD requests are sent with empty body
Kim Alvefur <zash@zash.se>
parents: 9628
diff changeset
   361
		return _M.send_head_response(response)
11163
de76f566159e net.http.server: Don't send Content-Length on 1xx/204 responses, per RFC (fixes #1596)
Matthew Wild <mwild1@gmail.com>
parents: 10955
diff changeset
   362
	end
6082
d0e824a21861 net.http.server: Fix some typos introduced in 420c0d3b8583.
Daurnimator <quae@daurnimator.com>
parents: 6071
diff changeset
   363
	local output = prepare_header(response);
4631
fc5d3b053454 net.http.{server|codes|parser}: Initial commit.
Waqas Hussain <waqas20@gmail.com>
parents:
diff changeset
   364
	t_insert(output, body);
fc5d3b053454 net.http.{server|codes|parser}: Initial commit.
Waqas Hussain <waqas20@gmail.com>
parents:
diff changeset
   365
	response.conn:write(t_concat(output));
6082
d0e824a21861 net.http.server: Fix some typos introduced in 420c0d3b8583.
Daurnimator <quae@daurnimator.com>
parents: 6071
diff changeset
   366
	response:done();
6071
420c0d3b8583 net.http.server: Add prepare_header() and finish_response() to allow sending chunked responses via the API
Daurnimator <quae@daurnimator.com>
parents: 5776
diff changeset
   367
end
7492
d32406f27efd net.http.server: Add response method for reading response body from a file handle
Kim Alvefur <zash@zash.se>
parents: 7087
diff changeset
   368
function _M.send_file(response, f)
10327
73938168681c net.http.server: Ensure HEAD requests are sent with empty body
Kim Alvefur <zash@zash.se>
parents: 9628
diff changeset
   369
	if response.is_head_request then
73938168681c net.http.server: Ensure HEAD requests are sent with empty body
Kim Alvefur <zash@zash.se>
parents: 9628
diff changeset
   370
		if f.close then f:close(); end
73938168681c net.http.server: Ensure HEAD requests are sent with empty body
Kim Alvefur <zash@zash.se>
parents: 9628
diff changeset
   371
		return _M.send_head_response(response);
73938168681c net.http.server: Ensure HEAD requests are sent with empty body
Kim Alvefur <zash@zash.se>
parents: 9628
diff changeset
   372
	end
7492
d32406f27efd net.http.server: Add response method for reading response body from a file handle
Kim Alvefur <zash@zash.se>
parents: 7087
diff changeset
   373
	if response.finished then return; end
d32406f27efd net.http.server: Add response method for reading response body from a file handle
Kim Alvefur <zash@zash.se>
parents: 7087
diff changeset
   374
	local chunked = not response.headers.content_length;
d32406f27efd net.http.server: Add response method for reading response body from a file handle
Kim Alvefur <zash@zash.se>
parents: 7087
diff changeset
   375
	if chunked then response.headers.transfer_encoding = "chunked"; end
d32406f27efd net.http.server: Add response method for reading response body from a file handle
Kim Alvefur <zash@zash.se>
parents: 7087
diff changeset
   376
	incomplete[response.conn] = response;
d32406f27efd net.http.server: Add response method for reading response body from a file handle
Kim Alvefur <zash@zash.se>
parents: 7087
diff changeset
   377
	response._send_more = function ()
d32406f27efd net.http.server: Add response method for reading response body from a file handle
Kim Alvefur <zash@zash.se>
parents: 7087
diff changeset
   378
		if response.finished then
d32406f27efd net.http.server: Add response method for reading response body from a file handle
Kim Alvefur <zash@zash.se>
parents: 7087
diff changeset
   379
			incomplete[response.conn] = nil;
d32406f27efd net.http.server: Add response method for reading response body from a file handle
Kim Alvefur <zash@zash.se>
parents: 7087
diff changeset
   380
			return;
d32406f27efd net.http.server: Add response method for reading response body from a file handle
Kim Alvefur <zash@zash.se>
parents: 7087
diff changeset
   381
		end
d32406f27efd net.http.server: Add response method for reading response body from a file handle
Kim Alvefur <zash@zash.se>
parents: 7087
diff changeset
   382
		local chunk = f:read(blocksize);
d32406f27efd net.http.server: Add response method for reading response body from a file handle
Kim Alvefur <zash@zash.se>
parents: 7087
diff changeset
   383
		if chunk then
d32406f27efd net.http.server: Add response method for reading response body from a file handle
Kim Alvefur <zash@zash.se>
parents: 7087
diff changeset
   384
			if chunked then
d32406f27efd net.http.server: Add response method for reading response body from a file handle
Kim Alvefur <zash@zash.se>
parents: 7087
diff changeset
   385
				chunk = ("%x\r\n%s\r\n"):format(#chunk, chunk);
d32406f27efd net.http.server: Add response method for reading response body from a file handle
Kim Alvefur <zash@zash.se>
parents: 7087
diff changeset
   386
			end
d32406f27efd net.http.server: Add response method for reading response body from a file handle
Kim Alvefur <zash@zash.se>
parents: 7087
diff changeset
   387
			-- io.write("."); io.flush();
d32406f27efd net.http.server: Add response method for reading response body from a file handle
Kim Alvefur <zash@zash.se>
parents: 7087
diff changeset
   388
			response.conn:write(chunk);
d32406f27efd net.http.server: Add response method for reading response body from a file handle
Kim Alvefur <zash@zash.se>
parents: 7087
diff changeset
   389
		else
12835
1cdaf21584da net.http.server: Fix #1789
Kim Alvefur <zash@zash.se>
parents: 11531
diff changeset
   390
			incomplete[response.conn] = nil;
12890
686c3cdd4775 Merge 0.12->trunk
Matthew Wild <mwild1@gmail.com>
parents: 12889
diff changeset
   391
			if f.close then f:close(); end
7492
d32406f27efd net.http.server: Add response method for reading response body from a file handle
Kim Alvefur <zash@zash.se>
parents: 7087
diff changeset
   392
			if chunked then
d32406f27efd net.http.server: Add response method for reading response body from a file handle
Kim Alvefur <zash@zash.se>
parents: 7087
diff changeset
   393
				response.conn:write("0\r\n\r\n");
d32406f27efd net.http.server: Add response method for reading response body from a file handle
Kim Alvefur <zash@zash.se>
parents: 7087
diff changeset
   394
			end
d32406f27efd net.http.server: Add response method for reading response body from a file handle
Kim Alvefur <zash@zash.se>
parents: 7087
diff changeset
   395
			-- io.write("\n");
d32406f27efd net.http.server: Add response method for reading response body from a file handle
Kim Alvefur <zash@zash.se>
parents: 7087
diff changeset
   396
			return response:done();
d32406f27efd net.http.server: Add response method for reading response body from a file handle
Kim Alvefur <zash@zash.se>
parents: 7087
diff changeset
   397
		end
d32406f27efd net.http.server: Add response method for reading response body from a file handle
Kim Alvefur <zash@zash.se>
parents: 7087
diff changeset
   398
	end
11531
eaff6e548f12 net.http.server: Split out method for sending only the header
Kim Alvefur <zash@zash.se>
parents: 11413
diff changeset
   399
	_M.write_headers(response);
7492
d32406f27efd net.http.server: Add response method for reading response body from a file handle
Kim Alvefur <zash@zash.se>
parents: 7087
diff changeset
   400
	return true;
d32406f27efd net.http.server: Add response method for reading response body from a file handle
Kim Alvefur <zash@zash.se>
parents: 7087
diff changeset
   401
end
6071
420c0d3b8583 net.http.server: Add prepare_header() and finish_response() to allow sending chunked responses via the API
Daurnimator <quae@daurnimator.com>
parents: 5776
diff changeset
   402
function _M.finish_response(response)
420c0d3b8583 net.http.server: Add prepare_header() and finish_response() to allow sending chunked responses via the API
Daurnimator <quae@daurnimator.com>
parents: 5776
diff changeset
   403
	if response.finished then return; end
420c0d3b8583 net.http.server: Add prepare_header() and finish_response() to allow sending chunked responses via the API
Daurnimator <quae@daurnimator.com>
parents: 5776
diff changeset
   404
	response.finished = true;
420c0d3b8583 net.http.server: Add prepare_header() and finish_response() to allow sending chunked responses via the API
Daurnimator <quae@daurnimator.com>
parents: 5776
diff changeset
   405
	response.conn._http_open_response = nil;
4691
a164fc7057ae net.http.server: Support for on_destroy callback on response objects, and a 'finished' flag to say when they are destroyed (responded to or connection closed)
Matthew Wild <mwild1@gmail.com>
parents: 4689
diff changeset
   406
	if response.on_destroy then
a164fc7057ae net.http.server: Support for on_destroy callback on response objects, and a 'finished' flag to say when they are destroyed (responded to or connection closed)
Matthew Wild <mwild1@gmail.com>
parents: 4689
diff changeset
   407
		response:on_destroy();
a164fc7057ae net.http.server: Support for on_destroy callback on response objects, and a 'finished' flag to say when they are destroyed (responded to or connection closed)
Matthew Wild <mwild1@gmail.com>
parents: 4689
diff changeset
   408
		response.on_destroy = nil;
a164fc7057ae net.http.server: Support for on_destroy callback on response objects, and a 'finished' flag to say when they are destroyed (responded to or connection closed)
Matthew Wild <mwild1@gmail.com>
parents: 4689
diff changeset
   409
	end
13345
407174990ab0 net.http.server: Complete async waiter for non-persistent connections
Kim Alvefur <zash@zash.se>
parents: 13265
diff changeset
   410
	response:finish_cb();
407174990ab0 net.http.server: Complete async waiter for non-persistent connections
Kim Alvefur <zash@zash.se>
parents: 13265
diff changeset
   411
	if not response.persistent then
4631
fc5d3b053454 net.http.{server|codes|parser}: Initial commit.
Waqas Hussain <waqas20@gmail.com>
parents:
diff changeset
   412
		response.conn:close();
fc5d3b053454 net.http.{server|codes|parser}: Initial commit.
Waqas Hussain <waqas20@gmail.com>
parents:
diff changeset
   413
	end
fc5d3b053454 net.http.{server|codes|parser}: Initial commit.
Waqas Hussain <waqas20@gmail.com>
parents:
diff changeset
   414
end
fc5d3b053454 net.http.{server|codes|parser}: Initial commit.
Waqas Hussain <waqas20@gmail.com>
parents:
diff changeset
   415
function _M.add_handler(event, handler, priority)
fc5d3b053454 net.http.{server|codes|parser}: Initial commit.
Waqas Hussain <waqas20@gmail.com>
parents:
diff changeset
   416
	events.add_handler(event, handler, priority);
fc5d3b053454 net.http.{server|codes|parser}: Initial commit.
Waqas Hussain <waqas20@gmail.com>
parents:
diff changeset
   417
end
fc5d3b053454 net.http.{server|codes|parser}: Initial commit.
Waqas Hussain <waqas20@gmail.com>
parents:
diff changeset
   418
function _M.remove_handler(event, handler)
fc5d3b053454 net.http.{server|codes|parser}: Initial commit.
Waqas Hussain <waqas20@gmail.com>
parents:
diff changeset
   419
	events.remove_handler(event, handler);
fc5d3b053454 net.http.{server|codes|parser}: Initial commit.
Waqas Hussain <waqas20@gmail.com>
parents:
diff changeset
   420
end
fc5d3b053454 net.http.{server|codes|parser}: Initial commit.
Waqas Hussain <waqas20@gmail.com>
parents:
diff changeset
   421
fc5d3b053454 net.http.{server|codes|parser}: Initial commit.
Waqas Hussain <waqas20@gmail.com>
parents:
diff changeset
   422
function _M.listen_on(port, interface, ssl)
7087
fdbe9ccac17d net.http.server: Return from listen_on() whatever net.server.addserver() returns
Kim Alvefur <zash@zash.se>
parents: 6966
diff changeset
   423
	return addserver(interface or "*", port, listener, "*a", ssl);
4631
fc5d3b053454 net.http.{server|codes|parser}: Initial commit.
Waqas Hussain <waqas20@gmail.com>
parents:
diff changeset
   424
end
4736
3514338c59c3 net.http.server, mod_http: Support http_default_host config option to specify where to direct requests for unknown HTTP vhosts
Matthew Wild <mwild1@gmail.com>
parents: 4735
diff changeset
   425
function _M.add_host(host)
3514338c59c3 net.http.server, mod_http: Support http_default_host config option to specify where to direct requests for unknown HTTP vhosts
Matthew Wild <mwild1@gmail.com>
parents: 4735
diff changeset
   426
	hosts[host] = true;
3514338c59c3 net.http.server, mod_http: Support http_default_host config option to specify where to direct requests for unknown HTTP vhosts
Matthew Wild <mwild1@gmail.com>
parents: 4735
diff changeset
   427
end
3514338c59c3 net.http.server, mod_http: Support http_default_host config option to specify where to direct requests for unknown HTTP vhosts
Matthew Wild <mwild1@gmail.com>
parents: 4735
diff changeset
   428
function _M.remove_host(host)
3514338c59c3 net.http.server, mod_http: Support http_default_host config option to specify where to direct requests for unknown HTTP vhosts
Matthew Wild <mwild1@gmail.com>
parents: 4735
diff changeset
   429
	hosts[host] = nil;
3514338c59c3 net.http.server, mod_http: Support http_default_host config option to specify where to direct requests for unknown HTTP vhosts
Matthew Wild <mwild1@gmail.com>
parents: 4735
diff changeset
   430
end
3514338c59c3 net.http.server, mod_http: Support http_default_host config option to specify where to direct requests for unknown HTTP vhosts
Matthew Wild <mwild1@gmail.com>
parents: 4735
diff changeset
   431
function _M.set_default_host(host)
3514338c59c3 net.http.server, mod_http: Support http_default_host config option to specify where to direct requests for unknown HTTP vhosts
Matthew Wild <mwild1@gmail.com>
parents: 4735
diff changeset
   432
	default_host = host;
3514338c59c3 net.http.server, mod_http: Support http_default_host config option to specify where to direct requests for unknown HTTP vhosts
Matthew Wild <mwild1@gmail.com>
parents: 4735
diff changeset
   433
end
5439
bd7b314c2301 net.http.server: add API to allow firing events directly on the server.
Marco Cirillo <maranda@lightwitch.org>
parents: 5404
diff changeset
   434
function _M.fire_event(event, ...)
bd7b314c2301 net.http.server: add API to allow firing events directly on the server.
Marco Cirillo <maranda@lightwitch.org>
parents: 5404
diff changeset
   435
	return events.fire_event(event, ...);
bd7b314c2301 net.http.server: add API to allow firing events directly on the server.
Marco Cirillo <maranda@lightwitch.org>
parents: 5404
diff changeset
   436
end
7582
d430573fe9f8 net.http.server: Expose way to set http server options
Kim Alvefur <zash@zash.se>
parents: 6592
diff changeset
   437
function _M.set_option(name, value)
d430573fe9f8 net.http.server: Expose way to set http server options
Kim Alvefur <zash@zash.se>
parents: 6592
diff changeset
   438
	options[name] = value;
d430573fe9f8 net.http.server: Expose way to set http server options
Kim Alvefur <zash@zash.se>
parents: 6592
diff changeset
   439
end
12889
3a6dae39c70e net.http.server: Add new API to get HTTP request from a connection
Matthew Wild <mwild1@gmail.com>
parents: 12835
diff changeset
   440
function _M.get_request_from_conn(conn)
3a6dae39c70e net.http.server: Add new API to get HTTP request from a connection
Matthew Wild <mwild1@gmail.com>
parents: 12835
diff changeset
   441
	local response = conn and conn._http_open_response;
3a6dae39c70e net.http.server: Add new API to get HTTP request from a connection
Matthew Wild <mwild1@gmail.com>
parents: 12835
diff changeset
   442
	return response and response.request or nil;
3a6dae39c70e net.http.server: Add new API to get HTTP request from a connection
Matthew Wild <mwild1@gmail.com>
parents: 12835
diff changeset
   443
end
4631
fc5d3b053454 net.http.{server|codes|parser}: Initial commit.
Waqas Hussain <waqas20@gmail.com>
parents:
diff changeset
   444
fc5d3b053454 net.http.{server|codes|parser}: Initial commit.
Waqas Hussain <waqas20@gmail.com>
parents:
diff changeset
   445
_M.listener = listener;
fc5d3b053454 net.http.{server|codes|parser}: Initial commit.
Waqas Hussain <waqas20@gmail.com>
parents:
diff changeset
   446
_M.codes = codes;
4706
845393c76d17 net.http.server: Expose events object (for debug purposes)
Matthew Wild <mwild1@gmail.com>
parents: 4704
diff changeset
   447
_M._events = events;
4631
fc5d3b053454 net.http.{server|codes|parser}: Initial commit.
Waqas Hussain <waqas20@gmail.com>
parents:
diff changeset
   448
return _M;