author | Kim Alvefur <zash@zash.se> |
Wed, 23 Aug 2023 12:18:34 +0200 | |
branch | 0.12 |
changeset 13382 | db30ffbf2090 |
parent 12893 | 94a99330ce87 |
child 13383 | 977d92aff563 |
permissions | -rw-r--r-- |
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; |
11024
7076ed654ac9
net.http.parser: Switch to util.dbuffer for buffering incoming data
Kim Alvefur <zash@zash.se>
parents:
10584
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 |
7581
65bf55fdf971
net.http.parser: Allow limits to be configurable via options callback
Kim Alvefur <zash@zash.se>
parents:
7580
diff
changeset
|
31 |
local bodylimit = tonumber(options_cb and options_cb().body_size_limit) or 10*1024*1024; |
11024
7076ed654ac9
net.http.parser: Switch to util.dbuffer for buffering incoming data
Kim Alvefur <zash@zash.se>
parents:
10584
diff
changeset
|
32 |
-- https://stackoverflow.com/a/686243 |
11731
f3aee8a825cc
Fix various spelling errors (thanks codespell)
Kim Alvefur <zash@zash.se>
parents:
11188
diff
changeset
|
33 |
-- Individual headers can be up to 16k? What madness? |
11024
7076ed654ac9
net.http.parser: Switch to util.dbuffer for buffering incoming data
Kim Alvefur <zash@zash.se>
parents:
10584
diff
changeset
|
34 |
local headlimit = tonumber(options_cb and options_cb().head_size_limit) or 10*1024; |
7581
65bf55fdf971
net.http.parser: Allow limits to be configurable via options callback
Kim Alvefur <zash@zash.se>
parents:
7580
diff
changeset
|
35 |
local buflimit = tonumber(options_cb and options_cb().buffer_size_limit) or bodylimit * 2; |
11024
7076ed654ac9
net.http.parser: Switch to util.dbuffer for buffering incoming data
Kim Alvefur <zash@zash.se>
parents:
10584
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:
10584
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 { |
7572
a15ce0014ac9
net.http.parser: Remove unused argument [luacheck]
Kim Alvefur <zash@zash.se>
parents:
6526
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 |
11024
7076ed654ac9
net.http.parser: Switch to util.dbuffer for buffering incoming data
Kim Alvefur <zash@zash.se>
parents:
10584
diff
changeset
|
48 |
buffer:collapse(); |
7076ed654ac9
net.http.parser: Switch to util.dbuffer for buffering incoming data
Kim Alvefur <zash@zash.se>
parents:
10584
diff
changeset
|
49 |
packet.body = buffer:read_chunk() or ""; |
11188
2ede7f43ccfe
net.http.parser: Expose 'partial', 'chunked' and 'body_length' on packets
Matthew Wild <mwild1@gmail.com>
parents:
11033
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); |
11024
7076ed654ac9
net.http.parser: Switch to util.dbuffer for buffering incoming data
Kim Alvefur <zash@zash.se>
parents:
10584
diff
changeset
|
52 |
state = nil; |
7076ed654ac9
net.http.parser: Switch to util.dbuffer for buffering incoming data
Kim Alvefur <zash@zash.se>
parents:
10584
diff
changeset
|
53 |
elseif buffer:length() ~= 0 then -- unexpected EOF |
8048
55a56dc935f2
net.http: Pass error all the way to callback
Kim Alvefur <zash@zash.se>
parents:
7638
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 |
11024
7076ed654ac9
net.http.parser: Switch to util.dbuffer for buffering incoming data
Kim Alvefur <zash@zash.se>
parents:
10584
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:
10584
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 |
11024
7076ed654ac9
net.http.parser: Switch to util.dbuffer for buffering incoming data
Kim Alvefur <zash@zash.se>
parents:
10584
diff
changeset
|
61 |
local index = buffer:sub(1, headlimit):find("\r\n\r\n", nil, true); |
13382
db30ffbf2090
net.http.parser: Reject overlarge header section earlier
Kim Alvefur <zash@zash.se>
parents:
12893
diff
changeset
|
62 |
if not index then |
db30ffbf2090
net.http.parser: Reject overlarge header section earlier
Kim Alvefur <zash@zash.se>
parents:
12893
diff
changeset
|
63 |
if buffer:length() > headlimit then |
db30ffbf2090
net.http.parser: Reject overlarge header section earlier
Kim Alvefur <zash@zash.se>
parents:
12893
diff
changeset
|
64 |
return error_cb("header-too-large"); |
db30ffbf2090
net.http.parser: Reject overlarge header section earlier
Kim Alvefur <zash@zash.se>
parents:
12893
diff
changeset
|
65 |
end |
db30ffbf2090
net.http.parser: Reject overlarge header section earlier
Kim Alvefur <zash@zash.se>
parents:
12893
diff
changeset
|
66 |
-- not enough data |
db30ffbf2090
net.http.parser: Reject overlarge header section earlier
Kim Alvefur <zash@zash.se>
parents:
12893
diff
changeset
|
67 |
return; |
db30ffbf2090
net.http.parser: Reject overlarge header section earlier
Kim Alvefur <zash@zash.se>
parents:
12893
diff
changeset
|
68 |
end |
10544
375d31225d53
net.http.parser: Silence warning about unused variable [luacheck]
Kim Alvefur <zash@zash.se>
parents:
8048
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:
8048
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 = {}; |
11024
7076ed654ac9
net.http.parser: Switch to util.dbuffer for buffering incoming data
Kim Alvefur <zash@zash.se>
parents:
10584
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; |
11024
7076ed654ac9
net.http.parser: Switch to util.dbuffer for buffering incoming data
Kim Alvefur <zash@zash.se>
parents:
10584
diff
changeset
|
105 |
body = false; |
11188
2ede7f43ccfe
net.http.parser: Expose 'partial', 'chunked' and 'body_length' on packets
Matthew Wild <mwild1@gmail.com>
parents:
11033
diff
changeset
|
106 |
body_length = len; |
2ede7f43ccfe
net.http.parser: Expose 'partial', 'chunked' and 'body_length' on packets
Matthew Wild <mwild1@gmail.com>
parents:
11033
diff
changeset
|
107 |
chunked = chunked; |
2ede7f43ccfe
net.http.parser: Expose 'partial', 'chunked' and 'body_length' on packets
Matthew Wild <mwild1@gmail.com>
parents:
11033
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; |
11024
7076ed654ac9
net.http.parser: Switch to util.dbuffer for buffering incoming data
Kim Alvefur <zash@zash.se>
parents:
10584
diff
changeset
|
133 |
body = false; |
7076ed654ac9
net.http.parser: Switch to util.dbuffer for buffering incoming data
Kim Alvefur <zash@zash.se>
parents:
10584
diff
changeset
|
134 |
body_sink = nil; |
11188
2ede7f43ccfe
net.http.parser: Expose 'partial', 'chunked' and 'body_length' on packets
Matthew Wild <mwild1@gmail.com>
parents:
11033
diff
changeset
|
135 |
chunked = chunked; |
2ede7f43ccfe
net.http.parser: Expose 'partial', 'chunked' and 'body_length' on packets
Matthew Wild <mwild1@gmail.com>
parents:
11033
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 |
12886
9ed628635dc6
net.http.parser: Improve handling of responses without content-length
Matthew Wild <mwild1@gmail.com>
parents:
11731
diff
changeset
|
139 |
if not len or len > bodylimit then |
11025
9673c95895fb
net.http.parser: Allow specifying sink for large request bodies
Kim Alvefur <zash@zash.se>
parents:
11024
diff
changeset
|
140 |
-- Early notification, for redirection |
9673c95895fb
net.http.parser: Allow specifying sink for large request bodies
Kim Alvefur <zash@zash.se>
parents:
11024
diff
changeset
|
141 |
success_cb(packet); |
12886
9ed628635dc6
net.http.parser: Improve handling of responses without content-length
Matthew Wild <mwild1@gmail.com>
parents:
11731
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:
11731
diff
changeset
|
143 |
error = true; |
9ed628635dc6
net.http.parser: Improve handling of responses without content-length
Matthew Wild <mwild1@gmail.com>
parents:
11731
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:
11731
diff
changeset
|
145 |
end |
11025
9673c95895fb
net.http.parser: Allow specifying sink for large request bodies
Kim Alvefur <zash@zash.se>
parents:
11024
diff
changeset
|
146 |
end |
9673c95895fb
net.http.parser: Allow specifying sink for large request bodies
Kim Alvefur <zash@zash.se>
parents:
11024
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:
11024
diff
changeset
|
148 |
success_cb(packet); |
9673c95895fb
net.http.parser: Allow specifying sink for large request bodies
Kim Alvefur <zash@zash.se>
parents:
11024
diff
changeset
|
149 |
if not packet.body_sink then |
11033
5550fc5e83f3
net.http.parser: Fix indentation
Kim Alvefur <zash@zash.se>
parents:
11025
diff
changeset
|
150 |
packet.body_buffer = dbuffer.new(buflimit); |
5550fc5e83f3
net.http.parser: Fix indentation
Kim Alvefur <zash@zash.se>
parents:
11025
diff
changeset
|
151 |
end |
11025
9673c95895fb
net.http.parser: Allow specifying sink for large request bodies
Kim Alvefur <zash@zash.se>
parents:
11024
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 |
11024
7076ed654ac9
net.http.parser: Switch to util.dbuffer for buffering incoming data
Kim Alvefur <zash@zash.se>
parents:
10584
diff
changeset
|
156 |
if chunked then |
7076ed654ac9
net.http.parser: Switch to util.dbuffer for buffering incoming data
Kim Alvefur <zash@zash.se>
parents:
10584
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:
10584
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:
10584
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:
10584
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:
10584
diff
changeset
|
161 |
if not chunk_size then error = true; return error_cb("invalid-chunk-size"); end |
12893
94a99330ce87
net.http.parser: Fix off-by-one error in chunk parser
Matthew Wild <mwild1@gmail.com>
parents:
12886
diff
changeset
|
162 |
|
11024
7076ed654ac9
net.http.parser: Switch to util.dbuffer for buffering incoming data
Kim Alvefur <zash@zash.se>
parents:
10584
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:
10584
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:
10584
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:
10584
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:
10584
diff
changeset
|
167 |
body_buffer:collapse(); |
7076ed654ac9
net.http.parser: Switch to util.dbuffer for buffering incoming data
Kim Alvefur <zash@zash.se>
parents:
10584
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 |
11024
7076ed654ac9
net.http.parser: Switch to util.dbuffer for buffering incoming data
Kim Alvefur <zash@zash.se>
parents:
10584
diff
changeset
|
170 |
|
7076ed654ac9
net.http.parser: Switch to util.dbuffer for buffering incoming data
Kim Alvefur <zash@zash.se>
parents:
10584
diff
changeset
|
171 |
buffer:collapse(); |
7076ed654ac9
net.http.parser: Switch to util.dbuffer for buffering incoming data
Kim Alvefur <zash@zash.se>
parents:
10584
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:
10584
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:
10584
diff
changeset
|
174 |
buffer:write(buf); |
7076ed654ac9
net.http.parser: Switch to util.dbuffer for buffering incoming data
Kim Alvefur <zash@zash.se>
parents:
10584
diff
changeset
|
175 |
state, chunked = nil, nil; |
11188
2ede7f43ccfe
net.http.parser: Expose 'partial', 'chunked' and 'body_length' on packets
Matthew Wild <mwild1@gmail.com>
parents:
11033
diff
changeset
|
176 |
packet.partial = nil; |
11024
7076ed654ac9
net.http.parser: Switch to util.dbuffer for buffering incoming data
Kim Alvefur <zash@zash.se>
parents:
10584
diff
changeset
|
177 |
success_cb(packet); |
12893
94a99330ce87
net.http.parser: Fix off-by-one error in chunk parser
Matthew Wild <mwild1@gmail.com>
parents:
12886
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:
12886
diff
changeset
|
179 |
buffer:discard(chunk_start - 1); |
11025
9673c95895fb
net.http.parser: Allow specifying sink for large request bodies
Kim Alvefur <zash@zash.se>
parents:
11024
diff
changeset
|
180 |
(packet.body_sink or packet.body_buffer):write(buffer:read(chunk_size)); |
11024
7076ed654ac9
net.http.parser: Switch to util.dbuffer for buffering incoming data
Kim Alvefur <zash@zash.se>
parents:
10584
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:
10584
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 |
11025
9673c95895fb
net.http.parser: Allow specifying sink for large request bodies
Kim Alvefur <zash@zash.se>
parents:
11024
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:
11024
diff
changeset
|
186 |
local chunk = buffer:read_chunk(len); |
12886
9ed628635dc6
net.http.parser: Improve handling of responses without content-length
Matthew Wild <mwild1@gmail.com>
parents:
11731
diff
changeset
|
187 |
while chunk and (not len or len > 0) do |
11025
9673c95895fb
net.http.parser: Allow specifying sink for large request bodies
Kim Alvefur <zash@zash.se>
parents:
11024
diff
changeset
|
188 |
if packet.body_sink:write(chunk) then |
12886
9ed628635dc6
net.http.parser: Improve handling of responses without content-length
Matthew Wild <mwild1@gmail.com>
parents:
11731
diff
changeset
|
189 |
if len then |
9ed628635dc6
net.http.parser: Improve handling of responses without content-length
Matthew Wild <mwild1@gmail.com>
parents:
11731
diff
changeset
|
190 |
len = len - #chunk; |
9ed628635dc6
net.http.parser: Improve handling of responses without content-length
Matthew Wild <mwild1@gmail.com>
parents:
11731
diff
changeset
|
191 |
end |
11025
9673c95895fb
net.http.parser: Allow specifying sink for large request bodies
Kim Alvefur <zash@zash.se>
parents:
11024
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:
11024
diff
changeset
|
193 |
else |
9673c95895fb
net.http.parser: Allow specifying sink for large request bodies
Kim Alvefur <zash@zash.se>
parents:
11024
diff
changeset
|
194 |
error = true; |
9673c95895fb
net.http.parser: Allow specifying sink for large request bodies
Kim Alvefur <zash@zash.se>
parents:
11024
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:
11024
diff
changeset
|
196 |
end |
9673c95895fb
net.http.parser: Allow specifying sink for large request bodies
Kim Alvefur <zash@zash.se>
parents:
11024
diff
changeset
|
197 |
end |
11188
2ede7f43ccfe
net.http.parser: Expose 'partial', 'chunked' and 'body_length' on packets
Matthew Wild <mwild1@gmail.com>
parents:
11033
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:
11033
diff
changeset
|
199 |
state = nil; |
2ede7f43ccfe
net.http.parser: Expose 'partial', 'chunked' and 'body_length' on packets
Matthew Wild <mwild1@gmail.com>
parents:
11033
diff
changeset
|
200 |
packet.partial = nil; |
2ede7f43ccfe
net.http.parser: Expose 'partial', 'chunked' and 'body_length' on packets
Matthew Wild <mwild1@gmail.com>
parents:
11033
diff
changeset
|
201 |
success_cb(packet); |
2ede7f43ccfe
net.http.parser: Expose 'partial', 'chunked' and 'body_length' on packets
Matthew Wild <mwild1@gmail.com>
parents:
11033
diff
changeset
|
202 |
end |
12886
9ed628635dc6
net.http.parser: Improve handling of responses without content-length
Matthew Wild <mwild1@gmail.com>
parents:
11731
diff
changeset
|
203 |
elseif not len or buffer:length() >= len then -- or not len |
11024
7076ed654ac9
net.http.parser: Switch to util.dbuffer for buffering incoming data
Kim Alvefur <zash@zash.se>
parents:
10584
diff
changeset
|
204 |
assert(not chunked) |
12886
9ed628635dc6
net.http.parser: Improve handling of responses without content-length
Matthew Wild <mwild1@gmail.com>
parents:
11731
diff
changeset
|
205 |
packet.body = len and buffer:read(len) or buffer:read_chunk() or ""; |
11188
2ede7f43ccfe
net.http.parser: Expose 'partial', 'chunked' and 'body_length' on packets
Matthew Wild <mwild1@gmail.com>
parents:
11033
diff
changeset
|
206 |
state = nil; |
2ede7f43ccfe
net.http.parser: Expose 'partial', 'chunked' and 'body_length' on packets
Matthew Wild <mwild1@gmail.com>
parents:
11033
diff
changeset
|
207 |
packet.partial = nil; |
2ede7f43ccfe
net.http.parser: Expose 'partial', 'chunked' and 'body_length' on packets
Matthew Wild <mwild1@gmail.com>
parents:
11033
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 |
11024
7076ed654ac9
net.http.parser: Switch to util.dbuffer for buffering incoming data
Kim Alvefur <zash@zash.se>
parents:
10584
diff
changeset
|
212 |
else |
7076ed654ac9
net.http.parser: Switch to util.dbuffer for buffering incoming data
Kim Alvefur <zash@zash.se>
parents:
10584
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; |