@@ -14,8 +14,8 @@ It does not discuss the algorithms nor data structures used by the matching engi
1414## Non-goals
1515
1616- Matching URL fragments (` #section ` )
17- - Matching the URL port (` :8080 ` )
18- - Matching the URL credentials (` user:pass@ ` )
17+ - Matching URL port (` :8080 ` )
18+ - Matching URL credentials (` user:pass@ ` )
1919- Caching
2020- Request/Response handling
2121
@@ -64,7 +64,7 @@ You can use any combination of these to create a route pattern, for example:
6464// ...and so on...
6565```
6666
67- ** Delimiters :** Route patterns use the first occurrences of ` :// ` , ` / ` , and ` ? ` as delimiters to split a route pattern into its parts.
67+ ** Part delimiters :** Route patterns use the first occurrences of ` :// ` , ` / ` , and ` ? ` as delimiters to split a route pattern into its parts.
6868Pathname-only route patterns are the most common, so route patterns are assumed to be pathname-only unless ` :// ` or ` ? ` are present.
6969As a result, hostnames must begin with ` :// ` and searches must begin with ` ? ` to distinguish both from pathnames.
7070
@@ -90,107 +90,35 @@ However, omitting a pathname means "match the 'empty' pathname" (namely `""` and
9090// ✗ doesn't match: https://api.example.com/users
9191```
9292
93-
9493## Pattern modifiers
9594
96- Before describing [ wildcards] ( #wildcards ) , [ params] ( #params ) , and [ optionals] ( #optionals ) ,
97- its important to note that each pattern modifier applies only in the same part of the URL where it appears.
95+ Each pattern modifier — [ param] ( #params ) , [ glob] ( #globs ) , or [ optional] ( #optionals ) — applies only in the same part of the URL where it appears.
9896As a result:
9997
100- - Wildcards and params do not match characters that appear outside of their part of the route pattern
98+ - Params and globs do not match characters that appear outside of their part of the route pattern
10199- Optionals must begin and end within the same part of the route pattern
102100
103- ### Wildcards
104-
105- | | protocol | hostname | pathname | search |
106- | ---------- | -------- | -------- | -------- | ------ |
107- | Supported? | ❌ | ✅ | ✅ | ❌ |
108-
109- Wildcards match dynamic parts of a URL.
110-
111- Route patterns support two types of wildcards:
112-
113- - ` * ` ("star") for matching anything _ within_ a segment
114- - ` ** ` ("star star") for matching anything, even across multiple segments
115-
116- As a result, wildcards correspond to these regular expressions:
117-
118- | | ` * ` | ` ** ` |
119- | -------- | --------- | ------ |
120- | hostname | ` /[^.]*/ ` | ` /.*/ ` |
121- | pathname | ` /[^/]*/ ` | ` /.*/ ` |
122-
123- ``` ts
124- ' /files/*' ;
125- // ✓ matches: /files/photo.jpg
126- // ✗ doesn't match: /files/2023/photo.jpg
127-
128- ' /docs/**' ;
129- // ✓ matches: /docs/api/v1/intro.html
130- // ✗ doesn't match: /docs (no trailing content)
131-
132- ' ://*.example.com' ;
133- // ✓ matches: ://cdn.example.com
134- // ✗ doesn't match: ://api.staging.example.com
135-
136- ' ://**.api.com' ;
137- // ✓ matches: ://tenant.v1.api.com
138- // ✗ doesn't match: ://api.com (no prefix)
139- ```
140-
141- Route patterns can have multiple wildcards, even within the same segment.
142-
143- ``` ts
144- ' /assets/**/static/**/*.css' ;
145- // ✓ matches: /assets/v2/themes/static/dark/main.css
146- // ✗ doesn't match: /assets/v2/themes/static/main.js
147-
148- ' ://us-**.cdn.com/cars/*-*' ;
149- // ✓ matches: ://us-east.staging.cdn.com/cars/audi-a4.jpg
150- // ✗ doesn't match: ://us-east.staging.cdn.com/cars/toyota.jpg
151- ```
152-
153- Wildcards only match characters within the same part of the URL:
154-
155- ``` ts
156- ' ://api.**/users' ;
157- // ✓ matches: ://api.example.com/users
158- // ✗ doesn't match: ://api.example.com/123/users
159- ```
160-
161101### Params
162102
163103| | protocol | hostname | pathname | search |
164104| ---------- | -------- | -------- | -------- | ------ |
165105| Supported? | ❌ | ✅ | ✅ | ❌ |
166106
167- Params, like wildcards, match dynamic parts of the URL but they also give you access to the matched values.
168-
169- A param is written as:
170-
171- - ` : ` followed by a name for capturing anything within a segment (similar to ` * ` )
172- - ` :: ` followed by a name for capturing anything, even across multiple segments (similar to ` ** ` )
173-
174- ** Note:** Param names must be [ JavaScript identifiers] ( #javascript-identifier ) .
107+ Params match dynamic parts of a URL within a segment.
175108
176- As a result, params correspond to these regular expressions:
177-
178- | | ` :<name> ` | ` ::<name> ` |
179- | -------- | ----------- | ---------- |
180- | hostname | ` /([^.]*)/ ` | ` /(.*)/ ` |
181- | pathname | ` /([^/]*)/ ` | ` /(.*)/ ` |
109+ They are written as a ` : ` optionally followed by a [ JavaScript identifier] ( #javascript-identifier ) that acts as its name:
182110
183111``` ts
184112' products/:id' ;
185113// /products/wireless-headphones → { id: 'wireless-headphones' }
186114// /products/123 → { id: '123' }
115+ ```
187116
188- // ❌ Error - missing or invalid param name
189- ' products/:123' ;
117+ When a param name is not given, the matched value won't be returned:
190118
191- ' docs/::path ' ;
192- // /docs/api/v1/intro.html → { path: 'api/v1/intro.html' }
193- // /docs/guide → { path: 'guide' }
119+ ``` ts
120+ ' products/:-shoes ' ;
121+ // /products/tennis-shoes -> { }
194122```
195123
196124Param names must be unique:
@@ -204,13 +132,9 @@ Param names must be unique:
204132
205133// ❌ Bad - duplicate param name across hostname and pathname
206134' ://:region.api.example.com/users/:region' ;
207-
208- // ✅ Good - `::` param captures across segments
209- ' files/::path/download' ;
210- // /files/2023/photos/vacation.jpg/download → { path: '2023/photos/vacation.jpg' }
211135```
212136
213- Params can be mixed with static text, wildcards, and even other params:
137+ Params can be mixed with static text and even other params:
214138
215139``` ts
216140' users/@:id' ;
@@ -222,22 +146,34 @@ Params can be mixed with static text, wildcards, and even other params:
222146' api/v:major.:minor-:channel' ;
223147// /api/v2.1-beta → { major: '2', minor: '1', channel: 'beta' }
224148
225- ' ://:region.:env.api.example.com' ;
226- // us-east.staging.api.example.com → { region: 'us-east', env: 'staging' }
149+ ' ://us-:region.:env.api.example.com' ;
150+ // us-east.staging.api.example.com → { region: 'east', env: 'staging' }
151+ ```
152+
153+ ### Globs
154+
155+ | | protocol | hostname | pathname | search |
156+ | ---------- | -------- | -------- | -------- | ------ |
157+ | Supported? | ❌ | ✅ | ✅ | ❌ |
158+
159+ Globs match dynamic parts of a URL, but — unlike [ params] ( #params ) — they are not limited to a single segment.
227160
228- ' cdn/::path/*.jpg' ;
229- // /cdn/images/2023/vacation.jpg → { path: 'images/2023' }
161+ They are written as a ` * ` optionally followed by a [ JavaScript identifier] ( #javascript-identifier ) that acts as its name:
230162
231- ' ://::subdomain.api.com/:version/*' ;
232- // tenant.v1.api.com/v2/users → { subdomain: 'tenant.v1', version: 'v2' }
163+ ``` ts
164+ // todo
165+ ```
166+
167+ When a glob name is not given, the matched value won't be returned:
168+
169+ ``` ts
170+ // todo
233171```
234172
235- Params only match characters within the same part of the URL :
173+ Globs share a namespace with params :
236174
237175``` ts
238- ' ://api.::domain/users' ;
239- // ✓ matches: ://api.example.com/users → { domain: 'example.com' }
240- // ✗ doesn't match: ://api.example.com/123/users
176+ // todo
241177```
242178
243179### Optionals
@@ -274,23 +210,23 @@ Optionals can span any characters and contain static text, params, or wildcards:
274210// /users/sarah/settings/profile → { id: 'sarah', section: 'profile' }
275211// /users/sarah/settings/profile/edit → { id: 'sarah', section: 'profile' }
276212
277- ' users/:userId(/files/* )' ;
213+ ' users/:userId(/files/: )' ;
278214// /users/sarah → { userId: 'sarah' }
279215// /users/sarah/files/document.pdf → { userId: 'sarah' }
280216
281- ' users/:userId(/docs/** )' ;
217+ ' users/:userId(/docs/*)' ;
282218// /users/sarah → { userId: 'sarah' }
283219// /users/sarah/docs/projects/readme.md → { userId: 'sarah' }
284220
285- ' users/:userId(/files/:: path)' ;
221+ ' users/:userId(/files/* path)' ;
286222// /users/sarah → { userId: 'sarah' }
287223// /users/sarah/files/projects/docs/readme.md → { userId: 'sarah', path: 'projects/docs/readme.md' }
288224
289225' ://(www.)shop.example.com' ;
290226// shop.example.com → {}
291227// www.shop.example.com → {}
292228
293- ' ://(* .)api.example.com(/v* )' ;
229+ ' ://(: .)api.example.com(/v: )' ;
294230// api.example.com → {}
295231// cdn.api.example.com/v2 → {}
296232```
0 commit comments