Beta documentation. This is an early preview — content is still in active development. Feedback helps shape the final release. Share your thoughts or join the discussion.

URL Utilities

The `url` library handles everything URL-related — encoding, decoding, parsing, building, and generating slugs.

On this page

URL manipulation done right

The url library handles everything URL-related — encoding, decoding, parsing, building, and generating slugs.

Function reference

Function Example Result
url.encode(s) url.encode("hello world") "hello+world"
url.decode(s) url.decode("hello+world") "hello world"
url.rawencode(s) url.rawencode("hello world") "hello%20world"
url.rawdecode(s) url.rawdecode("hello%20world") "hello world"
url.parse(url) url.parse("https://ex.com/path?q=1") { scheme, host, path, query }
url.build(parts) url.build({ host, path, query }) "example.com/test?a=1"
url.slug(s) url.slug("Hello World! 2026") "hello-world-2026"
url.redirect(url) url.redirect("/dashboard") Sends 302 redirect immediately

url.encode vs url.rawencode

-- Form encoding: spaces → +
url.encode("hello world")    → "hello+world"

-- RFC 3986: spaces → %20
url.rawencode("hello world") → "hello%20world"

Use rawencode for URL paths, encode for query strings.

Parsing a URL

local parts = url.parse("https://example.com:8080/path/to/page?q=lua&page=2")
-- {
--   scheme = "https",
--   host = "example.com",
--   port = "8080",
--   path = "/path/to/page",
--   query = "q=lua&page=2"
-- }

print(parts.host)  -- "example.com"

Building a URL

local link = url.build({
    scheme = "https",
    host = "mysite.wapka.site",
    path = "/blog/" .. slug,
    query = "utm_source=newsletter"
})
-- → "https://mysite.wapka.site/blog/hello-world?utm_source=newsletter"

Note: url.build() supports scheme, host, path, and query keys only. Port, fragment, and userinfo are not handled.

Generating slugs for SEO

-- Create clean URLs from titles
local title = "How to Build a Lua API in 10 Minutes"
local slug = url.slug(title)
-- → "how-to-build-a-lua-api-in-10-minutes"

-- Use it in a route
app:get("/blog/" .. slug, postHandler)

Quick redirect

-- Redirect and stop execution immediately
url.redirect("/login")

-- For custom status codes, use ctx:redirect instead
ctx:redirect("/new-location", 301)

Practical: building a search URL

app:post("/search", function(ctx)
    local q = url.encode(req.post.query)
    return ctx:redirect("/search?q=" .. q)
end)

app:get("/search", function(ctx)
    local query = req.query.q
    if not query then
        return ctx:render("search", { results = {} })
    end

    local results = api.dataset.find("articles", {
        filter = { title = { like = "%" .. query .. "%" } }
    })

    return ctx:render("search", {
        query = query,
        results = results.items
    })
end)

Next: Encoder — convert data between formats.

Previous HTTP Client Next Encoder