net/http/server.lua
author Kim Alvefur <zash@zash.se>
Thu, 28 Mar 2024 15:26:57 +0100
changeset 13472 98806cac64c3
parent 13384 d53dd83a9944
permissions -rw-r--r--
MUC: Switch to official XEP-0317 namespace for Hats (including compat) (thanks nicoco)
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;