reitit/doc/basics/route_syntax.md

163 lines
4.3 KiB
Markdown
Raw Permalink Normal View History

2017-10-29 07:29:06 +00:00
# Route Syntax
Routes are defined as vectors of:
- path (a string)
- optional route data: usually a map, but see [Route Data](./route_data.md)
- any number of child routes
Routes can be wrapped in vectors and lists and `nil` routes are ignored.
2019-06-09 17:46:20 +00:00
Paths can have path-parameters (`:id`) or catch-all-parameters (`*path`). Parameters can also be wrapped in brackets, enabling use of qualified keywords `{user/id}`, `{*user/path}`. By default, both syntaxes are supported, see [configuring routers](../advanced/configuring_routers.md) on how to change this.
### Examples
2017-10-29 07:29:06 +00:00
Simple route:
```clj
["/ping" {:handler ping}]
2017-10-29 07:29:06 +00:00
```
Two routes with more data:
2017-10-29 07:29:06 +00:00
```clj
[["/ping" {:handler ping
:cost 300}]
["/pong" {:handler pong
:tags #{:game}}]]
2017-10-29 07:29:06 +00:00
```
Routes with path parameters (see also [Coercion](../coercion/coercion.md) and [Ring Coercion](../ring/coercion.md)):
2017-10-29 07:29:06 +00:00
```clj
[["/users/:user-id" {:handler get-user}]
["/api/:version/ping" {:handler ping-version}]]
2017-10-29 07:29:06 +00:00
```
2019-02-10 10:43:00 +00:00
```clj
[["/users/{user-id}" {:handler get-user}]
["/files/file-{number}.pdf" {:handler get-pdf}]]
2019-02-10 10:43:00 +00:00
```
2017-10-29 07:29:06 +00:00
Route with catch-all parameter:
```clj
["/public/*path" {:handler get-file}]
2017-10-29 07:29:06 +00:00
```
2019-02-10 10:43:00 +00:00
```clj
["/public/{*path}" {:handler get-file}]
2019-02-10 10:43:00 +00:00
```
2017-10-29 07:29:06 +00:00
Nested routes:
```clj
["/api"
["/admin" {:middleware [::admin]}
["" {:name ::admin}]
["/db" {:name ::db}]]
["/ping" {:name ::ping}]]
2017-10-29 07:29:06 +00:00
```
Same routes flattened:
```clj
[["/api/admin" {:middleware [::admin], :name ::admin}]
["/api/admin/db" {:middleware [::admin], :name ::db}]
["/api/ping" {:name ::ping}]]
```
2019-02-10 10:43:00 +00:00
### Encoding
Reitit does not apply any encoding to your paths. If you need that, you must encode them yourself. E.g., `/foo bar` should be `/foo%20bar`.
### Wildcards
2020-02-12 13:22:19 +00:00
Normal path-parameters (`:id`) can start anywhere in the path string, but have to end either to slash `/` (currently hardcoded) or to an end of path string:
2019-02-10 10:43:00 +00:00
```clj
[["/api/:version" {...}]
["/files/file-:number" {...}]
["/user/:user-id/orders" {...}]]
2019-02-10 10:43:00 +00:00
```
Bracket path-parameters can start and stop anywhere in the path-string, the following character is used as a terminator.
```clj
[["/api/{version}" {...}]
["/files/{name}.{extension}" {...}]
["/user/{user-id}/orders" {...}]]
2019-02-10 10:43:00 +00:00
```
Having multiple terminators after a bracket path-path parameter with identical path prefix will cause a compile-time error at router creation:
```clj
[["/files/file-{name}.pdf" {...}] ;; terminator \.
["/files/file-{name}-{version}.pdf" {...}]] ;; terminator \-
2019-02-10 10:43:00 +00:00
```
### Slash Free Routing
```clj
[["broker.{customer}.{device}.{*data}" {...}]
["events.{target}.{type}" {...}]]
2019-02-10 10:43:00 +00:00
```
### Generating routes
2018-02-11 17:15:25 +00:00
Routes are just data, so it's easy to create them programmatically:
2017-10-29 07:29:06 +00:00
```clj
2018-02-11 17:15:25 +00:00
(defn cqrs-routes [actions]
2017-10-29 07:29:06 +00:00
["/api" {:interceptors [::api ::db]}
(for [[type interceptor] actions
:let [path (str "/" (name interceptor))
2019-02-10 10:43:00 +00:00
method (case type
2017-10-29 07:29:06 +00:00
:query :get
:command :post)]]
2018-02-11 17:15:25 +00:00
[path {method {:interceptors [interceptor]}}])])
2017-10-29 07:29:06 +00:00
```
```clj
(cqrs-routes
[[:query 'get-user]
[:command 'add-user]
2018-02-11 17:15:25 +00:00
[:command 'add-order]])
2017-10-29 07:29:06 +00:00
; ["/api" {:interceptors [::api ::db]}
; (["/get-user" {:get {:interceptors [get-user]}}]
; ["/add-user" {:post {:interceptors [add-user]}}]
2018-02-11 17:15:25 +00:00
; ["/add-order" {:post {:interceptors [add-order]}}])]
2017-10-29 07:29:06 +00:00
```
2019-06-09 17:46:20 +00:00
### Explicit path-parameter syntax
2021-03-12 11:45:55 +00:00
Router options `:syntax` allows the path-parameter syntax to be explicitly defined. It takes a keyword or set of keywords as a value. Valid values are `:colon` and `:bracket`. Default value is `#{:colon :bracket}`.
2019-06-09 17:46:20 +00:00
2019-06-15 08:49:11 +00:00
With defaults:
```clj
(-> (r/router
["http://localhost:8080/api/user/{id}" ::user-by-id])
(r/match-by-path "http://localhost:8080/api/user/123"))
;#Match{:template "http://localhost:8080/api/user/{id}",
; :data {:name :user/user-by-id},
; :result nil,
; :path-params {:id "123", :8080 ":8080"},
; :path "http://localhost:8080/api/user/123"}
```
2019-06-09 17:46:20 +00:00
Supporting only `:bracket` syntax:
```clj
(require '[reitit.core :as r])
(-> (r/router
["http://localhost:8080/api/user/{id}" ::user-by-id]
{:syntax :bracket})
(r/match-by-path "http://localhost:8080/api/user/123"))
;#Match{:template "http://localhost:8080/api/user/{id}",
; :data {:name :user/user-by-id},
; :result nil,
; :path-params {:id "123"},
; :path "http://localhost:8080/api/user/123"}
```