Skip to content

Commit 56e24ad

Browse files
committed
feat(urlpattern): add WHATWG URLPattern support
Implement WHATWG-style URLPattern parsing, compilation, matching, generation, and component comparison with cache-backed reuse. Integrate matched params with AsyncContext and initialize the shared URLPattern params variable at application boot so route context stays stable across processes. Regroup normalize_component_input/2 clauses to remove the compiler warning, add defensive coverage for URLPattern edge cases, and document the new API in the README and changelog.
1 parent 5d35f7f commit 56e24ad

14 files changed

Lines changed: 4943 additions & 0 deletions

File tree

CHANGELOG.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,11 @@ All notable changes to this project are documented in this file.
88

99
- `Web.File`.
1010
- `Web.FormData` struct and streaming multipart parser.
11+
- `Web.URLPattern` with WHATWG-style pattern parsing, compilation, matching,
12+
generation, component comparison, and ambient route param injection via
13+
`match_context/3`.
14+
- `Web.URLPattern.Cache`, `Web.URLPattern.Parser`, and
15+
`Web.URLPattern.Compiler`.
1116
- `Web.AsyncContext` for BEAM-native async context propagation.
1217
- `Web.AsyncContext.Variable` for scoped context values that participate in
1318
snapshot capture and restoration.
@@ -48,6 +53,9 @@ All notable changes to this project are documented in this file.
4853
- `Web.FormData.Parser` now captures and restores `Web.AsyncContext`
4954
snapshots, auto-binds to ambient abort signals, and propagates that context
5055
into live file streams it creates on demand.
56+
- `Web.Application` now eagerly initializes the singleton
57+
`Web.URLPattern.params/0` variable during boot so route-param context stays
58+
stable across processes in async workloads and tests.
5159
- `Web.Console.group/1` now keeps `group_depth` in logger metadata so grouped
5260
output survives async-context snapshot restore across task boundaries.
5361
- `Web.CompressionStream` and `Web.DecompressionStream` now emit context-aware

README.md

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,35 @@ end)
124124
# => ["req-42"]
125125
```
126126

127+
### `Web.URLPattern` — Spec-Compliant Routing and URL Matching
128+
`Web.URLPattern` implements the WHATWG URLPattern API for matching URL strings,
129+
`Web.URL` structs, requests, or component maps. It also bridges naturally into
130+
`Web.AsyncContext`, so successful matches can expose captured params to
131+
downstream work with `match_context/3`.
132+
133+
```elixir
134+
use Web
135+
136+
pattern =
137+
URLPattern.new(%{
138+
protocol: "https",
139+
hostname: "example.com",
140+
pathname: "/users/:id"
141+
})
142+
143+
URLPattern.test(pattern, "https://example.com/users/42")
144+
# => true
145+
146+
result = URLPattern.exec(pattern, "https://example.com/users/42")
147+
result[:pathname][:groups]
148+
# => %{"id" => "42"}
149+
150+
URLPattern.match_context(pattern, "https://example.com/users/42", fn ->
151+
AsyncContext.Variable.get(URLPattern.params())
152+
end)
153+
# => %{"id" => "42"}
154+
```
155+
127156
---
128157

129158
## 📖 API Usage & Examples

coveralls.json

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
{
2+
"skip_files": [
3+
"test/support/wpt.ex"
4+
]
5+
}

lib/web/application.ex

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,14 @@ defmodule Web.Application do
77
def start(_type, _args) do
88
Web.Performance.put_time_origin()
99

10+
# Eagerly initialize the url_params singleton in :persistent_term so that
11+
# the Variable handle is stable across all processes from the moment the
12+
# application boots.
13+
Web.URLPattern.params()
14+
1015
children = [
1116
{Task.Supervisor, name: Web.TaskSupervisor},
17+
Web.URLPattern.Cache,
1218
{Finch,
1319
name: Web.Finch,
1420
pools: %{

0 commit comments

Comments
 (0)