Software /
code /
prosody
Annotate
net/http/parser.lua @ 12468:353836684009
net.connect: Fix accumulation of connection attempt references
Connection attempts that failed the Happy Eyeballs race were not
unreferenced and would accumulate.
Tested by inspecting the 'pending_connections_map' after establishing
s2s with a s2s target where the IPv6 port has a -j DROP rule causing it
to time out and the IPv4 attempt wins the race.
Expected is that the losing connection stays around until net.server
timeouts kick in where it should be removed. The map table should tend
towards being empty during idle times.
author | Kim Alvefur <zash@zash.se> |
---|---|
date | Wed, 20 Apr 2022 22:41:54 +0200 |
parent | 11727:f3aee8a825cc |
child | 12882:9ed628635dc6 |
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; |
5460
274c10668fe8
net.http.parser: Depend on util.http instead of net.http for urlencode
Matthew Wild <mwild1@gmail.com>
parents:
5323
diff
changeset
|
4 local urldecode = require "util.http".urldecode; |
11020
7076ed654ac9
net.http.parser: Switch to util.dbuffer for buffering incoming data
Kim Alvefur <zash@zash.se>
parents:
10580
diff
changeset
|
5 local dbuffer = require "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); |
4631
fc5d3b053454
net.http.{server|codes|parser}: Initial commit.
Waqas Hussain <waqas20@gmail.com>
parents:
diff
changeset
|
62 if not index then return; end -- not enough data |
10540
375d31225d53
net.http.parser: Silence warning about unused variable [luacheck]
Kim Alvefur <zash@zash.se>
parents:
8045
diff
changeset
|
63 -- 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
|
64 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
|
65 local first_line; |
fc5d3b053454
net.http.{server|codes|parser}: Initial commit.
Waqas Hussain <waqas20@gmail.com>
parents:
diff
changeset
|
66 local headers = {}; |
11020
7076ed654ac9
net.http.parser: Switch to util.dbuffer for buffering incoming data
Kim Alvefur <zash@zash.se>
parents:
10580
diff
changeset
|
67 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
|
68 if first_line then |
fc5d3b053454
net.http.{server|codes|parser}: Initial commit.
Waqas Hussain <waqas20@gmail.com>
parents:
diff
changeset
|
69 local key, val = line:match("^([^%s:]+): *(.*)$"); |
fc5d3b053454
net.http.{server|codes|parser}: Initial commit.
Waqas Hussain <waqas20@gmail.com>
parents:
diff
changeset
|
70 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
|
71 key = key:lower(); |
fc5d3b053454
net.http.{server|codes|parser}: Initial commit.
Waqas Hussain <waqas20@gmail.com>
parents:
diff
changeset
|
72 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
|
73 else |
fc5d3b053454
net.http.{server|codes|parser}: Initial commit.
Waqas Hussain <waqas20@gmail.com>
parents:
diff
changeset
|
74 first_line = line; |
fc5d3b053454
net.http.{server|codes|parser}: Initial commit.
Waqas Hussain <waqas20@gmail.com>
parents:
diff
changeset
|
75 if client then |
fc5d3b053454
net.http.{server|codes|parser}: Initial commit.
Waqas Hussain <waqas20@gmail.com>
parents:
diff
changeset
|
76 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
|
77 status_code = tonumber(status_code); |
4631
fc5d3b053454
net.http.{server|codes|parser}: Initial commit.
Waqas Hussain <waqas20@gmail.com>
parents:
diff
changeset
|
78 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
|
79 have_body = not |
fc5d3b053454
net.http.{server|codes|parser}: Initial commit.
Waqas Hussain <waqas20@gmail.com>
parents:
diff
changeset
|
80 ( (options_cb and options_cb().method == "HEAD") |
fc5d3b053454
net.http.{server|codes|parser}: Initial commit.
Waqas Hussain <waqas20@gmail.com>
parents:
diff
changeset
|
81 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
|
82 or (status_code >= 100 and status_code < 200) ); |
fc5d3b053454
net.http.{server|codes|parser}: Initial commit.
Waqas Hussain <waqas20@gmail.com>
parents:
diff
changeset
|
83 else |
fc5d3b053454
net.http.{server|codes|parser}: Initial commit.
Waqas Hussain <waqas20@gmail.com>
parents:
diff
changeset
|
84 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
|
85 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
|
86 end |
fc5d3b053454
net.http.{server|codes|parser}: Initial commit.
Waqas Hussain <waqas20@gmail.com>
parents:
diff
changeset
|
87 end |
fc5d3b053454
net.http.{server|codes|parser}: Initial commit.
Waqas Hussain <waqas20@gmail.com>
parents:
diff
changeset
|
88 end |
5291
01f7522049fb
net.http.parser: Abort if no status line is received.
Kim Alvefur <zash@zash.se>
parents:
5259
diff
changeset
|
89 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
|
90 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
|
91 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
|
92 if client then |
fc5d3b053454
net.http.{server|codes|parser}: Initial commit.
Waqas Hussain <waqas20@gmail.com>
parents:
diff
changeset
|
93 -- FIXME handle '100 Continue' response (by skipping it) |
fc5d3b053454
net.http.{server|codes|parser}: Initial commit.
Waqas Hussain <waqas20@gmail.com>
parents:
diff
changeset
|
94 if not have_body then len = 0; end |
fc5d3b053454
net.http.{server|codes|parser}: Initial commit.
Waqas Hussain <waqas20@gmail.com>
parents:
diff
changeset
|
95 packet = { |
fc5d3b053454
net.http.{server|codes|parser}: Initial commit.
Waqas Hussain <waqas20@gmail.com>
parents:
diff
changeset
|
96 code = status_code; |
fc5d3b053454
net.http.{server|codes|parser}: Initial commit.
Waqas Hussain <waqas20@gmail.com>
parents:
diff
changeset
|
97 httpversion = httpversion; |
fc5d3b053454
net.http.{server|codes|parser}: Initial commit.
Waqas Hussain <waqas20@gmail.com>
parents:
diff
changeset
|
98 headers = headers; |
11020
7076ed654ac9
net.http.parser: Switch to util.dbuffer for buffering incoming data
Kim Alvefur <zash@zash.se>
parents:
10580
diff
changeset
|
99 body = false; |
11184
2ede7f43ccfe
net.http.parser: Expose 'partial', 'chunked' and 'body_length' on packets
Matthew Wild <mwild1@gmail.com>
parents:
11029
diff
changeset
|
100 body_length = len; |
2ede7f43ccfe
net.http.parser: Expose 'partial', 'chunked' and 'body_length' on packets
Matthew Wild <mwild1@gmail.com>
parents:
11029
diff
changeset
|
101 chunked = chunked; |
2ede7f43ccfe
net.http.parser: Expose 'partial', 'chunked' and 'body_length' on packets
Matthew Wild <mwild1@gmail.com>
parents:
11029
diff
changeset
|
102 partial = true; |
4631
fc5d3b053454
net.http.{server|codes|parser}: Initial commit.
Waqas Hussain <waqas20@gmail.com>
parents:
diff
changeset
|
103 -- COMPAT the properties below are deprecated |
fc5d3b053454
net.http.{server|codes|parser}: Initial commit.
Waqas Hussain <waqas20@gmail.com>
parents:
diff
changeset
|
104 responseversion = httpversion; |
fc5d3b053454
net.http.{server|codes|parser}: Initial commit.
Waqas Hussain <waqas20@gmail.com>
parents:
diff
changeset
|
105 responseheaders = headers; |
fc5d3b053454
net.http.{server|codes|parser}: Initial commit.
Waqas Hussain <waqas20@gmail.com>
parents:
diff
changeset
|
106 }; |
fc5d3b053454
net.http.{server|codes|parser}: Initial commit.
Waqas Hussain <waqas20@gmail.com>
parents:
diff
changeset
|
107 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
|
108 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
|
109 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
|
110 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
|
111 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
|
112 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
|
113 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
|
114 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
|
115 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
|
116 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
|
117 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
|
118 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
|
119 |
4631
fc5d3b053454
net.http.{server|codes|parser}: Initial commit.
Waqas Hussain <waqas20@gmail.com>
parents:
diff
changeset
|
120 len = len or 0; |
fc5d3b053454
net.http.{server|codes|parser}: Initial commit.
Waqas Hussain <waqas20@gmail.com>
parents:
diff
changeset
|
121 packet = { |
fc5d3b053454
net.http.{server|codes|parser}: Initial commit.
Waqas Hussain <waqas20@gmail.com>
parents:
diff
changeset
|
122 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
|
123 url = parsed_url; |
4631
fc5d3b053454
net.http.{server|codes|parser}: Initial commit.
Waqas Hussain <waqas20@gmail.com>
parents:
diff
changeset
|
124 path = path; |
fc5d3b053454
net.http.{server|codes|parser}: Initial commit.
Waqas Hussain <waqas20@gmail.com>
parents:
diff
changeset
|
125 httpversion = httpversion; |
fc5d3b053454
net.http.{server|codes|parser}: Initial commit.
Waqas Hussain <waqas20@gmail.com>
parents:
diff
changeset
|
126 headers = headers; |
11020
7076ed654ac9
net.http.parser: Switch to util.dbuffer for buffering incoming data
Kim Alvefur <zash@zash.se>
parents:
10580
diff
changeset
|
127 body = false; |
7076ed654ac9
net.http.parser: Switch to util.dbuffer for buffering incoming data
Kim Alvefur <zash@zash.se>
parents:
10580
diff
changeset
|
128 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
|
129 chunked = chunked; |
2ede7f43ccfe
net.http.parser: Expose 'partial', 'chunked' and 'body_length' on packets
Matthew Wild <mwild1@gmail.com>
parents:
11029
diff
changeset
|
130 partial = true; |
4631
fc5d3b053454
net.http.{server|codes|parser}: Initial commit.
Waqas Hussain <waqas20@gmail.com>
parents:
diff
changeset
|
131 }; |
fc5d3b053454
net.http.{server|codes|parser}: Initial commit.
Waqas Hussain <waqas20@gmail.com>
parents:
diff
changeset
|
132 end |
11021
9673c95895fb
net.http.parser: Allow specifying sink for large request bodies
Kim Alvefur <zash@zash.se>
parents:
11020
diff
changeset
|
133 if len and len > bodylimit then |
9673c95895fb
net.http.parser: Allow specifying sink for large request bodies
Kim Alvefur <zash@zash.se>
parents:
11020
diff
changeset
|
134 -- Early notification, for redirection |
9673c95895fb
net.http.parser: Allow specifying sink for large request bodies
Kim Alvefur <zash@zash.se>
parents:
11020
diff
changeset
|
135 success_cb(packet); |
9673c95895fb
net.http.parser: Allow specifying sink for large request bodies
Kim Alvefur <zash@zash.se>
parents:
11020
diff
changeset
|
136 if not packet.body_sink then error = true; return error_cb("content-length-limit-exceeded"); end |
9673c95895fb
net.http.parser: Allow specifying sink for large request bodies
Kim Alvefur <zash@zash.se>
parents:
11020
diff
changeset
|
137 end |
9673c95895fb
net.http.parser: Allow specifying sink for large request bodies
Kim Alvefur <zash@zash.se>
parents:
11020
diff
changeset
|
138 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
|
139 success_cb(packet); |
9673c95895fb
net.http.parser: Allow specifying sink for large request bodies
Kim Alvefur <zash@zash.se>
parents:
11020
diff
changeset
|
140 if not packet.body_sink then |
11029
5550fc5e83f3
net.http.parser: Fix indentation
Kim Alvefur <zash@zash.se>
parents:
11021
diff
changeset
|
141 packet.body_buffer = dbuffer.new(buflimit); |
5550fc5e83f3
net.http.parser: Fix indentation
Kim Alvefur <zash@zash.se>
parents:
11021
diff
changeset
|
142 end |
11021
9673c95895fb
net.http.parser: Allow specifying sink for large request bodies
Kim Alvefur <zash@zash.se>
parents:
11020
diff
changeset
|
143 end |
4631
fc5d3b053454
net.http.{server|codes|parser}: Initial commit.
Waqas Hussain <waqas20@gmail.com>
parents:
diff
changeset
|
144 state = true; |
fc5d3b053454
net.http.{server|codes|parser}: Initial commit.
Waqas Hussain <waqas20@gmail.com>
parents:
diff
changeset
|
145 end |
fc5d3b053454
net.http.{server|codes|parser}: Initial commit.
Waqas Hussain <waqas20@gmail.com>
parents:
diff
changeset
|
146 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
|
147 if chunked then |
7076ed654ac9
net.http.parser: Switch to util.dbuffer for buffering incoming data
Kim Alvefur <zash@zash.se>
parents:
10580
diff
changeset
|
148 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
|
149 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
|
150 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
|
151 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
|
152 if not chunk_size then error = true; return error_cb("invalid-chunk-size"); end |
7076ed654ac9
net.http.parser: Switch to util.dbuffer for buffering incoming data
Kim Alvefur <zash@zash.se>
parents:
10580
diff
changeset
|
153 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
|
154 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
|
155 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
|
156 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
|
157 body_buffer:collapse(); |
7076ed654ac9
net.http.parser: Switch to util.dbuffer for buffering incoming data
Kim Alvefur <zash@zash.se>
parents:
10580
diff
changeset
|
158 packet.body = body_buffer:read_chunk() or ""; |
4631
fc5d3b053454
net.http.{server|codes|parser}: Initial commit.
Waqas Hussain <waqas20@gmail.com>
parents:
diff
changeset
|
159 end |
11020
7076ed654ac9
net.http.parser: Switch to util.dbuffer for buffering incoming data
Kim Alvefur <zash@zash.se>
parents:
10580
diff
changeset
|
160 |
7076ed654ac9
net.http.parser: Switch to util.dbuffer for buffering incoming data
Kim Alvefur <zash@zash.se>
parents:
10580
diff
changeset
|
161 buffer:collapse(); |
7076ed654ac9
net.http.parser: Switch to util.dbuffer for buffering incoming data
Kim Alvefur <zash@zash.se>
parents:
10580
diff
changeset
|
162 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
|
163 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
|
164 buffer:write(buf); |
7076ed654ac9
net.http.parser: Switch to util.dbuffer for buffering incoming data
Kim Alvefur <zash@zash.se>
parents:
10580
diff
changeset
|
165 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
|
166 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
|
167 success_cb(packet); |
7076ed654ac9
net.http.parser: Switch to util.dbuffer for buffering incoming data
Kim Alvefur <zash@zash.se>
parents:
10580
diff
changeset
|
168 elseif buffer:length() - chunk_start - 2 >= chunk_size then -- we have a chunk |
7076ed654ac9
net.http.parser: Switch to util.dbuffer for buffering incoming data
Kim Alvefur <zash@zash.se>
parents:
10580
diff
changeset
|
169 buffer:discard(chunk_start - 1); -- TODO verify that it's not off-by-one |
11021
9673c95895fb
net.http.parser: Allow specifying sink for large request bodies
Kim Alvefur <zash@zash.se>
parents:
11020
diff
changeset
|
170 (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
|
171 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
|
172 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
|
173 break; |
4631
fc5d3b053454
net.http.{server|codes|parser}: Initial commit.
Waqas Hussain <waqas20@gmail.com>
parents:
diff
changeset
|
174 end |
11021
9673c95895fb
net.http.parser: Allow specifying sink for large request bodies
Kim Alvefur <zash@zash.se>
parents:
11020
diff
changeset
|
175 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
|
176 local 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
|
177 while chunk and len > 0 do |
9673c95895fb
net.http.parser: Allow specifying sink for large request bodies
Kim Alvefur <zash@zash.se>
parents:
11020
diff
changeset
|
178 if packet.body_sink:write(chunk) then |
9673c95895fb
net.http.parser: Allow specifying sink for large request bodies
Kim Alvefur <zash@zash.se>
parents:
11020
diff
changeset
|
179 len = len - #chunk; |
9673c95895fb
net.http.parser: Allow specifying sink for large request bodies
Kim Alvefur <zash@zash.se>
parents:
11020
diff
changeset
|
180 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
|
181 else |
9673c95895fb
net.http.parser: Allow specifying sink for large request bodies
Kim Alvefur <zash@zash.se>
parents:
11020
diff
changeset
|
182 error = true; |
9673c95895fb
net.http.parser: Allow specifying sink for large request bodies
Kim Alvefur <zash@zash.se>
parents:
11020
diff
changeset
|
183 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
|
184 end |
9673c95895fb
net.http.parser: Allow specifying sink for large request bodies
Kim Alvefur <zash@zash.se>
parents:
11020
diff
changeset
|
185 end |
11184
2ede7f43ccfe
net.http.parser: Expose 'partial', 'chunked' and 'body_length' on packets
Matthew Wild <mwild1@gmail.com>
parents:
11029
diff
changeset
|
186 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
|
187 state = nil; |
2ede7f43ccfe
net.http.parser: Expose 'partial', 'chunked' and 'body_length' on packets
Matthew Wild <mwild1@gmail.com>
parents:
11029
diff
changeset
|
188 packet.partial = nil; |
2ede7f43ccfe
net.http.parser: Expose 'partial', 'chunked' and 'body_length' on packets
Matthew Wild <mwild1@gmail.com>
parents:
11029
diff
changeset
|
189 success_cb(packet); |
2ede7f43ccfe
net.http.parser: Expose 'partial', 'chunked' and 'body_length' on packets
Matthew Wild <mwild1@gmail.com>
parents:
11029
diff
changeset
|
190 end |
11020
7076ed654ac9
net.http.parser: Switch to util.dbuffer for buffering incoming data
Kim Alvefur <zash@zash.se>
parents:
10580
diff
changeset
|
191 elseif buffer:length() >= len then |
7076ed654ac9
net.http.parser: Switch to util.dbuffer for buffering incoming data
Kim Alvefur <zash@zash.se>
parents:
10580
diff
changeset
|
192 assert(not chunked) |
7076ed654ac9
net.http.parser: Switch to util.dbuffer for buffering incoming data
Kim Alvefur <zash@zash.se>
parents:
10580
diff
changeset
|
193 packet.body = buffer:read(len) or ""; |
11184
2ede7f43ccfe
net.http.parser: Expose 'partial', 'chunked' and 'body_length' on packets
Matthew Wild <mwild1@gmail.com>
parents:
11029
diff
changeset
|
194 state = nil; |
2ede7f43ccfe
net.http.parser: Expose 'partial', 'chunked' and 'body_length' on packets
Matthew Wild <mwild1@gmail.com>
parents:
11029
diff
changeset
|
195 packet.partial = nil; |
2ede7f43ccfe
net.http.parser: Expose 'partial', 'chunked' and 'body_length' on packets
Matthew Wild <mwild1@gmail.com>
parents:
11029
diff
changeset
|
196 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
|
197 else |
e5ec60dfb202
net.http.parser: Break loop when no more usable data in buffer
Matthew Wild <mwild1@gmail.com>
parents:
4879
diff
changeset
|
198 break; |
4631
fc5d3b053454
net.http.{server|codes|parser}: Initial commit.
Waqas Hussain <waqas20@gmail.com>
parents:
diff
changeset
|
199 end |
11020
7076ed654ac9
net.http.parser: Switch to util.dbuffer for buffering incoming data
Kim Alvefur <zash@zash.se>
parents:
10580
diff
changeset
|
200 else |
7076ed654ac9
net.http.parser: Switch to util.dbuffer for buffering incoming data
Kim Alvefur <zash@zash.se>
parents:
10580
diff
changeset
|
201 break; |
4631
fc5d3b053454
net.http.{server|codes|parser}: Initial commit.
Waqas Hussain <waqas20@gmail.com>
parents:
diff
changeset
|
202 end |
fc5d3b053454
net.http.{server|codes|parser}: Initial commit.
Waqas Hussain <waqas20@gmail.com>
parents:
diff
changeset
|
203 end |
fc5d3b053454
net.http.{server|codes|parser}: Initial commit.
Waqas Hussain <waqas20@gmail.com>
parents:
diff
changeset
|
204 end; |
fc5d3b053454
net.http.{server|codes|parser}: Initial commit.
Waqas Hussain <waqas20@gmail.com>
parents:
diff
changeset
|
205 }; |
fc5d3b053454
net.http.{server|codes|parser}: Initial commit.
Waqas Hussain <waqas20@gmail.com>
parents:
diff
changeset
|
206 end |
fc5d3b053454
net.http.{server|codes|parser}: Initial commit.
Waqas Hussain <waqas20@gmail.com>
parents:
diff
changeset
|
207 |
fc5d3b053454
net.http.{server|codes|parser}: Initial commit.
Waqas Hussain <waqas20@gmail.com>
parents:
diff
changeset
|
208 return httpstream; |