Router → Wildcards & Globs

Wildcards & Globs

Use * to match exactly one unnamed segment, or ** to consume all remaining segments. Both are captured into req.captures[] in order.

Single wildcard — *

* matches any one path segment. The matched value is stored as a string in req.captures[n], where n is the left-to-right index of that wildcard in the pattern.

-- matches: asset/sword/preview, asset/shield/preview, …
app:Get("asset/*/preview", function(req, res)
    print(req.captures[1])  -- "sword", "shield" …
end)

Multiple wildcards

Each * gets its own sequential index in req.captures.

-- matches: zone/forest/item/axe, zone/cave/item/torch, …
app:Get("zone/*/item/*", function(req, res)
    print(req.captures[1])  -- zone name, e.g. "forest"
    print(req.captures[2])  -- item name, e.g. "axe"
end)

Glob — **

** must appear at the end of the pattern. It matches zero or more remaining segments and stores them as a table of strings in req.captures[1].

-- matches: assets/a  assets/a/b  assets/a/b/c …
app:Get("assets/**", function(req, res)
    -- req.captures[1] = { "a", "b", "c" }
    print(table.concat(req.captures[1], "/"))
end)
Zero segments. ** matches even when there are no trailing segments. In that case req.captures[1] is an empty table {}.

Captures reference

PatternMatchesCaptured inValue type
item/*Any single segment after item/req.captures[1]string
zone/*/item/*Two unnamed segmentsreq.captures[1], req.captures[2]string, string
files/**Zero or more trailing segmentsreq.captures[1]table of strings

Route priority

Wildcards are lower priority than named params, and globs are lowest of all. Literal segments beat everything. Registration order breaks ties within the same specificity level.

Priority (high → low)Example
Literalitem/sword
Constrained paramitem/:id(%d+)
Typed paramitem/:id=number
Plain paramitem/:id
Wildcarditem/*
Globitem/**

See also

← Router  ·  Named Params | named captures with type coercion  ·  Constraints | Lua pattern restrictions  ·  App | route registration methods