Annotate

net/http/parser.lua @ 13379:977d92aff563

Merge 0.12->trunk
author Kim Alvefur <zash@zash.se>
date Fri, 01 Dec 2023 17:11:19 +0100
parent 12974:ba409c67353b
parent 13378:db30ffbf2090
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;