Snusmumriken

Uri parser-cleaner

May 26th, 2019
23
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 3.19 KB | None | 0 0
  1.  
  2. local url = {}
  3. url.cleaning = {
  4.     {rx = '&+',     rp = '&'},
  5.     {rx = '=+',     rp = '='},
  6.     {rx = '@+',     rp = '@'},
  7.     {rx = ':+',     rp = ':'},
  8.     {rx = '#+',     rp = '#'},
  9.     {rx = '/+',     rp = '/'},   -- remove all '/'-duplicates
  10.     {rx = '%?+',    rp = '?'},
  11.     {rx = '^%w+:/', rp = '%1/'}, -- restore '/', if scheme is here
  12. }
  13.  
  14. function url.clear(u)
  15.     local sub, subs = 0, 0
  16.     for i, v in pairs(url.cleaning) do
  17.         u, sub = u:gsub(v.rx, v.rp)
  18.         subs = subs + sub
  19.     end
  20.     return u, subs
  21. end
  22.  
  23. -- specific string function, like table.remove returning an erased item
  24. -- a, b = url.extract('qwerty', 'w(er)') --> er, qty
  25. function url.extract(str, regex)
  26.     local a, b, matched = str:find(regex)
  27.     if not a then
  28.         return nil, str
  29.     end
  30.     local head, mid, tail = str:sub(1, a - 1), str:sub(a, b), str:sub(b + 1)
  31.     return matched, head .. tail
  32. end
  33.  
  34. -- average string-split
  35. function url.split(str, delm)
  36.     delm = delm or ' '
  37.     local res = {}
  38.     for line in (str..delm):gmatch('(.-)'..delm) do
  39.         res[#res + 1] = line
  40.     end
  41.     return res
  42. end
  43.  
  44. function url.parse_query(query)
  45.     local res = {}
  46.     for i, line in ipairs(url.split(query, '&')) do
  47.         local k, v = line:match('(.-)=(.*)')
  48.         if k then -- key-value
  49.             res[k] = v
  50.         else      -- flag, like /page?flag1&flag2
  51.             res[line] = true
  52.         end
  53.     end
  54.     return res
  55. end
  56.  
  57. function url.parse(u)
  58.     local res = {}
  59.  
  60.     -- foo://username:[email protected]:8080/hello/world.html/?arg1=val1&arg2=val2#frag
  61.     u = url.clear(u)
  62.  
  63.     -- (foo):// | username:[email protected]:8080/hello/world.html/?arg1=val1&arg2=val2#frag
  64.     local scheme, u = url.extract(u, '^(%w+)://')
  65.     res.scheme = scheme
  66.  
  67.     -- (username:password)@ | www.example.com.net:8080/hello/world.html/?arg1=val1&arg2=val2#frag
  68.     local userdata, u = url.extract(u, '^([^/]+)@')
  69.  
  70.     if userdata then
  71.         res.authority = {}
  72.         -- (username):(password) -- first priority
  73.         local user, pass = userdata:match('([^:]*):?(.*)')
  74.         res.authority.username = user
  75.         res.authority.password = pass
  76.     end
  77.  
  78.     -- (www.example.com.net:8080) | /hello/world.html/?arg1=val1&arg2=val2#frag
  79.     local hostname, u = url.extract(u, '^([^/]+)')
  80.     if hostname then
  81.         res.authority = res.authority or {}
  82.         -- (www.example.com.net):(8080) -- first priority
  83.         local host, port = hostname:match('([^:]*):?(.*)')
  84.         res.authority.hostname = host
  85.         res.authority.port     = port
  86.     end
  87.  
  88.     -- /(hello/world.html/) | ?arg1=val1&arg2=val2#frag
  89.     local path, u = url.extract(u, '^(/[^?]+)')
  90.        
  91.     res.path  = (path or '//'):gsub('/$', '') -- remove endslash, '/' - is default path
  92.     res.ppath = url.split(res.path:sub(2), '/')
  93.  
  94.     -- ?(arg1=val1&arg2=val2) | #frag
  95.     local query, u = url.extract(u, '^?([^#]+)')
  96.     if query then
  97.         res.query  = query
  98.         res.pquery = url.parse_query(query)
  99.     end
  100.  
  101.     -- #(frag)
  102.     local fragment, u = url.extract(u, '^#(.+)')
  103.  
  104.     res.fragment = fragment
  105.  
  106.     return res
  107. end
  108.  
  109. if not ... then return url end
  110.  
  111. return url
Advertisement
Add Comment
Please, Sign In to add comment