X-Git-Url: https://git.enpas.org/?a=blobdiff_plain;f=net%2Fhttp%2Fparser.lua;h=2545b5ac41457b88e345f5a6743650052e43ff40;hb=2c2cf38d1ac841f960da7d36f71fed1d1750ac3f;hp=fdcb8ebba796b51d5edc6e8e490984a127460b0c;hpb=99f81a1075fd60ec006fa6d6c157bfe1ff7bc646;p=prosody.git diff --git a/net/http/parser.lua b/net/http/parser.lua index fdcb8ebb..2545b5ac 100644 --- a/net/http/parser.lua +++ b/net/http/parser.lua @@ -1,6 +1,27 @@ local tonumber = tonumber; local assert = assert; +local url_parse = require "socket.url".parse; +local urldecode = require "net.http".urldecode; + +local function preprocess_path(path) + path = urldecode((path:gsub("//+", "/"))); + if path:sub(1,1) ~= "/" then + path = "/"..path; + end + local level = 0; + for component in path:gmatch("([^/]+)/") do + if component == ".." then + level = level - 1; + elseif component ~= "." then + level = level + 1; + end + if level < 0 then + return nil; + end + end + return path; +end local httpstream = {}; @@ -56,6 +77,7 @@ function httpstream.new(success_cb, error_cb, parser_type, options_cb) end end end + if not first_line then error = true; return error_cb("invalid-status-line"); end len = tonumber(headers["content-length"]); -- TODO check for invalid len if client then -- FIXME handle '100 Continue' response (by skipping it) @@ -70,15 +92,22 @@ function httpstream.new(success_cb, error_cb, parser_type, options_cb) responseheaders = headers; }; else - -- path normalization - if path:match("^https?://") then - headers.host, path = path:match("^https?://([^/]*)(.*)"); + local parsed_url; + if path:byte() == 47 then -- starts with / + local _path, _query = path:match("([^?]*).?(.*)"); + if _query == "" then _query = nil; end + parsed_url = { path = _path, query = _query }; + else + parsed_url = url_parse(path); + if not(parsed_url and parsed_url.path) then error = true; return error_cb("invalid-url"); end end - path = path:gsub("^//+", "/"); -- TODO parse url more + path = preprocess_path(parsed_url.path); + headers.host = parsed_url.host or headers.host; len = len or 0; packet = { method = method; + url = parsed_url; path = path; httpversion = httpversion; headers = headers; @@ -111,6 +140,8 @@ function httpstream.new(success_cb, error_cb, parser_type, options_cb) elseif #buf >= len then packet.body, buf = buf:sub(1, len), buf:sub(len + 1); state = nil; success_cb(packet); + else + break; end end end