The URL interface provides comprehensive URL parsing, encoding, and manipulation capabilities similar to Python's urllib.parse module. It supports RFC 3986 compliant URL handling with features for encoding/decoding, query string manipulation, URL joining, and component extraction.
The module is designed for HTTP client/server development, web API integration, and any application requiring robust URL manipulation.
It can be loaded with the line:
local url = require('net/url')
encoded = url.encode(String, ExtraChars)
Percent-encodes a string for safe URL use, encoding reserved characters according to RFC 3986.
local encoded = url.encode('hello world!')
-- Result: 'hello%20world%21'
local encoded = url.encode('user@domain.com')
-- Result: 'user%40domain.com'
The optional ExtraChars
parameter allows additional characters to be encoded beyond the standard reserved set.
encoded = url.encodePlus(String, ExtraChars)
Percent-encodes a string with spaces converted to plus signs, suitable for form data encoding.
local encoded = url.encodePlus('hello world')
-- Result: 'hello+world'
decoded = url.decode(String)
Decodes a percent-encoded string back to its original form.
local decoded = url.decode('hello%20world%21')
-- Result: 'hello world!'
decoded = url.decodePlus(String)
Decodes a percent-encoded string with plus signs converted to spaces.
local decoded = url.decodePlus('hello+world')
-- Result: 'hello world'
encoded = url.encodeComponent(String)
Encodes a string for safe use in URL path components.
local encoded = url.encodeComponent('file name.txt')
-- Result: 'file%20name.txt'
params = url.parseQuery(QueryString)
Parses a query string into a table of key-value pairs. Duplicate keys are automatically converted to arrays.
local params = url.parseQuery('name=John&age=30&tag=red&tag=blue')
-- Result: { name = 'John', age = '30', tag = { 'red', 'blue' } }
params = url.parseQueryList(QueryString)
Parses a query string into an ordered list of key-value pairs, preserving parameter order and duplicates.
local params = url.parseQueryList('first=1&second=2&first=3')
-- Result: {
-- { key = 'first', value = '1' },
-- { key = 'second', value = '2' },
-- { key = 'first', value = '3' }
-- }
queryString = url.buildQuery(Params)
Builds a query string from a table or list of parameters.
local params = { name = 'John Doe', age = 30 }
local query = url.buildQuery(params)
-- Result: 'name=John+Doe&age=30'
local list = { { key = 'first', value = '1' }, { key = 'second', value = '2' } }
local query = url.buildQuery(list)
-- Result: 'first=1&second=2'
queryString = url.encodeParams(Params)
Alias for url.buildQuery()
- encodes parameters into query string format.
components = url.parse(UrlString)
Parses a URL into its component parts, returning a table with the following fields:
Field | Description |
---|---|
scheme | Protocol scheme (e.g., 'http', 'https', 'ftp') |
auth | Authentication information (user:password) |
host | Hostname or IP address |
port | Port number (as integer) |
path | Path component |
params | Path parameters (after semicolon) |
query | Query string (after question mark) |
fragment | Fragment identifier (after hash) |
local parts = url.parse('https://user:pass@example.com:8080/path?query=value#section')
-- Result: {
-- scheme = 'https',
-- auth = 'user:pass',
-- host = 'example.com',
-- port = 8080,
-- path = '/path',
-- query = 'query=value',
-- fragment = 'section'
-- }
urlString = url.unparse(Components)
Reconstructs a URL from component parts.
local components = {
scheme = 'https',
host = 'example.com',
path = '/api/users',
query = 'limit=10'
}
local url = url.unparse(components)
-- Result: 'https://example.com/api/users?limit=10'
components = url.split(UrlString)
Splits a URL into 5 basic components (scheme, netloc, path, query, fragment) similar to Python's urlsplit.
local parts = url.split('https://example.com:8080/path?query=value#section')
-- Result: {
-- scheme = 'https',
-- netloc = 'example.com:8080',
-- path = '/path',
-- query = 'query=value',
-- fragment = 'section'
-- }
urlString = url.unsplit(Components)
Reconstructs a URL from split components.
base, fragment = url.defrag(UrlString)
Removes and returns the fragment portion of a URL.
local base, frag = url.defrag('https://example.com/path#section')
-- base = 'https://example.com/path'
-- frag = 'section'
joinedUrl = url.join(BaseUrl, RelativeUrl)
Joins a base URL with a relative URL, handling path resolution and normalisation.
local joined = url.join('https://example.com/api/', 'users/123')
-- Result: 'https://example.com/api/users/123'
local joined = url.join('https://example.com/api/v1/', '../v2/users')
-- Result: 'https://example.com/api/v2/users'
normalizedPath = url.normalize(Path)
Normalises a URL path by resolving .
and ..
components.
local normalized = url.normalize('/api/v1/../v2/./users')
-- Result: '/api/v2/users'
isAbs = url.isAbsolute(UrlString)
Returns true if the URL is absolute (contains a scheme).
local isAbs = url.isAbsolute('https://example.com') -- true
local isAbs = url.isAbsolute('/relative/path') -- false
isRel = url.isRelative(UrlString)
Returns true if the URL is relative (no scheme).
scheme = url.getScheme(UrlString)
Extracts and returns the scheme from a URL.
local scheme = url.getScheme('https://example.com')
-- Result: 'https'
host = url.getHost(UrlString)
Extracts and returns the hostname from a URL.
local host = url.getHost('https://example.com:8080/path')
-- Result: 'example.com'
port = url.getPort(UrlString, DefaultPort)
Extracts the port number from a URL, optionally returning a default if no port is specified.
local port = url.getPort('https://example.com:8080') -- 8080
local port = url.getPort('https://example.com') -- nil
local port = url.getPort('https://example.com', 443) -- 443
The URL parser fully supports IPv6 addresses in URLs:
local parts = url.parse('http://[2001:db8::1]:8080/path')
-- parts.host = '2001:db8::1'
-- parts.port = 8080
URL parsing functions return nil
for invalid input:
local parts = url.parse('') -- returns nil
local parts = url.parse(nil) -- returns nil
The module follows RFC 3986 standards for URL parsing and encoding, ensuring proper handling of reserved characters and edge cases.
local base = 'https://api.example.com/v1/'
local endpoint = url.join(base, 'users/search')
local params = { q = 'john doe', limit = 10, active = true }
local query = url.buildQuery(params)
local apiUrl = endpoint .. '?' .. query
-- Result: 'https://api.example.com/v1/users/search?q=john+doe&limit=10&active=true'
local requestUrl = 'https://example.com/api/users?name=John&age=30#profile'
local parts = url.parse(requestUrl)
local queryParams = url.parseQuery(parts.query)
print('Host:', parts.host) -- example.com
print('Path:', parts.path) -- /api/users
print('Name:', queryParams.name) -- John
print('Fragment:', parts.fragment) -- profile
local userInput = 'file with spaces & special chars!'
local safePath = url.encodeComponent(userInput)
local fullUrl = url.join('https://cdn.example.com/files/', safePath)
-- Result: 'https://cdn.example.com/files/file%20with%20spaces%20%26%20special%20chars%21'