diff options
Diffstat (limited to 'script/3rd/lua-uri/uri/_relative.lua')
-rw-r--r-- | script/3rd/lua-uri/uri/_relative.lua | 81 |
1 files changed, 81 insertions, 0 deletions
diff --git a/script/3rd/lua-uri/uri/_relative.lua b/script/3rd/lua-uri/uri/_relative.lua new file mode 100644 index 00000000..8cd53ca7 --- /dev/null +++ b/script/3rd/lua-uri/uri/_relative.lua @@ -0,0 +1,81 @@ +local M = { _NAME = "uri._relative" } +local Util = require "uri._util" +local URI = require "uri" +Util.subclass_of(M, URI) + +-- There needs to be an 'init' method in this class, to because the base-class +-- one expects there to be a 'scheme' value. +function M.init (self) + return self +end + +function M.scheme (self, ...) + if select("#", ...) > 0 then + error("relative URI references can't have a scheme, perhaps you" .. + " need to resolve this against an absolute URI instead") + end + return nil +end + +function M.is_relative () return true end + +-- This implements the algorithm from RFC 3986 section 5.2.3 +-- Note that this takes an additional argument which appears to be required +-- by the algorithm, but isn't shown when it is used in the RFC. +local function _merge_paths (base, r, base_has_auth) + if base_has_auth and base == "" then + return "/" .. r + end + + return base:gsub("[^/]+$", "", 1) .. r +end + +local function _do_resolve (self, base) + if type(base) == "string" then base = assert(URI:new(base)) end + setmetatable(self, URI) + + if self:host() or self:userinfo() or self:port() then + -- network path reference, just needs a scheme + self:path(Util.remove_dot_segments(self:path())) + self:scheme(base:scheme()) + return + end + + local path = self:path() + if path == "" then + self:path(base:path()) + if not self:query() then self:query(base:query()) end + else + if path:find("^/") then + self:path(Util.remove_dot_segments(path)) + else + local base_has_auth = base:host() or base:userinfo() or base:port() + local merged = _merge_paths(base:path(), path, base_has_auth) + self:path(Util.remove_dot_segments(merged)) + end + end + self:host(base:host()) + self:userinfo(base:userinfo()) + self:port(base:port()) + self:scheme(base:scheme()) +end + +function M.resolve (self, base) + local orig = tostring(self) + local ok, result = pcall(_do_resolve, self, base) + if ok then return end + + -- If the resolving causes an exception, it means that the resulting URI + -- would be invalid, so we restore self to its original state and rethrow + -- the exception. + local restored = assert(URI:new(orig)) + for k in pairs(self) do self[k] = nil end + for k, v in pairs(restored) do self[k] = v end + setmetatable(self, getmetatable(restored)) + error("resolved URI reference would be invalid: " .. result) +end + +function M.relativize (self, base) end -- already relative + +return M +-- vi:ts=4 sw=4 expandtab |