Annotate

net/http/parser.lua @ 13627:2db7b3b65363

core.configmanager: Add function for getting secrets from separate files Idea is to enable easily retrieving of secret values from files outside of the config, e.g. via the method used by systemd credentials. CREDENTIALS_DIRECTORY is expected to be set by the process manager invoking Prosody, so being unset and unavailable from prosodyctl is going to be normal and a warning is reported in that case. Care will have to be taken to make it clear that prosodyctl check will not work with such values. An error is thrown if the directory is unavailable when running under Prosody.
author Kim Alvefur <zash@zash.se>
date Thu, 16 Jan 2025 15:21:34 +0100
parent 13379:977d92aff563
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
4631
fc5d3b053454 net.http.{server|codes|parser}: Initial commit.
Waqas Hussain <waqas20@gmail.com>
parents:
diff changeset
1 local tonumber = tonumber;
fc5d3b053454 net.http.{server|codes|parser}: Initial commit.
Waqas Hussain <waqas20@gmail.com>
parents:
diff changeset
2 local assert = assert;
4866
d54999db3aa1 net.http.parser: Do full URL decoding and parsing (e.g. adds request.url.query when present)
Matthew Wild <mwild1@gmail.com>
parents: 4716
diff changeset
3 local url_parse = require "socket.url".parse;
12974
ba409c67353b net: Prefix module imports with prosody namespace
Kim Alvefur <zash@zash.se>
parents: 12889
diff changeset
4 local urldecode = require "prosody.util.http".urldecode;
ba409c67353b net: Prefix module imports with prosody namespace
Kim Alvefur <zash@zash.se>
parents: 12889
diff changeset
5 local dbuffer = require "prosody.util.dbuffer";
4631
fc5d3b053454 net.http.{server|codes|parser}: Initial commit.
Waqas Hussain <waqas20@gmail.com>
parents:
diff changeset
6
4716
6eeb142a8073 mod_http_files, net.http.parser: Move path normalization to net.http.parser so that all modules can benefit
Matthew Wild <mwild1@gmail.com>
parents: 4712
diff changeset
7 local function preprocess_path(path)
5222
61c47d26481d net.http.parser: Fix syntax error introduced in c5edb08fc7cb.
Waqas Hussain <waqas20@gmail.com>
parents: 5207
diff changeset
8 path = urldecode((path:gsub("//+", "/")));
4716
6eeb142a8073 mod_http_files, net.http.parser: Move path normalization to net.http.parser so that all modules can benefit
Matthew Wild <mwild1@gmail.com>
parents: 4712
diff changeset
9 if path:sub(1,1) ~= "/" then
6eeb142a8073 mod_http_files, net.http.parser: Move path normalization to net.http.parser so that all modules can benefit
Matthew Wild <mwild1@gmail.com>
parents: 4712
diff changeset
10 path = "/"..path;
6eeb142a8073 mod_http_files, net.http.parser: Move path normalization to net.http.parser so that all modules can benefit
Matthew Wild <mwild1@gmail.com>
parents: 4712
diff changeset
11 end
6eeb142a8073 mod_http_files, net.http.parser: Move path normalization to net.http.parser so that all modules can benefit
Matthew Wild <mwild1@gmail.com>
parents: 4712
diff changeset
12 local level = 0;
6eeb142a8073 mod_http_files, net.http.parser: Move path normalization to net.http.parser so that all modules can benefit
Matthew Wild <mwild1@gmail.com>
parents: 4712
diff changeset
13 for component in path:gmatch("([^/]+)/") do
6eeb142a8073 mod_http_files, net.http.parser: Move path normalization to net.http.parser so that all modules can benefit
Matthew Wild <mwild1@gmail.com>
parents: 4712
diff changeset
14 if component == ".." then
6eeb142a8073 mod_http_files, net.http.parser: Move path normalization to net.http.parser so that all modules can benefit
Matthew Wild <mwild1@gmail.com>
parents: 4712
diff changeset
15 level = level - 1;
6eeb142a8073 mod_http_files, net.http.parser: Move path normalization to net.http.parser so that all modules can benefit
Matthew Wild <mwild1@gmail.com>
parents: 4712
diff changeset
16 elseif component ~= "." then
6eeb142a8073 mod_http_files, net.http.parser: Move path normalization to net.http.parser so that all modules can benefit
Matthew Wild <mwild1@gmail.com>
parents: 4712
diff changeset
17 level = level + 1;
6eeb142a8073 mod_http_files, net.http.parser: Move path normalization to net.http.parser so that all modules can benefit
Matthew Wild <mwild1@gmail.com>
parents: 4712
diff changeset
18 end
6eeb142a8073 mod_http_files, net.http.parser: Move path normalization to net.http.parser so that all modules can benefit
Matthew Wild <mwild1@gmail.com>
parents: 4712
diff changeset
19 if level < 0 then
6eeb142a8073 mod_http_files, net.http.parser: Move path normalization to net.http.parser so that all modules can benefit
Matthew Wild <mwild1@gmail.com>
parents: 4712
diff changeset
20 return nil;
6eeb142a8073 mod_http_files, net.http.parser: Move path normalization to net.http.parser so that all modules can benefit
Matthew Wild <mwild1@gmail.com>
parents: 4712
diff changeset
21 end
6eeb142a8073 mod_http_files, net.http.parser: Move path normalization to net.http.parser so that all modules can benefit
Matthew Wild <mwild1@gmail.com>
parents: 4712
diff changeset
22 end
6eeb142a8073 mod_http_files, net.http.parser: Move path normalization to net.http.parser so that all modules can benefit
Matthew Wild <mwild1@gmail.com>
parents: 4712
diff changeset
23 return path;
6eeb142a8073 mod_http_files, net.http.parser: Move path normalization to net.http.parser so that all modules can benefit
Matthew Wild <mwild1@gmail.com>
parents: 4712
diff changeset
24 end
6eeb142a8073 mod_http_files, net.http.parser: Move path normalization to net.http.parser so that all modules can benefit
Matthew Wild <mwild1@gmail.com>
parents: 4712
diff changeset
25
4631
fc5d3b053454 net.http.{server|codes|parser}: Initial commit.
Waqas Hussain <waqas20@gmail.com>
parents:
diff changeset
26 local httpstream = {};
fc5d3b053454 net.http.{server|codes|parser}: Initial commit.
Waqas Hussain <waqas20@gmail.com>
parents:
diff changeset
27
fc5d3b053454 net.http.{server|codes|parser}: Initial commit.
Waqas Hussain <waqas20@gmail.com>
parents:
diff changeset
28 function httpstream.new(success_cb, error_cb, parser_type, options_cb)
fc5d3b053454 net.http.{server|codes|parser}: Initial commit.
Waqas Hussain <waqas20@gmail.com>
parents:
diff changeset
29 local client = true;
fc5d3b053454 net.http.{server|codes|parser}: Initial commit.
Waqas Hussain <waqas20@gmail.com>
parents:
diff changeset
30 if not parser_type or parser_type == "server" then client = false; else assert(parser_type == "client", "Invalid parser type"); end
7578
65bf55fdf971 net.http.parser: Allow limits to be configurable via options callback
Kim Alvefur <zash@zash.se>
parents: 7577
diff changeset
31 local bodylimit = tonumber(options_cb and options_cb().body_size_limit) or 10*1024*1024;
11020
7076ed654ac9 net.http.parser: Switch to util.dbuffer for buffering incoming data
Kim Alvefur <zash@zash.se>
parents: 10580
diff changeset
32 -- https://stackoverflow.com/a/686243
11727
f3aee8a825cc Fix various spelling errors (thanks codespell)
Kim Alvefur <zash@zash.se>
parents: 11184
diff changeset
33 -- Individual headers can be up to 16k? What madness?
11020
7076ed654ac9 net.http.parser: Switch to util.dbuffer for buffering incoming data
Kim Alvefur <zash@zash.se>
parents: 10580
diff changeset
34 local headlimit = tonumber(options_cb and options_cb().head_size_limit) or 10*1024;
7578
65bf55fdf971 net.http.parser: Allow limits to be configurable via options callback
Kim Alvefur <zash@zash.se>
parents: 7577
diff changeset
35 local buflimit = tonumber(options_cb and options_cb().buffer_size_limit) or bodylimit * 2;
11020
7076ed654ac9 net.http.parser: Switch to util.dbuffer for buffering incoming data
Kim Alvefur <zash@zash.se>
parents: 10580
diff changeset
36 local buffer = dbuffer.new(buflimit);
7076ed654ac9 net.http.parser: Switch to util.dbuffer for buffering incoming data
Kim Alvefur <zash@zash.se>
parents: 10580
diff changeset
37 local chunked;
4631
fc5d3b053454 net.http.{server|codes|parser}: Initial commit.
Waqas Hussain <waqas20@gmail.com>
parents:
diff changeset
38 local state = nil;
fc5d3b053454 net.http.{server|codes|parser}: Initial commit.
Waqas Hussain <waqas20@gmail.com>
parents:
diff changeset
39 local packet;
fc5d3b053454 net.http.{server|codes|parser}: Initial commit.
Waqas Hussain <waqas20@gmail.com>
parents:
diff changeset
40 local len;
fc5d3b053454 net.http.{server|codes|parser}: Initial commit.
Waqas Hussain <waqas20@gmail.com>
parents:
diff changeset
41 local have_body;
fc5d3b053454 net.http.{server|codes|parser}: Initial commit.
Waqas Hussain <waqas20@gmail.com>
parents:
diff changeset
42 local error;
fc5d3b053454 net.http.{server|codes|parser}: Initial commit.
Waqas Hussain <waqas20@gmail.com>
parents:
diff changeset
43 return {
7569
a15ce0014ac9 net.http.parser: Remove unused argument [luacheck]
Kim Alvefur <zash@zash.se>
parents: 6523
diff changeset
44 feed = function(_, data)
4631
fc5d3b053454 net.http.{server|codes|parser}: Initial commit.
Waqas Hussain <waqas20@gmail.com>
parents:
diff changeset
45 if error then return nil, "parse has failed"; end
fc5d3b053454 net.http.{server|codes|parser}: Initial commit.
Waqas Hussain <waqas20@gmail.com>
parents:
diff changeset
46 if not data then -- EOF
fc5d3b053454 net.http.{server|codes|parser}: Initial commit.
Waqas Hussain <waqas20@gmail.com>
parents:
diff changeset
47 if state and client and not len then -- reading client body until EOF
11020
7076ed654ac9 net.http.parser: Switch to util.dbuffer for buffering incoming data
Kim Alvefur <zash@zash.se>
parents: 10580
diff changeset
48 buffer:collapse();
7076ed654ac9 net.http.parser: Switch to util.dbuffer for buffering incoming data
Kim Alvefur <zash@zash.se>
parents: 10580
diff changeset
49 packet.body = buffer:read_chunk() or "";
11184
2ede7f43ccfe net.http.parser: Expose 'partial', 'chunked' and 'body_length' on packets
Matthew Wild <mwild1@gmail.com>
parents: 11029
diff changeset
50 packet.partial = nil;
4631
fc5d3b053454 net.http.{server|codes|parser}: Initial commit.
Waqas Hussain <waqas20@gmail.com>
parents:
diff changeset
51 success_cb(packet);
11020
7076ed654ac9 net.http.parser: Switch to util.dbuffer for buffering incoming data
Kim Alvefur <zash@zash.se>
parents: 10580
diff changeset
52 state = nil;
7076ed654ac9 net.http.parser: Switch to util.dbuffer for buffering incoming data
Kim Alvefur <zash@zash.se>
parents: 10580
diff changeset
53 elseif buffer:length() ~= 0 then -- unexpected EOF
8045
55a56dc935f2 net.http: Pass error all the way to callback
Kim Alvefur <zash@zash.se>
parents: 7635
diff changeset
54 error = true; return error_cb("unexpected-eof");
4631
fc5d3b053454 net.http.{server|codes|parser}: Initial commit.
Waqas Hussain <waqas20@gmail.com>
parents:
diff changeset
55 end
fc5d3b053454 net.http.{server|codes|parser}: Initial commit.
Waqas Hussain <waqas20@gmail.com>
parents:
diff changeset
56 return;
fc5d3b053454 net.http.{server|codes|parser}: Initial commit.
Waqas Hussain <waqas20@gmail.com>
parents:
diff changeset
57 end
11020
7076ed654ac9 net.http.parser: Switch to util.dbuffer for buffering incoming data
Kim Alvefur <zash@zash.se>
parents: 10580
diff changeset
58 if not buffer:write(data) then error = true; return error_cb("max-buffer-size-exceeded"); end
7076ed654ac9 net.http.parser: Switch to util.dbuffer for buffering incoming data
Kim Alvefur <zash@zash.se>
parents: 10580
diff changeset
59 while buffer:length() > 0 do
4631
fc5d3b053454 net.http.{server|codes|parser}: Initial commit.
Waqas Hussain <waqas20@gmail.com>
parents:
diff changeset
60 if state == nil then -- read request
11020
7076ed654ac9 net.http.parser: Switch to util.dbuffer for buffering incoming data
Kim Alvefur <zash@zash.se>
parents: 10580
diff changeset
61 local index = buffer:sub(1, headlimit):find("\r\n\r\n", nil, true);
13378
db30ffbf2090 net.http.parser: Reject overlarge header section earlier
Kim Alvefur <zash@zash.se>
parents: 12889
diff changeset
62 if not index then
db30ffbf2090 net.http.parser: Reject overlarge header section earlier
Kim Alvefur <zash@zash.se>
parents: 12889
diff changeset
63 if buffer:length() > headlimit then
db30ffbf2090 net.http.parser: Reject overlarge header section earlier
Kim Alvefur <zash@zash.se>
parents: 12889
diff changeset
64 return error_cb("header-too-large");
db30ffbf2090 net.http.parser: Reject overlarge header section earlier
Kim Alvefur <zash@zash.se>
parents: 12889
diff changeset
65 end
db30ffbf2090 net.http.parser: Reject overlarge header section earlier
Kim Alvefur <zash@zash.se>
parents: 12889
diff changeset
66 -- not enough data
db30ffbf2090 net.http.parser: Reject overlarge header section earlier
Kim Alvefur <zash@zash.se>
parents: 12889
diff changeset
67 return;
db30ffbf2090 net.http.parser: Reject overlarge header section earlier
Kim Alvefur <zash@zash.se>
parents: 12889
diff changeset
68 end
10540
375d31225d53 net.http.parser: Silence warning about unused variable [luacheck]
Kim Alvefur <zash@zash.se>
parents: 8045
diff changeset
69 -- FIXME was reason_phrase meant to be passed on somewhere?
375d31225d53 net.http.parser: Silence warning about unused variable [luacheck]
Kim Alvefur <zash@zash.se>
parents: 8045
diff changeset
70 local method, path, httpversion, status_code, reason_phrase; -- luacheck: ignore reason_phrase
4631
fc5d3b053454 net.http.{server|codes|parser}: Initial commit.
Waqas Hussain <waqas20@gmail.com>
parents:
diff changeset
71 local first_line;
fc5d3b053454 net.http.{server|codes|parser}: Initial commit.
Waqas Hussain <waqas20@gmail.com>
parents:
diff changeset
72 local headers = {};
11020
7076ed654ac9 net.http.parser: Switch to util.dbuffer for buffering incoming data
Kim Alvefur <zash@zash.se>
parents: 10580
diff changeset
73 for line in buffer:read(index+3):gmatch("([^\r\n]+)\r\n") do -- parse request
4631
fc5d3b053454 net.http.{server|codes|parser}: Initial commit.
Waqas Hussain <waqas20@gmail.com>
parents:
diff changeset
74 if first_line then
fc5d3b053454 net.http.{server|codes|parser}: Initial commit.
Waqas Hussain <waqas20@gmail.com>
parents:
diff changeset
75 local key, val = line:match("^([^%s:]+): *(.*)$");
fc5d3b053454 net.http.{server|codes|parser}: Initial commit.
Waqas Hussain <waqas20@gmail.com>
parents:
diff changeset
76 if not key then error = true; return error_cb("invalid-header-line"); end -- TODO handle multi-line and invalid headers
fc5d3b053454 net.http.{server|codes|parser}: Initial commit.
Waqas Hussain <waqas20@gmail.com>
parents:
diff changeset
77 key = key:lower();
fc5d3b053454 net.http.{server|codes|parser}: Initial commit.
Waqas Hussain <waqas20@gmail.com>
parents:
diff changeset
78 headers[key] = headers[key] and headers[key]..","..val or val;
fc5d3b053454 net.http.{server|codes|parser}: Initial commit.
Waqas Hussain <waqas20@gmail.com>
parents:
diff changeset
79 else
fc5d3b053454 net.http.{server|codes|parser}: Initial commit.
Waqas Hussain <waqas20@gmail.com>
parents:
diff changeset
80 first_line = line;
fc5d3b053454 net.http.{server|codes|parser}: Initial commit.
Waqas Hussain <waqas20@gmail.com>
parents:
diff changeset
81 if client then
fc5d3b053454 net.http.{server|codes|parser}: Initial commit.
Waqas Hussain <waqas20@gmail.com>
parents:
diff changeset
82 httpversion, status_code, reason_phrase = line:match("^HTTP/(1%.[01]) (%d%d%d) (.*)$");
5462
3ecae471d9dd net.http.parser: Convert status_code to a number before trying to compare it to numbers
Matthew Wild <mwild1@gmail.com>
parents: 5461
diff changeset
83 status_code = tonumber(status_code);
4631
fc5d3b053454 net.http.{server|codes|parser}: Initial commit.
Waqas Hussain <waqas20@gmail.com>
parents:
diff changeset
84 if not status_code then error = true; return error_cb("invalid-status-line"); end
fc5d3b053454 net.http.{server|codes|parser}: Initial commit.
Waqas Hussain <waqas20@gmail.com>
parents:
diff changeset
85 have_body = not
fc5d3b053454 net.http.{server|codes|parser}: Initial commit.
Waqas Hussain <waqas20@gmail.com>
parents:
diff changeset
86 ( (options_cb and options_cb().method == "HEAD")
fc5d3b053454 net.http.{server|codes|parser}: Initial commit.
Waqas Hussain <waqas20@gmail.com>
parents:
diff changeset
87 or (status_code == 204 or status_code == 304 or status_code == 301)
fc5d3b053454 net.http.{server|codes|parser}: Initial commit.
Waqas Hussain <waqas20@gmail.com>
parents:
diff changeset
88 or (status_code >= 100 and status_code < 200) );
fc5d3b053454 net.http.{server|codes|parser}: Initial commit.
Waqas Hussain <waqas20@gmail.com>
parents:
diff changeset
89 else
fc5d3b053454 net.http.{server|codes|parser}: Initial commit.
Waqas Hussain <waqas20@gmail.com>
parents:
diff changeset
90 method, path, httpversion = line:match("^(%w+) (%S+) HTTP/(1%.[01])$");
fc5d3b053454 net.http.{server|codes|parser}: Initial commit.
Waqas Hussain <waqas20@gmail.com>
parents:
diff changeset
91 if not method then error = true; return error_cb("invalid-status-line"); end
fc5d3b053454 net.http.{server|codes|parser}: Initial commit.
Waqas Hussain <waqas20@gmail.com>
parents:
diff changeset
92 end
fc5d3b053454 net.http.{server|codes|parser}: Initial commit.
Waqas Hussain <waqas20@gmail.com>
parents:
diff changeset
93 end
fc5d3b053454 net.http.{server|codes|parser}: Initial commit.
Waqas Hussain <waqas20@gmail.com>
parents:
diff changeset
94 end
5291
01f7522049fb net.http.parser: Abort if no status line is received.
Kim Alvefur <zash@zash.se>
parents: 5259
diff changeset
95 if not first_line then error = true; return error_cb("invalid-status-line"); end
5463
111953bfe767 net.http.parser: Fix chunked encoding response parsing, and make it more robust
Matthew Wild <mwild1@gmail.com>
parents: 5462
diff changeset
96 chunked = have_body and headers["transfer-encoding"] == "chunked";
4631
fc5d3b053454 net.http.{server|codes|parser}: Initial commit.
Waqas Hussain <waqas20@gmail.com>
parents:
diff changeset
97 len = tonumber(headers["content-length"]); -- TODO check for invalid len
fc5d3b053454 net.http.{server|codes|parser}: Initial commit.
Waqas Hussain <waqas20@gmail.com>
parents:
diff changeset
98 if client then
fc5d3b053454 net.http.{server|codes|parser}: Initial commit.
Waqas Hussain <waqas20@gmail.com>
parents:
diff changeset
99 -- FIXME handle '100 Continue' response (by skipping it)
fc5d3b053454 net.http.{server|codes|parser}: Initial commit.
Waqas Hussain <waqas20@gmail.com>
parents:
diff changeset
100 if not have_body then len = 0; end
fc5d3b053454 net.http.{server|codes|parser}: Initial commit.
Waqas Hussain <waqas20@gmail.com>
parents:
diff changeset
101 packet = {
fc5d3b053454 net.http.{server|codes|parser}: Initial commit.
Waqas Hussain <waqas20@gmail.com>
parents:
diff changeset
102 code = status_code;
fc5d3b053454 net.http.{server|codes|parser}: Initial commit.
Waqas Hussain <waqas20@gmail.com>
parents:
diff changeset
103 httpversion = httpversion;
fc5d3b053454 net.http.{server|codes|parser}: Initial commit.
Waqas Hussain <waqas20@gmail.com>
parents:
diff changeset
104 headers = headers;
11020
7076ed654ac9 net.http.parser: Switch to util.dbuffer for buffering incoming data
Kim Alvefur <zash@zash.se>
parents: 10580
diff changeset
105 body = false;
11184
2ede7f43ccfe net.http.parser: Expose 'partial', 'chunked' and 'body_length' on packets
Matthew Wild <mwild1@gmail.com>
parents: 11029
diff changeset
106 body_length = len;
2ede7f43ccfe net.http.parser: Expose 'partial', 'chunked' and 'body_length' on packets
Matthew Wild <mwild1@gmail.com>
parents: 11029
diff changeset
107 chunked = chunked;
2ede7f43ccfe net.http.parser: Expose 'partial', 'chunked' and 'body_length' on packets
Matthew Wild <mwild1@gmail.com>
parents: 11029
diff changeset
108 partial = true;
4631
fc5d3b053454 net.http.{server|codes|parser}: Initial commit.
Waqas Hussain <waqas20@gmail.com>
parents:
diff changeset
109 -- COMPAT the properties below are deprecated
fc5d3b053454 net.http.{server|codes|parser}: Initial commit.
Waqas Hussain <waqas20@gmail.com>
parents:
diff changeset
110 responseversion = httpversion;
fc5d3b053454 net.http.{server|codes|parser}: Initial commit.
Waqas Hussain <waqas20@gmail.com>
parents:
diff changeset
111 responseheaders = headers;
fc5d3b053454 net.http.{server|codes|parser}: Initial commit.
Waqas Hussain <waqas20@gmail.com>
parents:
diff changeset
112 };
fc5d3b053454 net.http.{server|codes|parser}: Initial commit.
Waqas Hussain <waqas20@gmail.com>
parents:
diff changeset
113 else
5259
c85c348253bd net.http.parser: Skip url.parse when we don't have a full URL (also fixes traceback on paths starting with '//').
Waqas Hussain <waqas20@gmail.com>
parents: 5222
diff changeset
114 local parsed_url;
c85c348253bd net.http.parser: Skip url.parse when we don't have a full URL (also fixes traceback on paths starting with '//').
Waqas Hussain <waqas20@gmail.com>
parents: 5222
diff changeset
115 if path:byte() == 47 then -- starts with /
c85c348253bd net.http.parser: Skip url.parse when we don't have a full URL (also fixes traceback on paths starting with '//').
Waqas Hussain <waqas20@gmail.com>
parents: 5222
diff changeset
116 local _path, _query = path:match("([^?]*).?(.*)");
c85c348253bd net.http.parser: Skip url.parse when we don't have a full URL (also fixes traceback on paths starting with '//').
Waqas Hussain <waqas20@gmail.com>
parents: 5222
diff changeset
117 if _query == "" then _query = nil; end
c85c348253bd net.http.parser: Skip url.parse when we don't have a full URL (also fixes traceback on paths starting with '//').
Waqas Hussain <waqas20@gmail.com>
parents: 5222
diff changeset
118 parsed_url = { path = _path, query = _query };
c85c348253bd net.http.parser: Skip url.parse when we don't have a full URL (also fixes traceback on paths starting with '//').
Waqas Hussain <waqas20@gmail.com>
parents: 5222
diff changeset
119 else
c85c348253bd net.http.parser: Skip url.parse when we don't have a full URL (also fixes traceback on paths starting with '//').
Waqas Hussain <waqas20@gmail.com>
parents: 5222
diff changeset
120 parsed_url = url_parse(path);
5323
4c30f638ff55 net.http.parser: Ensure full URL in status line contains a path.
Waqas Hussain <waqas20@gmail.com>
parents: 5322
diff changeset
121 if not(parsed_url and parsed_url.path) then error = true; return error_cb("invalid-url"); end
5259
c85c348253bd net.http.parser: Skip url.parse when we don't have a full URL (also fixes traceback on paths starting with '//').
Waqas Hussain <waqas20@gmail.com>
parents: 5222
diff changeset
122 end
4866
d54999db3aa1 net.http.parser: Do full URL decoding and parsing (e.g. adds request.url.query when present)
Matthew Wild <mwild1@gmail.com>
parents: 4716
diff changeset
123 path = preprocess_path(parsed_url.path);
4879
45bb378a4a98 net.http.parser: Keep the Host header no host is present in the URI
Kim Alvefur <zash@zash.se>
parents: 4866
diff changeset
124 headers.host = parsed_url.host or headers.host;
4712
4fc99f1b7570 net.http.parser: Handle full URLs in status line.
Waqas Hussain <waqas20@gmail.com>
parents: 4631
diff changeset
125
4631
fc5d3b053454 net.http.{server|codes|parser}: Initial commit.
Waqas Hussain <waqas20@gmail.com>
parents:
diff changeset
126 len = len or 0;
fc5d3b053454 net.http.{server|codes|parser}: Initial commit.
Waqas Hussain <waqas20@gmail.com>
parents:
diff changeset
127 packet = {
fc5d3b053454 net.http.{server|codes|parser}: Initial commit.
Waqas Hussain <waqas20@gmail.com>
parents:
diff changeset
128 method = method;
4866
d54999db3aa1 net.http.parser: Do full URL decoding and parsing (e.g. adds request.url.query when present)
Matthew Wild <mwild1@gmail.com>
parents: 4716
diff changeset
129 url = parsed_url;
4631
fc5d3b053454 net.http.{server|codes|parser}: Initial commit.
Waqas Hussain <waqas20@gmail.com>
parents:
diff changeset
130 path = path;
fc5d3b053454 net.http.{server|codes|parser}: Initial commit.
Waqas Hussain <waqas20@gmail.com>
parents:
diff changeset
131 httpversion = httpversion;
fc5d3b053454 net.http.{server|codes|parser}: Initial commit.
Waqas Hussain <waqas20@gmail.com>
parents:
diff changeset
132 headers = headers;
11020
7076ed654ac9 net.http.parser: Switch to util.dbuffer for buffering incoming data
Kim Alvefur <zash@zash.se>
parents: 10580
diff changeset
133 body = false;
7076ed654ac9 net.http.parser: Switch to util.dbuffer for buffering incoming data
Kim Alvefur <zash@zash.se>
parents: 10580
diff changeset
134 body_sink = nil;
11184
2ede7f43ccfe net.http.parser: Expose 'partial', 'chunked' and 'body_length' on packets
Matthew Wild <mwild1@gmail.com>
parents: 11029
diff changeset
135 chunked = chunked;
2ede7f43ccfe net.http.parser: Expose 'partial', 'chunked' and 'body_length' on packets
Matthew Wild <mwild1@gmail.com>
parents: 11029
diff changeset
136 partial = true;
4631
fc5d3b053454 net.http.{server|codes|parser}: Initial commit.
Waqas Hussain <waqas20@gmail.com>
parents:
diff changeset
137 };
fc5d3b053454 net.http.{server|codes|parser}: Initial commit.
Waqas Hussain <waqas20@gmail.com>
parents:
diff changeset
138 end
12882
9ed628635dc6 net.http.parser: Improve handling of responses without content-length
Matthew Wild <mwild1@gmail.com>
parents: 11727
diff changeset
139 if not len or len > bodylimit then
11021
9673c95895fb net.http.parser: Allow specifying sink for large request bodies
Kim Alvefur <zash@zash.se>
parents: 11020
diff changeset
140 -- Early notification, for redirection
9673c95895fb net.http.parser: Allow specifying sink for large request bodies
Kim Alvefur <zash@zash.se>
parents: 11020
diff changeset
141 success_cb(packet);
12882
9ed628635dc6 net.http.parser: Improve handling of responses without content-length
Matthew Wild <mwild1@gmail.com>
parents: 11727
diff changeset
142 if not packet.body_sink and (len and len > bodylimit) then
9ed628635dc6 net.http.parser: Improve handling of responses without content-length
Matthew Wild <mwild1@gmail.com>
parents: 11727
diff changeset
143 error = true;
9ed628635dc6 net.http.parser: Improve handling of responses without content-length
Matthew Wild <mwild1@gmail.com>
parents: 11727
diff changeset
144 return error_cb("content-length-limit-exceeded");
9ed628635dc6 net.http.parser: Improve handling of responses without content-length
Matthew Wild <mwild1@gmail.com>
parents: 11727
diff changeset
145 end
11021
9673c95895fb net.http.parser: Allow specifying sink for large request bodies
Kim Alvefur <zash@zash.se>
parents: 11020
diff changeset
146 end
9673c95895fb net.http.parser: Allow specifying sink for large request bodies
Kim Alvefur <zash@zash.se>
parents: 11020
diff changeset
147 if chunked and not packet.body_sink then
9673c95895fb net.http.parser: Allow specifying sink for large request bodies
Kim Alvefur <zash@zash.se>
parents: 11020
diff changeset
148 success_cb(packet);
9673c95895fb net.http.parser: Allow specifying sink for large request bodies
Kim Alvefur <zash@zash.se>
parents: 11020
diff changeset
149 if not packet.body_sink then
11029
5550fc5e83f3 net.http.parser: Fix indentation
Kim Alvefur <zash@zash.se>
parents: 11021
diff changeset
150 packet.body_buffer = dbuffer.new(buflimit);
5550fc5e83f3 net.http.parser: Fix indentation
Kim Alvefur <zash@zash.se>
parents: 11021
diff changeset
151 end
11021
9673c95895fb net.http.parser: Allow specifying sink for large request bodies
Kim Alvefur <zash@zash.se>
parents: 11020
diff changeset
152 end
4631
fc5d3b053454 net.http.{server|codes|parser}: Initial commit.
Waqas Hussain <waqas20@gmail.com>
parents:
diff changeset
153 state = true;
fc5d3b053454 net.http.{server|codes|parser}: Initial commit.
Waqas Hussain <waqas20@gmail.com>
parents:
diff changeset
154 end
fc5d3b053454 net.http.{server|codes|parser}: Initial commit.
Waqas Hussain <waqas20@gmail.com>
parents:
diff changeset
155 if state then -- read body
11020
7076ed654ac9 net.http.parser: Switch to util.dbuffer for buffering incoming data
Kim Alvefur <zash@zash.se>
parents: 10580
diff changeset
156 if chunked then
7076ed654ac9 net.http.parser: Switch to util.dbuffer for buffering incoming data
Kim Alvefur <zash@zash.se>
parents: 10580
diff changeset
157 local chunk_header = buffer:sub(1, 512); -- XXX How large do chunk headers grow?
7076ed654ac9 net.http.parser: Switch to util.dbuffer for buffering incoming data
Kim Alvefur <zash@zash.se>
parents: 10580
diff changeset
158 local chunk_size, chunk_start = chunk_header:match("^(%x+)[^\r\n]*\r\n()");
7076ed654ac9 net.http.parser: Switch to util.dbuffer for buffering incoming data
Kim Alvefur <zash@zash.se>
parents: 10580
diff changeset
159 if not chunk_size then return; end
7076ed654ac9 net.http.parser: Switch to util.dbuffer for buffering incoming data
Kim Alvefur <zash@zash.se>
parents: 10580
diff changeset
160 chunk_size = chunk_size and tonumber(chunk_size, 16);
7076ed654ac9 net.http.parser: Switch to util.dbuffer for buffering incoming data
Kim Alvefur <zash@zash.se>
parents: 10580
diff changeset
161 if not chunk_size then error = true; return error_cb("invalid-chunk-size"); end
12889
94a99330ce87 net.http.parser: Fix off-by-one error in chunk parser
Matthew Wild <mwild1@gmail.com>
parents: 12882
diff changeset
162
11020
7076ed654ac9 net.http.parser: Switch to util.dbuffer for buffering incoming data
Kim Alvefur <zash@zash.se>
parents: 10580
diff changeset
163 if chunk_size == 0 and chunk_header:find("\r\n\r\n", chunk_start-2, true) then
7076ed654ac9 net.http.parser: Switch to util.dbuffer for buffering incoming data
Kim Alvefur <zash@zash.se>
parents: 10580
diff changeset
164 local body_buffer = packet.body_buffer;
7076ed654ac9 net.http.parser: Switch to util.dbuffer for buffering incoming data
Kim Alvefur <zash@zash.se>
parents: 10580
diff changeset
165 if body_buffer then
7076ed654ac9 net.http.parser: Switch to util.dbuffer for buffering incoming data
Kim Alvefur <zash@zash.se>
parents: 10580
diff changeset
166 packet.body_buffer = nil;
7076ed654ac9 net.http.parser: Switch to util.dbuffer for buffering incoming data
Kim Alvefur <zash@zash.se>
parents: 10580
diff changeset
167 body_buffer:collapse();
7076ed654ac9 net.http.parser: Switch to util.dbuffer for buffering incoming data
Kim Alvefur <zash@zash.se>
parents: 10580
diff changeset
168 packet.body = body_buffer:read_chunk() or "";
4631
fc5d3b053454 net.http.{server|codes|parser}: Initial commit.
Waqas Hussain <waqas20@gmail.com>
parents:
diff changeset
169 end
11020
7076ed654ac9 net.http.parser: Switch to util.dbuffer for buffering incoming data
Kim Alvefur <zash@zash.se>
parents: 10580
diff changeset
170
7076ed654ac9 net.http.parser: Switch to util.dbuffer for buffering incoming data
Kim Alvefur <zash@zash.se>
parents: 10580
diff changeset
171 buffer:collapse();
7076ed654ac9 net.http.parser: Switch to util.dbuffer for buffering incoming data
Kim Alvefur <zash@zash.se>
parents: 10580
diff changeset
172 local buf = buffer:read_chunk();
7076ed654ac9 net.http.parser: Switch to util.dbuffer for buffering incoming data
Kim Alvefur <zash@zash.se>
parents: 10580
diff changeset
173 buf = buf:gsub("^.-\r\n\r\n", ""); -- This ensure extensions and trailers are stripped
7076ed654ac9 net.http.parser: Switch to util.dbuffer for buffering incoming data
Kim Alvefur <zash@zash.se>
parents: 10580
diff changeset
174 buffer:write(buf);
7076ed654ac9 net.http.parser: Switch to util.dbuffer for buffering incoming data
Kim Alvefur <zash@zash.se>
parents: 10580
diff changeset
175 state, chunked = nil, nil;
11184
2ede7f43ccfe net.http.parser: Expose 'partial', 'chunked' and 'body_length' on packets
Matthew Wild <mwild1@gmail.com>
parents: 11029
diff changeset
176 packet.partial = nil;
11020
7076ed654ac9 net.http.parser: Switch to util.dbuffer for buffering incoming data
Kim Alvefur <zash@zash.se>
parents: 10580
diff changeset
177 success_cb(packet);
12889
94a99330ce87 net.http.parser: Fix off-by-one error in chunk parser
Matthew Wild <mwild1@gmail.com>
parents: 12882
diff changeset
178 elseif buffer:length() - chunk_start - 1 >= chunk_size then -- we have a chunk
94a99330ce87 net.http.parser: Fix off-by-one error in chunk parser
Matthew Wild <mwild1@gmail.com>
parents: 12882
diff changeset
179 buffer:discard(chunk_start - 1);
11021
9673c95895fb net.http.parser: Allow specifying sink for large request bodies
Kim Alvefur <zash@zash.se>
parents: 11020
diff changeset
180 (packet.body_sink or packet.body_buffer):write(buffer:read(chunk_size));
11020
7076ed654ac9 net.http.parser: Switch to util.dbuffer for buffering incoming data
Kim Alvefur <zash@zash.se>
parents: 10580
diff changeset
181 buffer:discard(2); -- CRLF
7076ed654ac9 net.http.parser: Switch to util.dbuffer for buffering incoming data
Kim Alvefur <zash@zash.se>
parents: 10580
diff changeset
182 else -- Partial chunk remaining
5461
67b674f6a299 net.http.parser: Break when no more usable data in buffer (client part of e5ec60dfb202)
Matthew Wild <mwild1@gmail.com>
parents: 5460
diff changeset
183 break;
4631
fc5d3b053454 net.http.{server|codes|parser}: Initial commit.
Waqas Hussain <waqas20@gmail.com>
parents:
diff changeset
184 end
11021
9673c95895fb net.http.parser: Allow specifying sink for large request bodies
Kim Alvefur <zash@zash.se>
parents: 11020
diff changeset
185 elseif packet.body_sink then
9673c95895fb net.http.parser: Allow specifying sink for large request bodies
Kim Alvefur <zash@zash.se>
parents: 11020
diff changeset
186 local chunk = buffer:read_chunk(len);
12882
9ed628635dc6 net.http.parser: Improve handling of responses without content-length
Matthew Wild <mwild1@gmail.com>
parents: 11727
diff changeset
187 while chunk and (not len or len > 0) do
11021
9673c95895fb net.http.parser: Allow specifying sink for large request bodies
Kim Alvefur <zash@zash.se>
parents: 11020
diff changeset
188 if packet.body_sink:write(chunk) then
12882
9ed628635dc6 net.http.parser: Improve handling of responses without content-length
Matthew Wild <mwild1@gmail.com>
parents: 11727
diff changeset
189 if len then
9ed628635dc6 net.http.parser: Improve handling of responses without content-length
Matthew Wild <mwild1@gmail.com>
parents: 11727
diff changeset
190 len = len - #chunk;
9ed628635dc6 net.http.parser: Improve handling of responses without content-length
Matthew Wild <mwild1@gmail.com>
parents: 11727
diff changeset
191 end
11021
9673c95895fb net.http.parser: Allow specifying sink for large request bodies
Kim Alvefur <zash@zash.se>
parents: 11020
diff changeset
192 chunk = buffer:read_chunk(len);
9673c95895fb net.http.parser: Allow specifying sink for large request bodies
Kim Alvefur <zash@zash.se>
parents: 11020
diff changeset
193 else
9673c95895fb net.http.parser: Allow specifying sink for large request bodies
Kim Alvefur <zash@zash.se>
parents: 11020
diff changeset
194 error = true;
9673c95895fb net.http.parser: Allow specifying sink for large request bodies
Kim Alvefur <zash@zash.se>
parents: 11020
diff changeset
195 return error_cb("body-sink-write-failure");
9673c95895fb net.http.parser: Allow specifying sink for large request bodies
Kim Alvefur <zash@zash.se>
parents: 11020
diff changeset
196 end
9673c95895fb net.http.parser: Allow specifying sink for large request bodies
Kim Alvefur <zash@zash.se>
parents: 11020
diff changeset
197 end
11184
2ede7f43ccfe net.http.parser: Expose 'partial', 'chunked' and 'body_length' on packets
Matthew Wild <mwild1@gmail.com>
parents: 11029
diff changeset
198 if len == 0 then
2ede7f43ccfe net.http.parser: Expose 'partial', 'chunked' and 'body_length' on packets
Matthew Wild <mwild1@gmail.com>
parents: 11029
diff changeset
199 state = nil;
2ede7f43ccfe net.http.parser: Expose 'partial', 'chunked' and 'body_length' on packets
Matthew Wild <mwild1@gmail.com>
parents: 11029
diff changeset
200 packet.partial = nil;
2ede7f43ccfe net.http.parser: Expose 'partial', 'chunked' and 'body_length' on packets
Matthew Wild <mwild1@gmail.com>
parents: 11029
diff changeset
201 success_cb(packet);
2ede7f43ccfe net.http.parser: Expose 'partial', 'chunked' and 'body_length' on packets
Matthew Wild <mwild1@gmail.com>
parents: 11029
diff changeset
202 end
12882
9ed628635dc6 net.http.parser: Improve handling of responses without content-length
Matthew Wild <mwild1@gmail.com>
parents: 11727
diff changeset
203 elseif not len or buffer:length() >= len then -- or not len
11020
7076ed654ac9 net.http.parser: Switch to util.dbuffer for buffering incoming data
Kim Alvefur <zash@zash.se>
parents: 10580
diff changeset
204 assert(not chunked)
12882
9ed628635dc6 net.http.parser: Improve handling of responses without content-length
Matthew Wild <mwild1@gmail.com>
parents: 11727
diff changeset
205 packet.body = len and buffer:read(len) or buffer:read_chunk() or "";
11184
2ede7f43ccfe net.http.parser: Expose 'partial', 'chunked' and 'body_length' on packets
Matthew Wild <mwild1@gmail.com>
parents: 11029
diff changeset
206 state = nil;
2ede7f43ccfe net.http.parser: Expose 'partial', 'chunked' and 'body_length' on packets
Matthew Wild <mwild1@gmail.com>
parents: 11029
diff changeset
207 packet.partial = nil;
2ede7f43ccfe net.http.parser: Expose 'partial', 'chunked' and 'body_length' on packets
Matthew Wild <mwild1@gmail.com>
parents: 11029
diff changeset
208 success_cb(packet);
4910
e5ec60dfb202 net.http.parser: Break loop when no more usable data in buffer
Matthew Wild <mwild1@gmail.com>
parents: 4879
diff changeset
209 else
e5ec60dfb202 net.http.parser: Break loop when no more usable data in buffer
Matthew Wild <mwild1@gmail.com>
parents: 4879
diff changeset
210 break;
4631
fc5d3b053454 net.http.{server|codes|parser}: Initial commit.
Waqas Hussain <waqas20@gmail.com>
parents:
diff changeset
211 end
11020
7076ed654ac9 net.http.parser: Switch to util.dbuffer for buffering incoming data
Kim Alvefur <zash@zash.se>
parents: 10580
diff changeset
212 else
7076ed654ac9 net.http.parser: Switch to util.dbuffer for buffering incoming data
Kim Alvefur <zash@zash.se>
parents: 10580
diff changeset
213 break;
4631
fc5d3b053454 net.http.{server|codes|parser}: Initial commit.
Waqas Hussain <waqas20@gmail.com>
parents:
diff changeset
214 end
fc5d3b053454 net.http.{server|codes|parser}: Initial commit.
Waqas Hussain <waqas20@gmail.com>
parents:
diff changeset
215 end
fc5d3b053454 net.http.{server|codes|parser}: Initial commit.
Waqas Hussain <waqas20@gmail.com>
parents:
diff changeset
216 end;
fc5d3b053454 net.http.{server|codes|parser}: Initial commit.
Waqas Hussain <waqas20@gmail.com>
parents:
diff changeset
217 };
fc5d3b053454 net.http.{server|codes|parser}: Initial commit.
Waqas Hussain <waqas20@gmail.com>
parents:
diff changeset
218 end
fc5d3b053454 net.http.{server|codes|parser}: Initial commit.
Waqas Hussain <waqas20@gmail.com>
parents:
diff changeset
219
fc5d3b053454 net.http.{server|codes|parser}: Initial commit.
Waqas Hussain <waqas20@gmail.com>
parents:
diff changeset
220 return httpstream;