url.lua: separate remove_dot_components() from absolute_path(); also use in _M.absolute() even when not merging

This commit is contained in:
E. Westbrook 2018-08-21 08:03:51 -06:00
parent 17a95c126a
commit c905b5d44f
2 changed files with 40 additions and 23 deletions

View file

@ -76,6 +76,28 @@ function _M.unescape(s)
end))
end
-----------------------------------------------------------------------------
-- Removes '..' and '.' components appropriately from a path.
-- Input
-- path
-- Returns
-- dot-normalized path
local function remove_dot_components(path)
repeat
local was = path
path = path:gsub('/%./', '/')
until path == was
repeat
local was = path
path = path:gsub('[^/]+/%.%./([^/]+)', '%1')
until path == was
path = path:gsub('[^/]+/%.%./*$', '')
path = path:gsub('/%.%.$', '/')
path = path:gsub('/%.$', '/')
path = path:gsub('^/%.%.', '')
return path
end
-----------------------------------------------------------------------------
-- Builds a path from a base path and a relative path
-- Input
@ -85,21 +107,11 @@ end
-- corresponding absolute path
-----------------------------------------------------------------------------
local function absolute_path(base_path, relative_path)
if string.sub(relative_path, 1, 1) == "/" then return relative_path end
local path = string.gsub(base_path, "[^/]*$", "")
path = path .. relative_path
repeat
local was = path
path = path:gsub('/%./', '/')
until path == was
repeat
local was = path
path = path:gsub('[^/]+/%.%./([^/]+)', '%1')
until path == was
path = path:gsub('[^/]+/%.%./*$', '')
path = path:gsub('/%.%.$', '/')
path = path:gsub('/%.$', '/')
path = path:gsub('^/%.%.', '')
if string.sub(relative_path, 1, 1) == "/" then
return remove_dot_components(relative_path) end
base_path = base_path:gsub("[^/]*$", "")
local path = base_path .. relative_path
path = remove_dot_components(path)
return path
end
@ -225,10 +237,14 @@ function _M.absolute(base_url, relative_url)
else
base_parsed = _M.parse(base_url)
end
local result
local relative_parsed = _M.parse(relative_url)
if not base_parsed then return relative_url
elseif not relative_parsed then return base_url
elseif relative_parsed.scheme then return relative_url
if not base_parsed then
result = relative_url
elseif not relative_parsed then
result = base_url
elseif relative_parsed.scheme then
result = relative_url
else
relative_parsed.scheme = base_parsed.scheme
if not relative_parsed.authority then
@ -246,8 +262,9 @@ function _M.absolute(base_url, relative_url)
relative_parsed.path)
end
end
return _M.build(relative_parsed)
result = _M.build(relative_parsed)
end
return remove_dot_components(result)
end
-----------------------------------------------------------------------------