mirror of
https://github.com/metosin/reitit.git
synced 2025-12-24 02:48:25 +00:00
Build book from commit eb22bae047
This commit is contained in:
parent
8e380f14eb
commit
b97eaaecd5
11 changed files with 3171 additions and 367 deletions
682
basics.html
Normal file
682
basics.html
Normal file
|
|
@ -0,0 +1,682 @@
|
|||
|
||||
<!DOCTYPE HTML>
|
||||
<html lang="" >
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta content="text/html; charset=utf-8" http-equiv="Content-Type">
|
||||
<title>Route syntax · GitBook</title>
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
|
||||
<meta name="description" content="">
|
||||
<meta name="generator" content="GitBook 3.2.3">
|
||||
|
||||
|
||||
|
||||
|
||||
<link rel="stylesheet" href="gitbook/style.css">
|
||||
|
||||
|
||||
|
||||
|
||||
<link rel="stylesheet" href="gitbook/gitbook-plugin-highlight/website.css">
|
||||
|
||||
|
||||
|
||||
<link rel="stylesheet" href="gitbook/gitbook-plugin-search/search.css">
|
||||
|
||||
|
||||
|
||||
<link rel="stylesheet" href="gitbook/gitbook-plugin-fontsettings/website.css">
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<meta name="HandheldFriendly" content="true"/>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=no">
|
||||
<meta name="apple-mobile-web-app-capable" content="yes">
|
||||
<meta name="apple-mobile-web-app-status-bar-style" content="black">
|
||||
<link rel="apple-touch-icon-precomposed" sizes="152x152" href="gitbook/images/apple-touch-icon-precomposed-152.png">
|
||||
<link rel="shortcut icon" href="gitbook/images/favicon.ico" type="image/x-icon">
|
||||
|
||||
|
||||
<link rel="next" href="basics.html" />
|
||||
|
||||
|
||||
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<div class="book">
|
||||
<div class="book-summary">
|
||||
|
||||
|
||||
<div id="book-search-input" role="search">
|
||||
<input type="text" placeholder="Type to search" />
|
||||
</div>
|
||||
|
||||
|
||||
<nav role="navigation">
|
||||
|
||||
|
||||
|
||||
<ul class="summary">
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<li class="chapter " data-level="1.1" data-path="./">
|
||||
|
||||
<a href="./">
|
||||
|
||||
|
||||
Introduction
|
||||
|
||||
</a>
|
||||
|
||||
|
||||
|
||||
</li>
|
||||
|
||||
<li class="chapter " data-level="1.2" >
|
||||
|
||||
<span>
|
||||
|
||||
|
||||
Basics
|
||||
|
||||
</span>
|
||||
|
||||
|
||||
|
||||
<ul class="articles">
|
||||
|
||||
|
||||
<li class="chapter " data-level="1.2.1" data-path="basics.html">
|
||||
|
||||
<a href="basics.html#route-syntax">
|
||||
|
||||
|
||||
Route syntax
|
||||
|
||||
</a>
|
||||
|
||||
|
||||
|
||||
</li>
|
||||
|
||||
<li class="chapter " data-level="1.2.2" data-path="basics.html">
|
||||
|
||||
<a href="basics.html#router">
|
||||
|
||||
|
||||
Router
|
||||
|
||||
</a>
|
||||
|
||||
|
||||
|
||||
</li>
|
||||
|
||||
<li class="chapter " data-level="1.2.3" data-path="basics.html">
|
||||
|
||||
<a href="basics.html#path-based-routing">
|
||||
|
||||
|
||||
Path-based Routing
|
||||
|
||||
</a>
|
||||
|
||||
|
||||
|
||||
</li>
|
||||
|
||||
<li class="chapter " data-level="1.2.4" data-path="basics.html">
|
||||
|
||||
<a href="basics.html#name-based-routing">
|
||||
|
||||
|
||||
Name-based Routing
|
||||
|
||||
</a>
|
||||
|
||||
|
||||
|
||||
</li>
|
||||
|
||||
<li class="chapter " data-level="1.2.5" data-path="basics.html">
|
||||
|
||||
<a href="basics.html#route-data">
|
||||
|
||||
|
||||
Route data
|
||||
|
||||
</a>
|
||||
|
||||
|
||||
|
||||
</li>
|
||||
|
||||
<li class="chapter " data-level="1.2.6" data-path="basics.html">
|
||||
|
||||
<a href="basics.html#different-routers">
|
||||
|
||||
|
||||
Different Routers
|
||||
|
||||
</a>
|
||||
|
||||
|
||||
|
||||
</li>
|
||||
|
||||
|
||||
</ul>
|
||||
|
||||
</li>
|
||||
|
||||
<li class="chapter " data-level="1.3" >
|
||||
|
||||
<span>
|
||||
|
||||
|
||||
Advanced
|
||||
|
||||
</span>
|
||||
|
||||
|
||||
|
||||
<ul class="articles">
|
||||
|
||||
|
||||
<li class="chapter " data-level="1.3.1" data-path="route_conflicts.html">
|
||||
|
||||
<a href="route_conflicts.html">
|
||||
|
||||
|
||||
Route conflicts
|
||||
|
||||
</a>
|
||||
|
||||
|
||||
|
||||
</li>
|
||||
|
||||
<li class="chapter " data-level="1.3.2" data-path="route_validation.html">
|
||||
|
||||
<a href="route_validation.html">
|
||||
|
||||
|
||||
Route Validation
|
||||
|
||||
</a>
|
||||
|
||||
|
||||
|
||||
</li>
|
||||
|
||||
<li class="chapter " data-level="1.3.3" data-path="configuring_routers.html">
|
||||
|
||||
<a href="configuring_routers.html">
|
||||
|
||||
|
||||
Configuring routers
|
||||
|
||||
</a>
|
||||
|
||||
|
||||
|
||||
</li>
|
||||
|
||||
|
||||
</ul>
|
||||
|
||||
</li>
|
||||
|
||||
<li class="chapter " data-level="1.4" >
|
||||
|
||||
<span>
|
||||
|
||||
|
||||
Ring
|
||||
|
||||
</span>
|
||||
|
||||
|
||||
|
||||
<ul class="articles">
|
||||
|
||||
|
||||
<li class="chapter " data-level="1.4.1" data-path="ring.html">
|
||||
|
||||
<a href="ring.html">
|
||||
|
||||
|
||||
Ring-router
|
||||
|
||||
</a>
|
||||
|
||||
|
||||
|
||||
</li>
|
||||
|
||||
<li class="chapter " data-level="1.4.2" data-path="dynamic_extensions.html">
|
||||
|
||||
<a href="dynamic_extensions.html">
|
||||
|
||||
|
||||
Dynamic extensions
|
||||
|
||||
</a>
|
||||
|
||||
|
||||
|
||||
</li>
|
||||
|
||||
<li class="chapter " data-level="1.4.3" data-path="parameter_coercion.html">
|
||||
|
||||
<a href="parameter_coercion.html">
|
||||
|
||||
|
||||
Parameter coercion
|
||||
|
||||
</a>
|
||||
|
||||
|
||||
|
||||
</li>
|
||||
|
||||
<li class="chapter " data-level="1.4.4" data-path="compiling_middleware.html">
|
||||
|
||||
<a href="compiling_middleware.html">
|
||||
|
||||
|
||||
Compiling middleware
|
||||
|
||||
</a>
|
||||
|
||||
|
||||
|
||||
</li>
|
||||
|
||||
|
||||
</ul>
|
||||
|
||||
</li>
|
||||
|
||||
<li class="chapter " data-level="1.5" >
|
||||
|
||||
<span>
|
||||
|
||||
|
||||
TODO: Swagger & OpenAPI
|
||||
|
||||
</span>
|
||||
|
||||
|
||||
|
||||
</li>
|
||||
|
||||
<li class="chapter " data-level="1.6" >
|
||||
|
||||
<span>
|
||||
|
||||
|
||||
TODO: Interceptors
|
||||
|
||||
</span>
|
||||
|
||||
|
||||
|
||||
</li>
|
||||
|
||||
|
||||
|
||||
|
||||
<li class="divider"></li>
|
||||
|
||||
<li>
|
||||
<a href="https://www.gitbook.com" target="blank" class="gitbook-link">
|
||||
Published with GitBook
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
|
||||
</nav>
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
<div class="book-body">
|
||||
|
||||
<div class="body-inner">
|
||||
|
||||
|
||||
|
||||
<div class="book-header" role="navigation">
|
||||
|
||||
|
||||
<!-- Title -->
|
||||
<h1>
|
||||
<i class="fa fa-circle-o-notch fa-spin"></i>
|
||||
<a href="." >Route syntax</a>
|
||||
</h1>
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
|
||||
<div class="page-wrapper" tabindex="-1" role="main">
|
||||
<div class="page-inner">
|
||||
|
||||
<div id="book-search-results">
|
||||
<div class="search-noresults">
|
||||
|
||||
<section class="normal markdown-section">
|
||||
|
||||
<h1 id="route-syntax">Route Syntax</h1>
|
||||
<p>Raw routes are defined as vectors, which have a String path, optional (non-sequential) route argument and optional child routes. Routes can be wrapped in vectors and lists and <code>nil</code> routes are ignored. Paths can have path-parameters (<code>:id</code>) or catch-all-parameters (<code>*path</code>).</p>
|
||||
<p>Simple route:</p>
|
||||
<pre><code class="lang-clj">[<span class="hljs-string">"/ping"</span>]
|
||||
</code></pre>
|
||||
<p>Two routes:</p>
|
||||
<pre><code class="lang-clj">[[<span class="hljs-string">"/ping"</span>]
|
||||
[<span class="hljs-string">"/pong"</span>]]
|
||||
</code></pre>
|
||||
<p>Routes with route arguments:</p>
|
||||
<pre><code class="lang-clj">[[<span class="hljs-string">"/ping"</span> <span class="hljs-symbol">::ping</span>]
|
||||
[<span class="hljs-string">"/pong"</span> {<span class="hljs-symbol">:name</span> <span class="hljs-symbol">::pong</span>}]]
|
||||
</code></pre>
|
||||
<p>Routes with path parameters:</p>
|
||||
<pre><code class="lang-clj">[[<span class="hljs-string">"/users/:user-id"</span>]
|
||||
[<span class="hljs-string">"/api/:version/ping"</span>]]
|
||||
</code></pre>
|
||||
<p>Route with catch-all parameter:</p>
|
||||
<pre><code class="lang-clj">[<span class="hljs-string">"/public/*path"</span>]
|
||||
</code></pre>
|
||||
<p>Nested routes:</p>
|
||||
<pre><code class="lang-clj">[<span class="hljs-string">"/api"</span>
|
||||
[<span class="hljs-string">"/admin"</span> {<span class="hljs-symbol">:middleware</span> [<span class="hljs-symbol">::admin</span>]}
|
||||
[<span class="hljs-string">""</span> <span class="hljs-symbol">::admin</span>]
|
||||
[<span class="hljs-string">"/db"</span> <span class="hljs-symbol">::db</span>]]
|
||||
[<span class="hljs-string">"/ping"</span> <span class="hljs-symbol">::ping</span>]]
|
||||
</code></pre>
|
||||
<p>Same routes flattened:</p>
|
||||
<pre><code class="lang-clj">[[<span class="hljs-string">"/api/admin"</span> {<span class="hljs-symbol">:middleware</span> [<span class="hljs-symbol">::admin</span>], <span class="hljs-symbol">:name</span> <span class="hljs-symbol">::admin</span>}]
|
||||
[<span class="hljs-string">"/api/admin/db"</span> {<span class="hljs-symbol">:middleware</span> [<span class="hljs-symbol">::admin</span>], <span class="hljs-symbol">:name</span> <span class="hljs-symbol">::db</span>}]
|
||||
[<span class="hljs-string">"/api/ping"</span> {<span class="hljs-symbol">:name</span> <span class="hljs-symbol">::ping</span>}]]
|
||||
</code></pre>
|
||||
<p>As routes are just data, it's easy to create them programamtically:</p>
|
||||
<pre><code class="lang-clj">(<span class="hljs-name"><span class="hljs-builtin-name">defn</span></span> cqrs-routes [actions dev-mode?]
|
||||
[<span class="hljs-string">"/api"</span> {<span class="hljs-symbol">:interceptors</span> [<span class="hljs-symbol">::api</span> <span class="hljs-symbol">::db</span>]}
|
||||
(<span class="hljs-name"><span class="hljs-builtin-name">for</span></span> [[type interceptor] actions
|
||||
<span class="hljs-symbol">:let</span> [path (<span class="hljs-name"><span class="hljs-builtin-name">str</span></span> <span class="hljs-string">"/"</span> (<span class="hljs-name"><span class="hljs-builtin-name">name</span></span> interceptor))
|
||||
method (<span class="hljs-name"><span class="hljs-builtin-name">condp</span></span> = type
|
||||
<span class="hljs-symbol">:query</span> <span class="hljs-symbol">:get</span>
|
||||
<span class="hljs-symbol">:command</span> <span class="hljs-symbol">:post</span>)]]
|
||||
[path {method {<span class="hljs-symbol">:interceptors</span> [interceptor]}}])
|
||||
(<span class="hljs-name"><span class="hljs-builtin-name">if</span></span> dev-mode? [<span class="hljs-string">"/dev-tools"</span> <span class="hljs-symbol">::dev-tools</span>])])
|
||||
</code></pre>
|
||||
<pre><code class="lang-clj">(<span class="hljs-name">cqrs-routes</span>
|
||||
[[<span class="hljs-symbol">:query</span> 'get-user]
|
||||
[<span class="hljs-symbol">:command</span> 'add-user]
|
||||
[<span class="hljs-symbol">:command</span> 'add-order]]
|
||||
<span class="hljs-literal">false</span>)
|
||||
<span class="hljs-comment">; ["/api" {:interceptors [::api ::db]}</span>
|
||||
<span class="hljs-comment">; (["/get-user" {:get {:interceptors [get-user]}}]</span>
|
||||
<span class="hljs-comment">; ["/add-user" {:post {:interceptors [add-user]}}]</span>
|
||||
<span class="hljs-comment">; ["/add-order" {:post {:interceptors [add-order]}}])</span>
|
||||
<span class="hljs-comment">; nil]</span>
|
||||
</code></pre>
|
||||
<h1 id="router">Router</h1>
|
||||
<p>Routes are just data and to do actual routing, we need a Router satisfying the <code>reitit.core/Router</code> protocol. Routers are created with <code>reitit.core/router</code> function, taking the raw routes and optionally an options map. Raw routes gets expanded and optionally coerced and compiled.</p>
|
||||
<p><code>Router</code> protocol:</p>
|
||||
<pre><code class="lang-clj">(<span class="hljs-name"><span class="hljs-builtin-name">defprotocol</span></span> Router
|
||||
(<span class="hljs-name">router-name</span> [this])
|
||||
(<span class="hljs-name">routes</span> [this])
|
||||
(<span class="hljs-name">options</span> [this])
|
||||
(<span class="hljs-name">route-names</span> [this])
|
||||
(<span class="hljs-name">match-by-path</span> [this path])
|
||||
(<span class="hljs-name">match-by-name</span> [this name] [this name params]))
|
||||
</code></pre>
|
||||
<p>Creating a router:</p>
|
||||
<pre><code class="lang-clj">(<span class="hljs-name">require</span> '[reitit.core <span class="hljs-symbol">:as</span> r])
|
||||
|
||||
(<span class="hljs-name"><span class="hljs-builtin-name">def</span></span> router
|
||||
(<span class="hljs-name">r/router</span>
|
||||
[[<span class="hljs-string">"/api"</span>
|
||||
[<span class="hljs-string">"/ping"</span> <span class="hljs-symbol">::ping</span>]
|
||||
[<span class="hljs-string">"/user/:id"</span> <span class="hljs-symbol">::user</span>]]]))
|
||||
</code></pre>
|
||||
<p>Router flattens the raw routes and expands the route arguments using <code>reitit.core/Expand</code> protocol. By default, <code>Keyword</code>s are expanded to <code>:name</code> and functions are expaned to <code>:handler</code>. <code>nil</code> routes are removed. The expanded routes can be retrieved with router:</p>
|
||||
<pre><code class="lang-clj">(<span class="hljs-name">r/routes</span> router)
|
||||
<span class="hljs-comment">; [["/api/ping" {:name :user/ping}]</span>
|
||||
<span class="hljs-comment">; ["/api/user/:id" {:name :user/user}]]</span>
|
||||
</code></pre>
|
||||
<h2 id="path-based-routing">Path-based routing</h2>
|
||||
<p>Path-based routing is done using the <code>reitit.core/match-by-path</code> function. It takes the router and path as arguments and returns one of the following:</p>
|
||||
<ul>
|
||||
<li><code>nil</code>, no match</li>
|
||||
<li><code>PartialMatch</code>, path matched, missing path-parameters (only in reverse-routing)</li>
|
||||
<li><code>Match</code>, exact match</li>
|
||||
</ul>
|
||||
<pre><code class="lang-clj">(<span class="hljs-name">r/match-by-path</span> router <span class="hljs-string">"/hello"</span>)
|
||||
<span class="hljs-comment">; nil</span>
|
||||
</code></pre>
|
||||
<pre><code class="lang-clj">(<span class="hljs-name">r/match-by-path</span> router <span class="hljs-string">"/api/user/1"</span>)
|
||||
<span class="hljs-comment">; #Match{:template "/api/user/:id"</span>
|
||||
<span class="hljs-comment">; :meta {:name :user/user}</span>
|
||||
<span class="hljs-comment">; :path "/api/user/1"</span>
|
||||
<span class="hljs-comment">; :result nil</span>
|
||||
<span class="hljs-comment">; :params {:id "1"}}</span>
|
||||
</code></pre>
|
||||
<h2 id="name-based-routing">Name-based routing</h2>
|
||||
<p>All routes which <code>:name</code> route data defined, can be matched by name.</p>
|
||||
<p>Listing all route names:</p>
|
||||
<pre><code class="lang-clj">(<span class="hljs-name">r/route-names</span> router)
|
||||
<span class="hljs-comment">; [:user/ping :user/user]</span>
|
||||
</code></pre>
|
||||
<p>Matching by name:</p>
|
||||
<pre><code class="lang-clj">(<span class="hljs-name">r/match-by-name</span> router <span class="hljs-symbol">::user</span>)
|
||||
<span class="hljs-comment">; #PartialMatch{:template "/api/user/:id",</span>
|
||||
<span class="hljs-comment">; :meta {:name :user/user},</span>
|
||||
<span class="hljs-comment">; :result nil,</span>
|
||||
<span class="hljs-comment">; :params nil,</span>
|
||||
<span class="hljs-comment">; :required #{:id}}</span>
|
||||
|
||||
(<span class="hljs-name">r/partial-match?</span> (<span class="hljs-name">r/match-by-name</span> router <span class="hljs-symbol">::user</span>))
|
||||
<span class="hljs-comment">; true</span>
|
||||
</code></pre>
|
||||
<p>We only got a partial match as we didn't provide the needed path-parameters. Let's provide the them too:</p>
|
||||
<pre><code class="lang-clj">(<span class="hljs-name">r/match-by-name</span> router <span class="hljs-symbol">::user</span> {<span class="hljs-symbol">:id</span> <span class="hljs-string">"1"</span>})
|
||||
<span class="hljs-comment">; #Match{:template "/api/user/:id"</span>
|
||||
<span class="hljs-comment">; :meta {:name :user/user}</span>
|
||||
<span class="hljs-comment">; :path "/api/user/1"</span>
|
||||
<span class="hljs-comment">; :result nil</span>
|
||||
<span class="hljs-comment">; :params {:id "1"}}</span>
|
||||
</code></pre>
|
||||
<p>There is also a exception throwing version:</p>
|
||||
<pre><code class="lang-clj">(<span class="hljs-name">r/match-by-name!</span> router <span class="hljs-symbol">::user</span>)
|
||||
<span class="hljs-comment">; ExceptionInfo missing path-params for route /api/user/:id: #{:id}</span>
|
||||
</code></pre>
|
||||
<h1 id="route-data">Route data</h1>
|
||||
<p>Routes can have arbitrary meta-data, interpreted by the router (via it's <code>:compile</code> hook) or the application itself. For nested routes, route data is accumulated recursively using <a href="https://github.com/weavejester/meta-merge" target="_blank">meta-merge</a>. By default, it appends collections, but it can be overridden to do <code>:prepend</code>, <code>:replace</code> or <code>:displace</code>.</p>
|
||||
<p>An example router with nested data:</p>
|
||||
<pre><code class="lang-clj">(<span class="hljs-name"><span class="hljs-builtin-name">def</span></span> router
|
||||
(<span class="hljs-name">r/router</span>
|
||||
[<span class="hljs-string">"/api"</span> {<span class="hljs-symbol">:interceptors</span> [<span class="hljs-symbol">::api</span>]}
|
||||
[<span class="hljs-string">"/ping"</span> <span class="hljs-symbol">::ping</span>]
|
||||
[<span class="hljs-string">"/admin"</span> {<span class="hljs-symbol">:roles</span> #{<span class="hljs-symbol">:admin</span>}}
|
||||
[<span class="hljs-string">"/users"</span> <span class="hljs-symbol">::users</span>]
|
||||
[<span class="hljs-string">"/db"</span> {<span class="hljs-symbol">:interceptors</span> [<span class="hljs-symbol">::db</span>]
|
||||
<span class="hljs-symbol">:roles</span> ^<span class="hljs-symbol">:replace</span> #{<span class="hljs-symbol">:db-admin</span>}}
|
||||
[<span class="hljs-string">"/:db"</span> {<span class="hljs-symbol">:parameters</span> {<span class="hljs-symbol">:db</span> String}}
|
||||
[<span class="hljs-string">"/drop"</span> <span class="hljs-symbol">::drop-db</span>]
|
||||
[<span class="hljs-string">"/stats"</span> <span class="hljs-symbol">::db-stats</span>]]]]]))
|
||||
</code></pre>
|
||||
<p>Resolved route tree:</p>
|
||||
<pre><code class="lang-clj">(<span class="hljs-name">reitit/routes</span> router)
|
||||
<span class="hljs-comment">; [["/api/ping" {:interceptors [::api]</span>
|
||||
<span class="hljs-comment">; :name ::ping}]</span>
|
||||
<span class="hljs-comment">; ["/api/admin/users" {:interceptors [::api]</span>
|
||||
<span class="hljs-comment">; :roles #{:admin}</span>
|
||||
<span class="hljs-comment">; :name ::users}]</span>
|
||||
<span class="hljs-comment">; ["/api/admin/db/:db/drop" {:interceptors [::api ::db]</span>
|
||||
<span class="hljs-comment">; :roles #{:db-admin}</span>
|
||||
<span class="hljs-comment">; :parameters {:db String}</span>
|
||||
<span class="hljs-comment">; :name ::drop-db}]</span>
|
||||
<span class="hljs-comment">; ["/api/admin/db/:db/stats" {:interceptors [::api ::db]</span>
|
||||
<span class="hljs-comment">; :roles #{:db-admin}</span>
|
||||
<span class="hljs-comment">; :parameters {:db String}</span>
|
||||
<span class="hljs-comment">; :name ::db-stats}]]</span>
|
||||
</code></pre>
|
||||
<p>Route data is returned with <code>Match</code> and the application can act based on it.</p>
|
||||
<pre><code class="lang-clj">(<span class="hljs-name">r/match-by-path</span> router <span class="hljs-string">"/api/admin/db/users/drop"</span>)
|
||||
<span class="hljs-comment">; #Match{:template "/api/admin/db/:db/drop"</span>
|
||||
<span class="hljs-comment">; :meta {:interceptors [::api ::db]</span>
|
||||
<span class="hljs-comment">; :roles #{:db-admin}</span>
|
||||
<span class="hljs-comment">; :parameters {:db String}</span>
|
||||
<span class="hljs-comment">; :name ::drop-db}</span>
|
||||
<span class="hljs-comment">; :result nil</span>
|
||||
<span class="hljs-comment">; :params {:db "users"}</span>
|
||||
<span class="hljs-comment">; :path "/api/admin/db/users/drop"}</span>
|
||||
</code></pre>
|
||||
<h1 id="different-routers">Different Routers</h1>
|
||||
<p>Reitit ships with several different implementations for the <code>Router</code> protocol, originally based on the awesome <a href="https://github.com/pedestal/pedestal/tree/master/route" target="_blank">Pedestal</a> implementation. <code>router</code> selects the most suitable implementation by inspecting the expanded routes. The implementation can be set manually using <code>:router</code> ROUTER OPTION.</p>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>router</th>
|
||||
<th>description</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td><code>:linear-router</code></td>
|
||||
<td>Matches the routes one-by-one starting from the top until a match is found. Works with any kind of routes.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>:lookup-router</code></td>
|
||||
<td>Fastest router, uses hash-lookup to resolve the route. Valid if no paths have path or catch-all parameters.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>:mixed-router</code></td>
|
||||
<td>Creates internally a <code>:linear-router</code> and a <code>:lookup-router</code> and used them to effectively get best-of-both-worlds. Valid if there are no CONFLICTING ROUTES.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>:prefix-tree-router</code></td>
|
||||
<td><a href="https://github.com/julienschmidt/httprouter#how-does-it-work" target="_blank">TODO</a></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<p>The router name can be asked from the router</p>
|
||||
<pre><code class="lang-clj">(<span class="hljs-name">r/router-name</span> router)
|
||||
<span class="hljs-comment">; :mixed-router</span>
|
||||
</code></pre>
|
||||
|
||||
|
||||
</section>
|
||||
|
||||
</div>
|
||||
<div class="search-results">
|
||||
<div class="has-results">
|
||||
|
||||
<h1 class="search-results-title"><span class='search-results-count'></span> results matching "<span class='search-query'></span>"</h1>
|
||||
<ul class="search-results-list"></ul>
|
||||
|
||||
</div>
|
||||
<div class="no-results">
|
||||
|
||||
<h1 class="search-results-title">No results matching "<span class='search-query'></span>"</h1>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
|
||||
<a href="basics.html#router" class="navigation navigation-next navigation-unique" aria-label="Next page: Router">
|
||||
<i class="fa fa-angle-right"></i>
|
||||
</a>
|
||||
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
<script>
|
||||
var gitbook = gitbook || [];
|
||||
gitbook.push(function() {
|
||||
gitbook.page.hasChanged({"page":{"title":"Route syntax","level":"1.2.1","depth":2,"next":{"title":"Router","level":"1.2.2","depth":2,"anchor":"#router","path":"basics.md","ref":"basics.md#router","articles":[]},"previous":{"title":"Basics","level":"1.2","depth":1,"ref":"","articles":[{"title":"Route syntax","level":"1.2.1","depth":2,"anchor":"#route-syntax","path":"basics.md","ref":"basics.md#route-syntax","articles":[]},{"title":"Router","level":"1.2.2","depth":2,"anchor":"#router","path":"basics.md","ref":"basics.md#router","articles":[]},{"title":"Path-based Routing","level":"1.2.3","depth":2,"anchor":"#path-based-routing","path":"basics.md","ref":"basics.md#path-based-routing","articles":[]},{"title":"Name-based Routing","level":"1.2.4","depth":2,"anchor":"#name-based-routing","path":"basics.md","ref":"basics.md#name-based-routing","articles":[]},{"title":"Route data","level":"1.2.5","depth":2,"anchor":"#route-data","path":"basics.md","ref":"basics.md#route-data","articles":[]},{"title":"Different Routers","level":"1.2.6","depth":2,"anchor":"#different-routers","path":"basics.md","ref":"basics.md#different-routers","articles":[]}]},"dir":"ltr"},"config":{"plugins":["editlink","github","highlight"],"root":"doc","styles":{"website":"styles/website.css","pdf":"styles/pdf.css","epub":"styles/epub.css","mobi":"styles/mobi.css","ebook":"styles/ebook.css","print":"styles/print.css"},"pluginsConfig":{"editlink":{"label":"Edit This Page","multilingual":false,"base":"https://github.com/metosin/reitit/tree/master/doc"},"github":{"url":"https://github.com/metosin/reitit"},"highlight":{},"search":{},"lunr":{"maxIndexSize":1000000,"ignoreSpecialCharacters":false},"sharing":{"facebook":true,"twitter":true,"google":false,"weibo":false,"instapaper":false,"vk":false,"all":["facebook","google","twitter","weibo","instapaper"]},"fontsettings":{"theme":"white","family":"sans","size":2},"theme-default":{"styles":{"website":"styles/website.css","pdf":"styles/pdf.css","epub":"styles/epub.css","mobi":"styles/mobi.css","ebook":"styles/ebook.css","print":"styles/print.css"},"showLevel":false}},"theme":"default","pdf":{"pageNumbers":true,"fontSize":12,"fontFamily":"Arial","paperSize":"a4","chapterMark":"pagebreak","pageBreaksBefore":"/","margin":{"right":62,"left":62,"top":56,"bottom":56}},"structure":{"langs":"LANGS.md","readme":"README.md","glossary":"GLOSSARY.md","summary":"SUMMARY.md"},"variables":{},"gitbook":"*"},"file":{"path":"basics.md","mtime":"2017-09-18T05:30:25.732Z","type":"markdown"},"gitbook":{"version":"3.2.3","time":"2017-09-18T05:30:51.447Z"},"basePath":".","book":{"language":""}});
|
||||
});
|
||||
</script>
|
||||
</div>
|
||||
|
||||
|
||||
<script src="gitbook/gitbook.js"></script>
|
||||
<script src="gitbook/theme.js"></script>
|
||||
|
||||
|
||||
<script src="gitbook/gitbook-plugin-editlink/plugin.js"></script>
|
||||
|
||||
|
||||
|
||||
<script src="gitbook/gitbook-plugin-github/plugin.js"></script>
|
||||
|
||||
|
||||
|
||||
<script src="gitbook/gitbook-plugin-search/search-engine.js"></script>
|
||||
|
||||
|
||||
|
||||
<script src="gitbook/gitbook-plugin-search/search.js"></script>
|
||||
|
||||
|
||||
|
||||
<script src="gitbook/gitbook-plugin-lunr/lunr.min.js"></script>
|
||||
|
||||
|
||||
|
||||
<script src="gitbook/gitbook-plugin-lunr/search-lunr.js"></script>
|
||||
|
||||
|
||||
|
||||
<script src="gitbook/gitbook-plugin-sharing/buttons.js"></script>
|
||||
|
||||
|
||||
|
||||
<script src="gitbook/gitbook-plugin-fontsettings/fontsettings.js"></script>
|
||||
|
||||
|
||||
|
||||
</body>
|
||||
</html>
|
||||
|
||||
|
|
@ -57,8 +57,6 @@
|
|||
<link rel="shortcut icon" href="gitbook/images/favicon.ico" type="image/x-icon">
|
||||
|
||||
|
||||
<link rel="next" href="validating.html" />
|
||||
|
||||
|
||||
<link rel="prev" href="parameter_coercion.html" />
|
||||
|
||||
|
|
@ -107,7 +105,7 @@
|
|||
<span>
|
||||
|
||||
|
||||
Routing
|
||||
Basics
|
||||
|
||||
</span>
|
||||
|
||||
|
|
@ -116,9 +114,9 @@
|
|||
<ul class="articles">
|
||||
|
||||
|
||||
<li class="chapter " data-level="1.2.1" data-path="routing/route_syntax.html">
|
||||
<li class="chapter " data-level="1.2.1" data-path="basics.html">
|
||||
|
||||
<a href="routing/route_syntax.html">
|
||||
<a href="basics.html#route-syntax">
|
||||
|
||||
|
||||
Route syntax
|
||||
|
|
@ -129,12 +127,12 @@
|
|||
|
||||
</li>
|
||||
|
||||
<li class="chapter " data-level="1.2.2" data-path="routing/routers.html">
|
||||
<li class="chapter " data-level="1.2.2" data-path="basics.html">
|
||||
|
||||
<a href="routing/routers.html">
|
||||
<a href="basics.html#router">
|
||||
|
||||
|
||||
Routers
|
||||
Router
|
||||
|
||||
</a>
|
||||
|
||||
|
|
@ -142,12 +140,12 @@
|
|||
|
||||
</li>
|
||||
|
||||
<li class="chapter " data-level="1.2.3" data-path="routing/route_metadata.html">
|
||||
<li class="chapter " data-level="1.2.3" data-path="basics.html">
|
||||
|
||||
<a href="routing/route_metadata.html">
|
||||
<a href="basics.html#path-based-routing">
|
||||
|
||||
|
||||
Route metadata
|
||||
Path-based Routing
|
||||
|
||||
</a>
|
||||
|
||||
|
|
@ -155,12 +153,38 @@
|
|||
|
||||
</li>
|
||||
|
||||
<li class="chapter " data-level="1.2.4" data-path="routing/route_conflicts.html">
|
||||
<li class="chapter " data-level="1.2.4" data-path="basics.html">
|
||||
|
||||
<a href="routing/route_conflicts.html">
|
||||
<a href="basics.html#name-based-routing">
|
||||
|
||||
|
||||
Route conflicts
|
||||
Name-based Routing
|
||||
|
||||
</a>
|
||||
|
||||
|
||||
|
||||
</li>
|
||||
|
||||
<li class="chapter " data-level="1.2.5" data-path="basics.html">
|
||||
|
||||
<a href="basics.html#route-data">
|
||||
|
||||
|
||||
Route data
|
||||
|
||||
</a>
|
||||
|
||||
|
||||
|
||||
</li>
|
||||
|
||||
<li class="chapter " data-level="1.2.6" data-path="basics.html">
|
||||
|
||||
<a href="basics.html#different-routers">
|
||||
|
||||
|
||||
Different Routers
|
||||
|
||||
</a>
|
||||
|
||||
|
|
@ -173,12 +197,26 @@
|
|||
|
||||
</li>
|
||||
|
||||
<li class="chapter " data-level="1.3" data-path="ring.html">
|
||||
<li class="chapter " data-level="1.3" >
|
||||
|
||||
<a href="ring.html">
|
||||
<span>
|
||||
|
||||
|
||||
Ring support
|
||||
Advanced
|
||||
|
||||
</span>
|
||||
|
||||
|
||||
|
||||
<ul class="articles">
|
||||
|
||||
|
||||
<li class="chapter " data-level="1.3.1" data-path="route_conflicts.html">
|
||||
|
||||
<a href="route_conflicts.html">
|
||||
|
||||
|
||||
Route conflicts
|
||||
|
||||
</a>
|
||||
|
||||
|
|
@ -186,12 +224,12 @@
|
|||
|
||||
</li>
|
||||
|
||||
<li class="chapter " data-level="1.4" data-path="parameter_coercion.html">
|
||||
<li class="chapter " data-level="1.3.2" data-path="route_validation.html">
|
||||
|
||||
<a href="parameter_coercion.html">
|
||||
<a href="route_validation.html">
|
||||
|
||||
|
||||
Parameter coercion
|
||||
Route Validation
|
||||
|
||||
</a>
|
||||
|
||||
|
|
@ -199,33 +237,7 @@
|
|||
|
||||
</li>
|
||||
|
||||
<li class="chapter active" data-level="1.5" data-path="compiling_middleware.html">
|
||||
|
||||
<a href="compiling_middleware.html">
|
||||
|
||||
|
||||
Compiling middleware
|
||||
|
||||
</a>
|
||||
|
||||
|
||||
|
||||
</li>
|
||||
|
||||
<li class="chapter " data-level="1.6" data-path="validating.html">
|
||||
|
||||
<a href="validating.html">
|
||||
|
||||
|
||||
Validating route-trees
|
||||
|
||||
</a>
|
||||
|
||||
|
||||
|
||||
</li>
|
||||
|
||||
<li class="chapter " data-level="1.7" data-path="configuring_routers.html">
|
||||
<li class="chapter " data-level="1.3.3" data-path="configuring_routers.html">
|
||||
|
||||
<a href="configuring_routers.html">
|
||||
|
||||
|
|
@ -238,20 +250,83 @@
|
|||
|
||||
</li>
|
||||
|
||||
<li class="chapter " data-level="1.8" >
|
||||
|
||||
</ul>
|
||||
|
||||
</li>
|
||||
|
||||
<li class="chapter " data-level="1.4" >
|
||||
|
||||
<span>
|
||||
|
||||
|
||||
TODO: Merging route-trees
|
||||
Ring
|
||||
|
||||
</span>
|
||||
|
||||
|
||||
|
||||
<ul class="articles">
|
||||
|
||||
|
||||
<li class="chapter " data-level="1.4.1" data-path="ring.html">
|
||||
|
||||
<a href="ring.html">
|
||||
|
||||
|
||||
Ring-router
|
||||
|
||||
</a>
|
||||
|
||||
|
||||
|
||||
</li>
|
||||
|
||||
<li class="chapter " data-level="1.9" >
|
||||
<li class="chapter " data-level="1.4.2" data-path="dynamic_extensions.html">
|
||||
|
||||
<a href="dynamic_extensions.html">
|
||||
|
||||
|
||||
Dynamic extensions
|
||||
|
||||
</a>
|
||||
|
||||
|
||||
|
||||
</li>
|
||||
|
||||
<li class="chapter " data-level="1.4.3" data-path="parameter_coercion.html">
|
||||
|
||||
<a href="parameter_coercion.html">
|
||||
|
||||
|
||||
Parameter coercion
|
||||
|
||||
</a>
|
||||
|
||||
|
||||
|
||||
</li>
|
||||
|
||||
<li class="chapter active" data-level="1.4.4" data-path="compiling_middleware.html">
|
||||
|
||||
<a href="compiling_middleware.html">
|
||||
|
||||
|
||||
Compiling middleware
|
||||
|
||||
</a>
|
||||
|
||||
|
||||
|
||||
</li>
|
||||
|
||||
|
||||
</ul>
|
||||
|
||||
</li>
|
||||
|
||||
<li class="chapter " data-level="1.5" >
|
||||
|
||||
<span>
|
||||
|
||||
|
|
@ -264,7 +339,7 @@
|
|||
|
||||
</li>
|
||||
|
||||
<li class="chapter " data-level="1.10" >
|
||||
<li class="chapter " data-level="1.6" >
|
||||
|
||||
<span>
|
||||
|
||||
|
|
@ -322,12 +397,12 @@
|
|||
|
||||
<section class="normal markdown-section">
|
||||
|
||||
<h2 id="compiling-middleware">Compiling Middleware</h2>
|
||||
<h1 id="compiling-middleware">Compiling Middleware</h1>
|
||||
<p>The <a href="ring.html#meta-data-based-extensions">meta-data extensions</a> are a easy way to extend the system. Routes meta-data can be transformed into any shape (records, functions etc.) in route compilation, enabling fast access at request-time.</p>
|
||||
<p>Still, we can do better. As we know the exact route that interceptor/middleware is linked to, we can pass the (compiled) route information into the interceptor/middleware at creation-time. It can extract and transform relevant data just for it and pass it into the actual request-handler via a closure - yielding faster runtime processing.</p>
|
||||
<p>To do this we use <a href="ring.html#middleware-records">middleware records</a> <code>:gen</code> hook instead of the normal <code>:wrap</code>. <code>:gen</code> expects a function of <code>route-meta router-opts => wrap</code>. Middleware can also return <code>nil</code>, which effective unmounts the middleware. Why mount a <code>wrap-enforce-roles</code> middleware for a route if there are no roles required for it?</p>
|
||||
<p>To demonstrate the two approaches, below are response coercion middleware written as normal ring middleware function and as middleware record with <code>:gen</code>. These are the actual codes are from <a href="https://github.com/metosin/reitit/blob/master/src/reitit/coercion.cljc" target="_blank"><code>reitit.coercion</code></a>:</p>
|
||||
<h3 id="naive">Naive</h3>
|
||||
<h2 id="naive">Naive</h2>
|
||||
<ul>
|
||||
<li>Extracts the compiled route information on every request.</li>
|
||||
</ul>
|
||||
|
|
@ -362,7 +437,7 @@
|
|||
(<span class="hljs-name">handler</span> request #(<span class="hljs-name">respond</span> (<span class="hljs-name">coerce-response</span> coercers request %))))
|
||||
(<span class="hljs-name">handler</span> request respond raise))))))
|
||||
</code></pre>
|
||||
<h3 id="compiled">Compiled</h3>
|
||||
<h2 id="compiled">Compiled</h2>
|
||||
<ul>
|
||||
<li>Route information is provided via a closure</li>
|
||||
<li>Pre-compiled coercers</li>
|
||||
|
|
@ -412,15 +487,11 @@
|
|||
|
||||
|
||||
|
||||
<a href="parameter_coercion.html" class="navigation navigation-prev " aria-label="Previous page: Parameter coercion">
|
||||
<a href="parameter_coercion.html" class="navigation navigation-prev navigation-unique" aria-label="Previous page: Parameter coercion">
|
||||
<i class="fa fa-angle-left"></i>
|
||||
</a>
|
||||
|
||||
|
||||
<a href="validating.html" class="navigation navigation-next " aria-label="Next page: Validating route-trees">
|
||||
<i class="fa fa-angle-right"></i>
|
||||
</a>
|
||||
|
||||
|
||||
|
||||
</div>
|
||||
|
|
@ -428,7 +499,7 @@
|
|||
<script>
|
||||
var gitbook = gitbook || [];
|
||||
gitbook.push(function() {
|
||||
gitbook.page.hasChanged({"page":{"title":"Compiling middleware","level":"1.5","depth":1,"next":{"title":"Validating route-trees","level":"1.6","depth":1,"path":"validating.md","ref":"validating.md","articles":[]},"previous":{"title":"Parameter coercion","level":"1.4","depth":1,"path":"parameter_coercion.md","ref":"parameter_coercion.md","articles":[]},"dir":"ltr"},"config":{"plugins":["editlink","github","highlight"],"root":"doc","styles":{"website":"styles/website.css","pdf":"styles/pdf.css","epub":"styles/epub.css","mobi":"styles/mobi.css","ebook":"styles/ebook.css","print":"styles/print.css"},"pluginsConfig":{"editlink":{"label":"Edit This Page","multilingual":false,"base":"https://github.com/metosin/reitit/tree/master/doc"},"github":{"url":"https://github.com/metosin/reitit"},"highlight":{},"search":{},"lunr":{"maxIndexSize":1000000,"ignoreSpecialCharacters":false},"sharing":{"facebook":true,"twitter":true,"google":false,"weibo":false,"instapaper":false,"vk":false,"all":["facebook","google","twitter","weibo","instapaper"]},"fontsettings":{"theme":"white","family":"sans","size":2},"theme-default":{"styles":{"website":"styles/website.css","pdf":"styles/pdf.css","epub":"styles/epub.css","mobi":"styles/mobi.css","ebook":"styles/ebook.css","print":"styles/print.css"},"showLevel":false}},"theme":"default","pdf":{"pageNumbers":true,"fontSize":12,"fontFamily":"Arial","paperSize":"a4","chapterMark":"pagebreak","pageBreaksBefore":"/","margin":{"right":62,"left":62,"top":56,"bottom":56}},"structure":{"langs":"LANGS.md","readme":"README.md","glossary":"GLOSSARY.md","summary":"SUMMARY.md"},"variables":{},"gitbook":"*"},"file":{"path":"compiling_middleware.md","mtime":"2017-09-14T15:08:32.263Z","type":"markdown"},"gitbook":{"version":"3.2.3","time":"2017-09-14T15:08:59.979Z"},"basePath":".","book":{"language":""}});
|
||||
gitbook.page.hasChanged({"page":{"title":"Compiling middleware","level":"1.4.4","depth":2,"next":{"title":"TODO: Swagger & OpenAPI","level":"1.5","depth":1,"ref":"","articles":[]},"previous":{"title":"Parameter coercion","level":"1.4.3","depth":2,"path":"parameter_coercion.md","ref":"parameter_coercion.md","articles":[]},"dir":"ltr"},"config":{"plugins":["editlink","github","highlight"],"root":"doc","styles":{"website":"styles/website.css","pdf":"styles/pdf.css","epub":"styles/epub.css","mobi":"styles/mobi.css","ebook":"styles/ebook.css","print":"styles/print.css"},"pluginsConfig":{"editlink":{"label":"Edit This Page","multilingual":false,"base":"https://github.com/metosin/reitit/tree/master/doc"},"github":{"url":"https://github.com/metosin/reitit"},"highlight":{},"search":{},"lunr":{"maxIndexSize":1000000,"ignoreSpecialCharacters":false},"sharing":{"facebook":true,"twitter":true,"google":false,"weibo":false,"instapaper":false,"vk":false,"all":["facebook","google","twitter","weibo","instapaper"]},"fontsettings":{"theme":"white","family":"sans","size":2},"theme-default":{"styles":{"website":"styles/website.css","pdf":"styles/pdf.css","epub":"styles/epub.css","mobi":"styles/mobi.css","ebook":"styles/ebook.css","print":"styles/print.css"},"showLevel":false}},"theme":"default","pdf":{"pageNumbers":true,"fontSize":12,"fontFamily":"Arial","paperSize":"a4","chapterMark":"pagebreak","pageBreaksBefore":"/","margin":{"right":62,"left":62,"top":56,"bottom":56}},"structure":{"langs":"LANGS.md","readme":"README.md","glossary":"GLOSSARY.md","summary":"SUMMARY.md"},"variables":{},"gitbook":"*"},"file":{"path":"compiling_middleware.md","mtime":"2017-09-18T05:30:25.732Z","type":"markdown"},"gitbook":{"version":"3.2.3","time":"2017-09-18T05:30:51.447Z"},"basePath":".","book":{"language":""}});
|
||||
});
|
||||
</script>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -58,7 +58,7 @@
|
|||
|
||||
|
||||
|
||||
<link rel="prev" href="validating.html" />
|
||||
<link rel="prev" href="route_validation.html" />
|
||||
|
||||
|
||||
</head>
|
||||
|
|
@ -105,7 +105,7 @@
|
|||
<span>
|
||||
|
||||
|
||||
Routing
|
||||
Basics
|
||||
|
||||
</span>
|
||||
|
||||
|
|
@ -114,9 +114,9 @@
|
|||
<ul class="articles">
|
||||
|
||||
|
||||
<li class="chapter " data-level="1.2.1" data-path="routing/route_syntax.html">
|
||||
<li class="chapter " data-level="1.2.1" data-path="basics.html">
|
||||
|
||||
<a href="routing/route_syntax.html">
|
||||
<a href="basics.html#route-syntax">
|
||||
|
||||
|
||||
Route syntax
|
||||
|
|
@ -127,12 +127,12 @@
|
|||
|
||||
</li>
|
||||
|
||||
<li class="chapter " data-level="1.2.2" data-path="routing/routers.html">
|
||||
<li class="chapter " data-level="1.2.2" data-path="basics.html">
|
||||
|
||||
<a href="routing/routers.html">
|
||||
<a href="basics.html#router">
|
||||
|
||||
|
||||
Routers
|
||||
Router
|
||||
|
||||
</a>
|
||||
|
||||
|
|
@ -140,12 +140,12 @@
|
|||
|
||||
</li>
|
||||
|
||||
<li class="chapter " data-level="1.2.3" data-path="routing/route_metadata.html">
|
||||
<li class="chapter " data-level="1.2.3" data-path="basics.html">
|
||||
|
||||
<a href="routing/route_metadata.html">
|
||||
<a href="basics.html#path-based-routing">
|
||||
|
||||
|
||||
Route metadata
|
||||
Path-based Routing
|
||||
|
||||
</a>
|
||||
|
||||
|
|
@ -153,12 +153,38 @@
|
|||
|
||||
</li>
|
||||
|
||||
<li class="chapter " data-level="1.2.4" data-path="routing/route_conflicts.html">
|
||||
<li class="chapter " data-level="1.2.4" data-path="basics.html">
|
||||
|
||||
<a href="routing/route_conflicts.html">
|
||||
<a href="basics.html#name-based-routing">
|
||||
|
||||
|
||||
Route conflicts
|
||||
Name-based Routing
|
||||
|
||||
</a>
|
||||
|
||||
|
||||
|
||||
</li>
|
||||
|
||||
<li class="chapter " data-level="1.2.5" data-path="basics.html">
|
||||
|
||||
<a href="basics.html#route-data">
|
||||
|
||||
|
||||
Route data
|
||||
|
||||
</a>
|
||||
|
||||
|
||||
|
||||
</li>
|
||||
|
||||
<li class="chapter " data-level="1.2.6" data-path="basics.html">
|
||||
|
||||
<a href="basics.html#different-routers">
|
||||
|
||||
|
||||
Different Routers
|
||||
|
||||
</a>
|
||||
|
||||
|
|
@ -171,12 +197,26 @@
|
|||
|
||||
</li>
|
||||
|
||||
<li class="chapter " data-level="1.3" data-path="ring.html">
|
||||
<li class="chapter " data-level="1.3" >
|
||||
|
||||
<a href="ring.html">
|
||||
<span>
|
||||
|
||||
|
||||
Ring support
|
||||
Advanced
|
||||
|
||||
</span>
|
||||
|
||||
|
||||
|
||||
<ul class="articles">
|
||||
|
||||
|
||||
<li class="chapter " data-level="1.3.1" data-path="route_conflicts.html">
|
||||
|
||||
<a href="route_conflicts.html">
|
||||
|
||||
|
||||
Route conflicts
|
||||
|
||||
</a>
|
||||
|
||||
|
|
@ -184,12 +224,12 @@
|
|||
|
||||
</li>
|
||||
|
||||
<li class="chapter " data-level="1.4" data-path="parameter_coercion.html">
|
||||
<li class="chapter " data-level="1.3.2" data-path="route_validation.html">
|
||||
|
||||
<a href="parameter_coercion.html">
|
||||
<a href="route_validation.html">
|
||||
|
||||
|
||||
Parameter coercion
|
||||
Route Validation
|
||||
|
||||
</a>
|
||||
|
||||
|
|
@ -197,33 +237,7 @@
|
|||
|
||||
</li>
|
||||
|
||||
<li class="chapter " data-level="1.5" data-path="compiling_middleware.html">
|
||||
|
||||
<a href="compiling_middleware.html">
|
||||
|
||||
|
||||
Compiling middleware
|
||||
|
||||
</a>
|
||||
|
||||
|
||||
|
||||
</li>
|
||||
|
||||
<li class="chapter " data-level="1.6" data-path="validating.html">
|
||||
|
||||
<a href="validating.html">
|
||||
|
||||
|
||||
Validating route-trees
|
||||
|
||||
</a>
|
||||
|
||||
|
||||
|
||||
</li>
|
||||
|
||||
<li class="chapter active" data-level="1.7" data-path="configuring_routers.html">
|
||||
<li class="chapter active" data-level="1.3.3" data-path="configuring_routers.html">
|
||||
|
||||
<a href="configuring_routers.html">
|
||||
|
||||
|
|
@ -236,20 +250,83 @@
|
|||
|
||||
</li>
|
||||
|
||||
<li class="chapter " data-level="1.8" >
|
||||
|
||||
</ul>
|
||||
|
||||
</li>
|
||||
|
||||
<li class="chapter " data-level="1.4" >
|
||||
|
||||
<span>
|
||||
|
||||
|
||||
TODO: Merging route-trees
|
||||
Ring
|
||||
|
||||
</span>
|
||||
|
||||
|
||||
|
||||
<ul class="articles">
|
||||
|
||||
|
||||
<li class="chapter " data-level="1.4.1" data-path="ring.html">
|
||||
|
||||
<a href="ring.html">
|
||||
|
||||
|
||||
Ring-router
|
||||
|
||||
</a>
|
||||
|
||||
|
||||
|
||||
</li>
|
||||
|
||||
<li class="chapter " data-level="1.9" >
|
||||
<li class="chapter " data-level="1.4.2" data-path="dynamic_extensions.html">
|
||||
|
||||
<a href="dynamic_extensions.html">
|
||||
|
||||
|
||||
Dynamic extensions
|
||||
|
||||
</a>
|
||||
|
||||
|
||||
|
||||
</li>
|
||||
|
||||
<li class="chapter " data-level="1.4.3" data-path="parameter_coercion.html">
|
||||
|
||||
<a href="parameter_coercion.html">
|
||||
|
||||
|
||||
Parameter coercion
|
||||
|
||||
</a>
|
||||
|
||||
|
||||
|
||||
</li>
|
||||
|
||||
<li class="chapter " data-level="1.4.4" data-path="compiling_middleware.html">
|
||||
|
||||
<a href="compiling_middleware.html">
|
||||
|
||||
|
||||
Compiling middleware
|
||||
|
||||
</a>
|
||||
|
||||
|
||||
|
||||
</li>
|
||||
|
||||
|
||||
</ul>
|
||||
|
||||
</li>
|
||||
|
||||
<li class="chapter " data-level="1.5" >
|
||||
|
||||
<span>
|
||||
|
||||
|
|
@ -262,7 +339,7 @@
|
|||
|
||||
</li>
|
||||
|
||||
<li class="chapter " data-level="1.10" >
|
||||
<li class="chapter " data-level="1.6" >
|
||||
|
||||
<span>
|
||||
|
||||
|
|
@ -391,7 +468,7 @@
|
|||
|
||||
|
||||
|
||||
<a href="validating.html" class="navigation navigation-prev navigation-unique" aria-label="Previous page: Validating route-trees">
|
||||
<a href="route_validation.html" class="navigation navigation-prev navigation-unique" aria-label="Previous page: Route Validation">
|
||||
<i class="fa fa-angle-left"></i>
|
||||
</a>
|
||||
|
||||
|
|
@ -403,7 +480,7 @@
|
|||
<script>
|
||||
var gitbook = gitbook || [];
|
||||
gitbook.push(function() {
|
||||
gitbook.page.hasChanged({"page":{"title":"Configuring routers","level":"1.7","depth":1,"next":{"title":"TODO: Merging route-trees","level":"1.8","depth":1,"ref":"","articles":[]},"previous":{"title":"Validating route-trees","level":"1.6","depth":1,"path":"validating.md","ref":"validating.md","articles":[]},"dir":"ltr"},"config":{"plugins":["editlink","github","highlight"],"root":"doc","styles":{"website":"styles/website.css","pdf":"styles/pdf.css","epub":"styles/epub.css","mobi":"styles/mobi.css","ebook":"styles/ebook.css","print":"styles/print.css"},"pluginsConfig":{"editlink":{"label":"Edit This Page","multilingual":false,"base":"https://github.com/metosin/reitit/tree/master/doc"},"github":{"url":"https://github.com/metosin/reitit"},"highlight":{},"search":{},"lunr":{"maxIndexSize":1000000,"ignoreSpecialCharacters":false},"sharing":{"facebook":true,"twitter":true,"google":false,"weibo":false,"instapaper":false,"vk":false,"all":["facebook","google","twitter","weibo","instapaper"]},"fontsettings":{"theme":"white","family":"sans","size":2},"theme-default":{"styles":{"website":"styles/website.css","pdf":"styles/pdf.css","epub":"styles/epub.css","mobi":"styles/mobi.css","ebook":"styles/ebook.css","print":"styles/print.css"},"showLevel":false}},"theme":"default","pdf":{"pageNumbers":true,"fontSize":12,"fontFamily":"Arial","paperSize":"a4","chapterMark":"pagebreak","pageBreaksBefore":"/","margin":{"right":62,"left":62,"top":56,"bottom":56}},"structure":{"langs":"LANGS.md","readme":"README.md","glossary":"GLOSSARY.md","summary":"SUMMARY.md"},"variables":{},"gitbook":"*"},"file":{"path":"configuring_routers.md","mtime":"2017-09-14T15:08:32.263Z","type":"markdown"},"gitbook":{"version":"3.2.3","time":"2017-09-14T15:08:59.979Z"},"basePath":".","book":{"language":""}});
|
||||
gitbook.page.hasChanged({"page":{"title":"Configuring routers","level":"1.3.3","depth":2,"next":{"title":"Ring","level":"1.4","depth":1,"ref":"","articles":[{"title":"Ring-router","level":"1.4.1","depth":2,"path":"ring.md","ref":"ring.md","articles":[]},{"title":"Dynamic extensions","level":"1.4.2","depth":2,"path":"dynamic_extensions.md","ref":"dynamic_extensions.md","articles":[]},{"title":"Parameter coercion","level":"1.4.3","depth":2,"path":"parameter_coercion.md","ref":"parameter_coercion.md","articles":[]},{"title":"Compiling middleware","level":"1.4.4","depth":2,"path":"compiling_middleware.md","ref":"compiling_middleware.md","articles":[]}]},"previous":{"title":"Route Validation","level":"1.3.2","depth":2,"path":"route_validation.md","ref":"route_validation.md","articles":[]},"dir":"ltr"},"config":{"plugins":["editlink","github","highlight"],"root":"doc","styles":{"website":"styles/website.css","pdf":"styles/pdf.css","epub":"styles/epub.css","mobi":"styles/mobi.css","ebook":"styles/ebook.css","print":"styles/print.css"},"pluginsConfig":{"editlink":{"label":"Edit This Page","multilingual":false,"base":"https://github.com/metosin/reitit/tree/master/doc"},"github":{"url":"https://github.com/metosin/reitit"},"highlight":{},"search":{},"lunr":{"maxIndexSize":1000000,"ignoreSpecialCharacters":false},"sharing":{"facebook":true,"twitter":true,"google":false,"weibo":false,"instapaper":false,"vk":false,"all":["facebook","google","twitter","weibo","instapaper"]},"fontsettings":{"theme":"white","family":"sans","size":2},"theme-default":{"styles":{"website":"styles/website.css","pdf":"styles/pdf.css","epub":"styles/epub.css","mobi":"styles/mobi.css","ebook":"styles/ebook.css","print":"styles/print.css"},"showLevel":false}},"theme":"default","pdf":{"pageNumbers":true,"fontSize":12,"fontFamily":"Arial","paperSize":"a4","chapterMark":"pagebreak","pageBreaksBefore":"/","margin":{"right":62,"left":62,"top":56,"bottom":56}},"structure":{"langs":"LANGS.md","readme":"README.md","glossary":"GLOSSARY.md","summary":"SUMMARY.md"},"variables":{},"gitbook":"*"},"file":{"path":"configuring_routers.md","mtime":"2017-09-18T05:30:25.732Z","type":"markdown"},"gitbook":{"version":"3.2.3","time":"2017-09-18T05:30:51.447Z"},"basePath":".","book":{"language":""}});
|
||||
});
|
||||
</script>
|
||||
</div>
|
||||
|
|
|
|||
525
dynamic_extensions.html
Normal file
525
dynamic_extensions.html
Normal file
|
|
@ -0,0 +1,525 @@
|
|||
|
||||
<!DOCTYPE HTML>
|
||||
<html lang="" >
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta content="text/html; charset=utf-8" http-equiv="Content-Type">
|
||||
<title>Dynamic extensions · GitBook</title>
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
|
||||
<meta name="description" content="">
|
||||
<meta name="generator" content="GitBook 3.2.3">
|
||||
|
||||
|
||||
|
||||
|
||||
<link rel="stylesheet" href="gitbook/style.css">
|
||||
|
||||
|
||||
|
||||
|
||||
<link rel="stylesheet" href="gitbook/gitbook-plugin-highlight/website.css">
|
||||
|
||||
|
||||
|
||||
<link rel="stylesheet" href="gitbook/gitbook-plugin-search/search.css">
|
||||
|
||||
|
||||
|
||||
<link rel="stylesheet" href="gitbook/gitbook-plugin-fontsettings/website.css">
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<meta name="HandheldFriendly" content="true"/>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=no">
|
||||
<meta name="apple-mobile-web-app-capable" content="yes">
|
||||
<meta name="apple-mobile-web-app-status-bar-style" content="black">
|
||||
<link rel="apple-touch-icon-precomposed" sizes="152x152" href="gitbook/images/apple-touch-icon-precomposed-152.png">
|
||||
<link rel="shortcut icon" href="gitbook/images/favicon.ico" type="image/x-icon">
|
||||
|
||||
|
||||
<link rel="next" href="parameter_coercion.html" />
|
||||
|
||||
|
||||
<link rel="prev" href="ring.html" />
|
||||
|
||||
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<div class="book">
|
||||
<div class="book-summary">
|
||||
|
||||
|
||||
<div id="book-search-input" role="search">
|
||||
<input type="text" placeholder="Type to search" />
|
||||
</div>
|
||||
|
||||
|
||||
<nav role="navigation">
|
||||
|
||||
|
||||
|
||||
<ul class="summary">
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<li class="chapter " data-level="1.1" data-path="./">
|
||||
|
||||
<a href="./">
|
||||
|
||||
|
||||
Introduction
|
||||
|
||||
</a>
|
||||
|
||||
|
||||
|
||||
</li>
|
||||
|
||||
<li class="chapter " data-level="1.2" >
|
||||
|
||||
<span>
|
||||
|
||||
|
||||
Basics
|
||||
|
||||
</span>
|
||||
|
||||
|
||||
|
||||
<ul class="articles">
|
||||
|
||||
|
||||
<li class="chapter " data-level="1.2.1" data-path="basics.html">
|
||||
|
||||
<a href="basics.html#route-syntax">
|
||||
|
||||
|
||||
Route syntax
|
||||
|
||||
</a>
|
||||
|
||||
|
||||
|
||||
</li>
|
||||
|
||||
<li class="chapter " data-level="1.2.2" data-path="basics.html">
|
||||
|
||||
<a href="basics.html#router">
|
||||
|
||||
|
||||
Router
|
||||
|
||||
</a>
|
||||
|
||||
|
||||
|
||||
</li>
|
||||
|
||||
<li class="chapter " data-level="1.2.3" data-path="basics.html">
|
||||
|
||||
<a href="basics.html#path-based-routing">
|
||||
|
||||
|
||||
Path-based Routing
|
||||
|
||||
</a>
|
||||
|
||||
|
||||
|
||||
</li>
|
||||
|
||||
<li class="chapter " data-level="1.2.4" data-path="basics.html">
|
||||
|
||||
<a href="basics.html#name-based-routing">
|
||||
|
||||
|
||||
Name-based Routing
|
||||
|
||||
</a>
|
||||
|
||||
|
||||
|
||||
</li>
|
||||
|
||||
<li class="chapter " data-level="1.2.5" data-path="basics.html">
|
||||
|
||||
<a href="basics.html#route-data">
|
||||
|
||||
|
||||
Route data
|
||||
|
||||
</a>
|
||||
|
||||
|
||||
|
||||
</li>
|
||||
|
||||
<li class="chapter " data-level="1.2.6" data-path="basics.html">
|
||||
|
||||
<a href="basics.html#different-routers">
|
||||
|
||||
|
||||
Different Routers
|
||||
|
||||
</a>
|
||||
|
||||
|
||||
|
||||
</li>
|
||||
|
||||
|
||||
</ul>
|
||||
|
||||
</li>
|
||||
|
||||
<li class="chapter " data-level="1.3" >
|
||||
|
||||
<span>
|
||||
|
||||
|
||||
Advanced
|
||||
|
||||
</span>
|
||||
|
||||
|
||||
|
||||
<ul class="articles">
|
||||
|
||||
|
||||
<li class="chapter " data-level="1.3.1" data-path="route_conflicts.html">
|
||||
|
||||
<a href="route_conflicts.html">
|
||||
|
||||
|
||||
Route conflicts
|
||||
|
||||
</a>
|
||||
|
||||
|
||||
|
||||
</li>
|
||||
|
||||
<li class="chapter " data-level="1.3.2" data-path="route_validation.html">
|
||||
|
||||
<a href="route_validation.html">
|
||||
|
||||
|
||||
Route Validation
|
||||
|
||||
</a>
|
||||
|
||||
|
||||
|
||||
</li>
|
||||
|
||||
<li class="chapter " data-level="1.3.3" data-path="configuring_routers.html">
|
||||
|
||||
<a href="configuring_routers.html">
|
||||
|
||||
|
||||
Configuring routers
|
||||
|
||||
</a>
|
||||
|
||||
|
||||
|
||||
</li>
|
||||
|
||||
|
||||
</ul>
|
||||
|
||||
</li>
|
||||
|
||||
<li class="chapter " data-level="1.4" >
|
||||
|
||||
<span>
|
||||
|
||||
|
||||
Ring
|
||||
|
||||
</span>
|
||||
|
||||
|
||||
|
||||
<ul class="articles">
|
||||
|
||||
|
||||
<li class="chapter " data-level="1.4.1" data-path="ring.html">
|
||||
|
||||
<a href="ring.html">
|
||||
|
||||
|
||||
Ring-router
|
||||
|
||||
</a>
|
||||
|
||||
|
||||
|
||||
</li>
|
||||
|
||||
<li class="chapter active" data-level="1.4.2" data-path="dynamic_extensions.html">
|
||||
|
||||
<a href="dynamic_extensions.html">
|
||||
|
||||
|
||||
Dynamic extensions
|
||||
|
||||
</a>
|
||||
|
||||
|
||||
|
||||
</li>
|
||||
|
||||
<li class="chapter " data-level="1.4.3" data-path="parameter_coercion.html">
|
||||
|
||||
<a href="parameter_coercion.html">
|
||||
|
||||
|
||||
Parameter coercion
|
||||
|
||||
</a>
|
||||
|
||||
|
||||
|
||||
</li>
|
||||
|
||||
<li class="chapter " data-level="1.4.4" data-path="compiling_middleware.html">
|
||||
|
||||
<a href="compiling_middleware.html">
|
||||
|
||||
|
||||
Compiling middleware
|
||||
|
||||
</a>
|
||||
|
||||
|
||||
|
||||
</li>
|
||||
|
||||
|
||||
</ul>
|
||||
|
||||
</li>
|
||||
|
||||
<li class="chapter " data-level="1.5" >
|
||||
|
||||
<span>
|
||||
|
||||
|
||||
TODO: Swagger & OpenAPI
|
||||
|
||||
</span>
|
||||
|
||||
|
||||
|
||||
</li>
|
||||
|
||||
<li class="chapter " data-level="1.6" >
|
||||
|
||||
<span>
|
||||
|
||||
|
||||
TODO: Interceptors
|
||||
|
||||
</span>
|
||||
|
||||
|
||||
|
||||
</li>
|
||||
|
||||
|
||||
|
||||
|
||||
<li class="divider"></li>
|
||||
|
||||
<li>
|
||||
<a href="https://www.gitbook.com" target="blank" class="gitbook-link">
|
||||
Published with GitBook
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
|
||||
</nav>
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
<div class="book-body">
|
||||
|
||||
<div class="body-inner">
|
||||
|
||||
|
||||
|
||||
<div class="book-header" role="navigation">
|
||||
|
||||
|
||||
<!-- Title -->
|
||||
<h1>
|
||||
<i class="fa fa-circle-o-notch fa-spin"></i>
|
||||
<a href="." >Dynamic extensions</a>
|
||||
</h1>
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
|
||||
<div class="page-wrapper" tabindex="-1" role="main">
|
||||
<div class="page-inner">
|
||||
|
||||
<div id="book-search-results">
|
||||
<div class="search-noresults">
|
||||
|
||||
<section class="normal markdown-section">
|
||||
|
||||
<h1 id="dynamic-extensions">Dynamic extensions</h1>
|
||||
<p><code>ring-handler</code> injects the <code>Match</code> into a request and it can be extracted at runtime with <code>reitit.ring/get-match</code>. This can be used to build dynamic extensions to the system.</p>
|
||||
<p>Example middleware to guard routes based on user roles:</p>
|
||||
<pre><code class="lang-clj">(<span class="hljs-name">require</span> '[clojure.set <span class="hljs-symbol">:as</span> set])
|
||||
|
||||
(<span class="hljs-name"><span class="hljs-builtin-name">defn</span></span> wrap-enforce-roles [handler]
|
||||
(<span class="hljs-name"><span class="hljs-builtin-name">fn</span></span> [{<span class="hljs-symbol">:keys</span> [<span class="hljs-symbol">::roles</span>] <span class="hljs-symbol">:as</span> request}]
|
||||
(<span class="hljs-name"><span class="hljs-builtin-name">let</span></span> [required (<span class="hljs-name">some-></span> request (<span class="hljs-name">ring/get-match</span>) <span class="hljs-symbol">:meta</span> <span class="hljs-symbol">::roles</span>)]
|
||||
(<span class="hljs-name"><span class="hljs-builtin-name">if</span></span> (<span class="hljs-name"><span class="hljs-builtin-name">and</span></span> (<span class="hljs-name"><span class="hljs-builtin-name">seq</span></span> required) (<span class="hljs-name"><span class="hljs-builtin-name">not</span></span> (<span class="hljs-name">set/intersection</span> required roles)))
|
||||
{<span class="hljs-symbol">:status</span> <span class="hljs-number">403</span>, <span class="hljs-symbol">:body</span> <span class="hljs-string">"forbidden"</span>}
|
||||
(<span class="hljs-name">handler</span> request)))))
|
||||
</code></pre>
|
||||
<p>Mounted to an app via router meta-data (effecting all routes):</p>
|
||||
<pre><code class="lang-clj">(<span class="hljs-name"><span class="hljs-builtin-name">def</span></span> handler (<span class="hljs-name"><span class="hljs-builtin-name">constantly</span></span> {<span class="hljs-symbol">:status</span> <span class="hljs-number">200</span>, <span class="hljs-symbol">:body</span> <span class="hljs-string">"ok"</span>}))
|
||||
|
||||
(<span class="hljs-name"><span class="hljs-builtin-name">def</span></span> app
|
||||
(<span class="hljs-name">ring/ring-handler</span>
|
||||
(<span class="hljs-name">ring/router</span>
|
||||
[[<span class="hljs-string">"/api"</span>
|
||||
[<span class="hljs-string">"/ping"</span> handler]
|
||||
[<span class="hljs-string">"/admin"</span> {<span class="hljs-symbol">::roles</span> #{<span class="hljs-symbol">:admin</span>}}
|
||||
[<span class="hljs-string">"/ping"</span> handler]]]]
|
||||
{<span class="hljs-symbol">:meta</span> {<span class="hljs-symbol">:middleware</span> [wrap-enforce-roles]}})))
|
||||
</code></pre>
|
||||
<p>Anonymous access to public route:</p>
|
||||
<pre><code class="lang-clj">(<span class="hljs-name">app</span> {<span class="hljs-symbol">:request-method</span> <span class="hljs-symbol">:get</span>, <span class="hljs-symbol">:uri</span> <span class="hljs-string">"/api/ping"</span>})
|
||||
<span class="hljs-comment">; {:status 200, :body "ok"}</span>
|
||||
</code></pre>
|
||||
<p>Anonymous access to guarded route:</p>
|
||||
<pre><code class="lang-clj">(<span class="hljs-name">app</span> {<span class="hljs-symbol">:request-method</span> <span class="hljs-symbol">:get</span>, <span class="hljs-symbol">:uri</span> <span class="hljs-string">"/api/admin/ping"</span>})
|
||||
<span class="hljs-comment">; {:status 403, :body "forbidden"}</span>
|
||||
</code></pre>
|
||||
<p>Authorized access to guarded route:</p>
|
||||
<pre><code class="lang-clj">(<span class="hljs-name">app</span> {<span class="hljs-symbol">:request-method</span> <span class="hljs-symbol">:get</span>, <span class="hljs-symbol">:uri</span> <span class="hljs-string">"/api/admin/ping"</span>, <span class="hljs-symbol">::roles</span> #{<span class="hljs-symbol">:admin</span>}})
|
||||
<span class="hljs-comment">; {:status 200, :body "ok"}</span>
|
||||
</code></pre>
|
||||
|
||||
|
||||
</section>
|
||||
|
||||
</div>
|
||||
<div class="search-results">
|
||||
<div class="has-results">
|
||||
|
||||
<h1 class="search-results-title"><span class='search-results-count'></span> results matching "<span class='search-query'></span>"</h1>
|
||||
<ul class="search-results-list"></ul>
|
||||
|
||||
</div>
|
||||
<div class="no-results">
|
||||
|
||||
<h1 class="search-results-title">No results matching "<span class='search-query'></span>"</h1>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
<a href="ring.html" class="navigation navigation-prev " aria-label="Previous page: Ring-router">
|
||||
<i class="fa fa-angle-left"></i>
|
||||
</a>
|
||||
|
||||
|
||||
<a href="parameter_coercion.html" class="navigation navigation-next " aria-label="Next page: Parameter coercion">
|
||||
<i class="fa fa-angle-right"></i>
|
||||
</a>
|
||||
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
<script>
|
||||
var gitbook = gitbook || [];
|
||||
gitbook.push(function() {
|
||||
gitbook.page.hasChanged({"page":{"title":"Dynamic extensions","level":"1.4.2","depth":2,"next":{"title":"Parameter coercion","level":"1.4.3","depth":2,"path":"parameter_coercion.md","ref":"parameter_coercion.md","articles":[]},"previous":{"title":"Ring-router","level":"1.4.1","depth":2,"path":"ring.md","ref":"ring.md","articles":[]},"dir":"ltr"},"config":{"plugins":["editlink","github","highlight"],"root":"doc","styles":{"website":"styles/website.css","pdf":"styles/pdf.css","epub":"styles/epub.css","mobi":"styles/mobi.css","ebook":"styles/ebook.css","print":"styles/print.css"},"pluginsConfig":{"editlink":{"label":"Edit This Page","multilingual":false,"base":"https://github.com/metosin/reitit/tree/master/doc"},"github":{"url":"https://github.com/metosin/reitit"},"highlight":{},"search":{},"lunr":{"maxIndexSize":1000000,"ignoreSpecialCharacters":false},"sharing":{"facebook":true,"twitter":true,"google":false,"weibo":false,"instapaper":false,"vk":false,"all":["facebook","google","twitter","weibo","instapaper"]},"fontsettings":{"theme":"white","family":"sans","size":2},"theme-default":{"styles":{"website":"styles/website.css","pdf":"styles/pdf.css","epub":"styles/epub.css","mobi":"styles/mobi.css","ebook":"styles/ebook.css","print":"styles/print.css"},"showLevel":false}},"theme":"default","pdf":{"pageNumbers":true,"fontSize":12,"fontFamily":"Arial","paperSize":"a4","chapterMark":"pagebreak","pageBreaksBefore":"/","margin":{"right":62,"left":62,"top":56,"bottom":56}},"structure":{"langs":"LANGS.md","readme":"README.md","glossary":"GLOSSARY.md","summary":"SUMMARY.md"},"variables":{},"gitbook":"*"},"file":{"path":"dynamic_extensions.md","mtime":"2017-09-18T05:30:25.732Z","type":"markdown"},"gitbook":{"version":"3.2.3","time":"2017-09-18T05:30:51.447Z"},"basePath":".","book":{"language":""}});
|
||||
});
|
||||
</script>
|
||||
</div>
|
||||
|
||||
|
||||
<script src="gitbook/gitbook.js"></script>
|
||||
<script src="gitbook/theme.js"></script>
|
||||
|
||||
|
||||
<script src="gitbook/gitbook-plugin-editlink/plugin.js"></script>
|
||||
|
||||
|
||||
|
||||
<script src="gitbook/gitbook-plugin-github/plugin.js"></script>
|
||||
|
||||
|
||||
|
||||
<script src="gitbook/gitbook-plugin-search/search-engine.js"></script>
|
||||
|
||||
|
||||
|
||||
<script src="gitbook/gitbook-plugin-search/search.js"></script>
|
||||
|
||||
|
||||
|
||||
<script src="gitbook/gitbook-plugin-lunr/lunr.min.js"></script>
|
||||
|
||||
|
||||
|
||||
<script src="gitbook/gitbook-plugin-lunr/search-lunr.js"></script>
|
||||
|
||||
|
||||
|
||||
<script src="gitbook/gitbook-plugin-sharing/buttons.js"></script>
|
||||
|
||||
|
||||
|
||||
<script src="gitbook/gitbook-plugin-fontsettings/fontsettings.js"></script>
|
||||
|
||||
|
||||
|
||||
</body>
|
||||
</html>
|
||||
|
||||
291
index.html
291
index.html
|
|
@ -103,7 +103,7 @@
|
|||
<span>
|
||||
|
||||
|
||||
Routing
|
||||
Basics
|
||||
|
||||
</span>
|
||||
|
||||
|
|
@ -112,9 +112,9 @@
|
|||
<ul class="articles">
|
||||
|
||||
|
||||
<li class="chapter " data-level="1.2.1" data-path="routing/route_syntax.html">
|
||||
<li class="chapter " data-level="1.2.1" data-path="basics.html">
|
||||
|
||||
<a href="routing/route_syntax.html">
|
||||
<a href="basics.html#route-syntax">
|
||||
|
||||
|
||||
Route syntax
|
||||
|
|
@ -125,12 +125,12 @@
|
|||
|
||||
</li>
|
||||
|
||||
<li class="chapter " data-level="1.2.2" data-path="routing/routers.html">
|
||||
<li class="chapter " data-level="1.2.2" data-path="basics.html">
|
||||
|
||||
<a href="routing/routers.html">
|
||||
<a href="basics.html#router">
|
||||
|
||||
|
||||
Routers
|
||||
Router
|
||||
|
||||
</a>
|
||||
|
||||
|
|
@ -138,12 +138,12 @@
|
|||
|
||||
</li>
|
||||
|
||||
<li class="chapter " data-level="1.2.3" data-path="routing/route_metadata.html">
|
||||
<li class="chapter " data-level="1.2.3" data-path="basics.html">
|
||||
|
||||
<a href="routing/route_metadata.html">
|
||||
<a href="basics.html#path-based-routing">
|
||||
|
||||
|
||||
Route metadata
|
||||
Path-based Routing
|
||||
|
||||
</a>
|
||||
|
||||
|
|
@ -151,12 +151,38 @@
|
|||
|
||||
</li>
|
||||
|
||||
<li class="chapter " data-level="1.2.4" data-path="routing/route_conflicts.html">
|
||||
<li class="chapter " data-level="1.2.4" data-path="basics.html">
|
||||
|
||||
<a href="routing/route_conflicts.html">
|
||||
<a href="basics.html#name-based-routing">
|
||||
|
||||
|
||||
Route conflicts
|
||||
Name-based Routing
|
||||
|
||||
</a>
|
||||
|
||||
|
||||
|
||||
</li>
|
||||
|
||||
<li class="chapter " data-level="1.2.5" data-path="basics.html">
|
||||
|
||||
<a href="basics.html#route-data">
|
||||
|
||||
|
||||
Route data
|
||||
|
||||
</a>
|
||||
|
||||
|
||||
|
||||
</li>
|
||||
|
||||
<li class="chapter " data-level="1.2.6" data-path="basics.html">
|
||||
|
||||
<a href="basics.html#different-routers">
|
||||
|
||||
|
||||
Different Routers
|
||||
|
||||
</a>
|
||||
|
||||
|
|
@ -169,12 +195,26 @@
|
|||
|
||||
</li>
|
||||
|
||||
<li class="chapter " data-level="1.3" data-path="ring.html">
|
||||
<li class="chapter " data-level="1.3" >
|
||||
|
||||
<a href="ring.html">
|
||||
<span>
|
||||
|
||||
|
||||
Ring support
|
||||
Advanced
|
||||
|
||||
</span>
|
||||
|
||||
|
||||
|
||||
<ul class="articles">
|
||||
|
||||
|
||||
<li class="chapter " data-level="1.3.1" data-path="route_conflicts.html">
|
||||
|
||||
<a href="route_conflicts.html">
|
||||
|
||||
|
||||
Route conflicts
|
||||
|
||||
</a>
|
||||
|
||||
|
|
@ -182,12 +222,12 @@
|
|||
|
||||
</li>
|
||||
|
||||
<li class="chapter " data-level="1.4" data-path="parameter_coercion.html">
|
||||
<li class="chapter " data-level="1.3.2" data-path="route_validation.html">
|
||||
|
||||
<a href="parameter_coercion.html">
|
||||
<a href="route_validation.html">
|
||||
|
||||
|
||||
Parameter coercion
|
||||
Route Validation
|
||||
|
||||
</a>
|
||||
|
||||
|
|
@ -195,33 +235,7 @@
|
|||
|
||||
</li>
|
||||
|
||||
<li class="chapter " data-level="1.5" data-path="compiling_middleware.html">
|
||||
|
||||
<a href="compiling_middleware.html">
|
||||
|
||||
|
||||
Compiling middleware
|
||||
|
||||
</a>
|
||||
|
||||
|
||||
|
||||
</li>
|
||||
|
||||
<li class="chapter " data-level="1.6" data-path="validating.html">
|
||||
|
||||
<a href="validating.html">
|
||||
|
||||
|
||||
Validating route-trees
|
||||
|
||||
</a>
|
||||
|
||||
|
||||
|
||||
</li>
|
||||
|
||||
<li class="chapter " data-level="1.7" data-path="configuring_routers.html">
|
||||
<li class="chapter " data-level="1.3.3" data-path="configuring_routers.html">
|
||||
|
||||
<a href="configuring_routers.html">
|
||||
|
||||
|
|
@ -234,20 +248,83 @@
|
|||
|
||||
</li>
|
||||
|
||||
<li class="chapter " data-level="1.8" >
|
||||
|
||||
</ul>
|
||||
|
||||
</li>
|
||||
|
||||
<li class="chapter " data-level="1.4" >
|
||||
|
||||
<span>
|
||||
|
||||
|
||||
TODO: Merging route-trees
|
||||
Ring
|
||||
|
||||
</span>
|
||||
|
||||
|
||||
|
||||
<ul class="articles">
|
||||
|
||||
|
||||
<li class="chapter " data-level="1.4.1" data-path="ring.html">
|
||||
|
||||
<a href="ring.html">
|
||||
|
||||
|
||||
Ring-router
|
||||
|
||||
</a>
|
||||
|
||||
|
||||
|
||||
</li>
|
||||
|
||||
<li class="chapter " data-level="1.9" >
|
||||
<li class="chapter " data-level="1.4.2" data-path="dynamic_extensions.html">
|
||||
|
||||
<a href="dynamic_extensions.html">
|
||||
|
||||
|
||||
Dynamic extensions
|
||||
|
||||
</a>
|
||||
|
||||
|
||||
|
||||
</li>
|
||||
|
||||
<li class="chapter " data-level="1.4.3" data-path="parameter_coercion.html">
|
||||
|
||||
<a href="parameter_coercion.html">
|
||||
|
||||
|
||||
Parameter coercion
|
||||
|
||||
</a>
|
||||
|
||||
|
||||
|
||||
</li>
|
||||
|
||||
<li class="chapter " data-level="1.4.4" data-path="compiling_middleware.html">
|
||||
|
||||
<a href="compiling_middleware.html">
|
||||
|
||||
|
||||
Compiling middleware
|
||||
|
||||
</a>
|
||||
|
||||
|
||||
|
||||
</li>
|
||||
|
||||
|
||||
</ul>
|
||||
|
||||
</li>
|
||||
|
||||
<li class="chapter " data-level="1.5" >
|
||||
|
||||
<span>
|
||||
|
||||
|
|
@ -260,7 +337,7 @@
|
|||
|
||||
</li>
|
||||
|
||||
<li class="chapter " data-level="1.10" >
|
||||
<li class="chapter " data-level="1.6" >
|
||||
|
||||
<span>
|
||||
|
||||
|
|
@ -318,20 +395,116 @@
|
|||
|
||||
<section class="normal markdown-section">
|
||||
|
||||
<h1 id="reitit">reitit</h1>
|
||||
<p><a href="https://github.com/metosin/reitit" target="_blank">reitit</a> is a friendly data-driven router for Clojure(Script).</p>
|
||||
<h1 id="introduction">Introduction</h1>
|
||||
<p><a href="https://github.com/metosin/reitit" target="_blank">Reitit</a> is a small Clojure(Script) library for data-driven routing.</p>
|
||||
<ul>
|
||||
<li>Simple data-driven <a href="routing/route_syntax.html">route syntax</a></li>
|
||||
<li>First-class <a href="routing/route_metadata.html">route meta-data</a></li>
|
||||
<li>Generic, not tied to HTTP</li>
|
||||
<li><a href="routing/route_conflicts.html">Route conflict resolution</a></li>
|
||||
<li>Simple data-driven <a href="routing/route_syntax.md">route syntax</a></li>
|
||||
<li>First-class <a href="routing/route_metadata.md">route meta-data</a></li>
|
||||
<li>Bi-directional-routing</li>
|
||||
<li><a href="routing/route_conflicts.md">Route conflict resolution</a></li>
|
||||
<li><a href="parameter-coercion.md">Pluggable coercion</a> (<a href="https://clojure.org/about/spec" target="_blank">clojure.spec</a>)</li>
|
||||
<li>both <a href="ring.html#middleware">Middleware</a> & Interceptors</li>
|
||||
<li>Both <a href="ring.html#middleware">Middleware</a> & Interceptors</li>
|
||||
<li>Extendable</li>
|
||||
<li>Fast</li>
|
||||
</ul>
|
||||
<h2 id="latest-version">Latest version</h2>
|
||||
<p><a href="http://clojars.org/metosin/reitit" target="_blank"><img src="http://clojars.org/metosin/reitit/latest-version.svg" alt="Clojars Project"></a></p>
|
||||
<p>To use Reitit, add the following dependecy to your project:</p>
|
||||
<pre><code class="lang-clj">[metosin/reitit <span class="hljs-string">"0.1.0-SNAPSHOT"</span>]
|
||||
</code></pre>
|
||||
<h1 id="examples">Examples</h1>
|
||||
<h2 id="simple-router">Simple router</h2>
|
||||
<pre><code class="lang-clj">(<span class="hljs-name">require</span> '[reitit.core <span class="hljs-symbol">:as</span> r])
|
||||
|
||||
(<span class="hljs-name"><span class="hljs-builtin-name">def</span></span> router
|
||||
(<span class="hljs-name">r/router</span>
|
||||
[[<span class="hljs-string">"/api/ping"</span> <span class="hljs-symbol">::ping</span>]
|
||||
[<span class="hljs-string">"/api/orders/:id"</span> <span class="hljs-symbol">::order-by-id</span>]]))
|
||||
</code></pre>
|
||||
<p>Routing:</p>
|
||||
<pre><code class="lang-clj">(<span class="hljs-name">r/match-by-path</span> router <span class="hljs-string">"/api/ipa"</span>)
|
||||
<span class="hljs-comment">; nil</span>
|
||||
|
||||
(<span class="hljs-name">r/match-by-path</span> router <span class="hljs-string">"/api/ping"</span>)
|
||||
<span class="hljs-comment">; #Match{:template "/api/ping"</span>
|
||||
<span class="hljs-comment">; :meta {:name ::ping}</span>
|
||||
<span class="hljs-comment">; :result nil</span>
|
||||
<span class="hljs-comment">; :params {}</span>
|
||||
<span class="hljs-comment">; :path "/api/ping"}</span>
|
||||
|
||||
(<span class="hljs-name">r/match-by-path</span> router <span class="hljs-string">"/api/orders/1"</span>)
|
||||
<span class="hljs-comment">; #Match{:template "/api/orders/:id"</span>
|
||||
<span class="hljs-comment">; :meta {:name ::order-by-id}</span>
|
||||
<span class="hljs-comment">; :result nil</span>
|
||||
<span class="hljs-comment">; :params {:id "1"}</span>
|
||||
<span class="hljs-comment">; :path "/api/orders/1"}</span>
|
||||
</code></pre>
|
||||
<p>Reverse-routing:</p>
|
||||
<pre><code class="lang-clj">(<span class="hljs-name">r/match-by-name</span> router <span class="hljs-symbol">::ipa</span>)
|
||||
<span class="hljs-comment">; nil</span>
|
||||
|
||||
(<span class="hljs-name">r/match-by-name</span> router <span class="hljs-symbol">::ping</span>)
|
||||
<span class="hljs-comment">; #Match{:template "/api/ping"</span>
|
||||
<span class="hljs-comment">; :meta {:name ::ping}</span>
|
||||
<span class="hljs-comment">; :result nil</span>
|
||||
<span class="hljs-comment">; :params {}</span>
|
||||
<span class="hljs-comment">; :path "/api/ping"}</span>
|
||||
|
||||
(<span class="hljs-name">r/match-by-name</span> router <span class="hljs-symbol">::order-by-id</span>)
|
||||
<span class="hljs-comment">; #PartialMatch{:template "/api/orders/:id"</span>
|
||||
<span class="hljs-comment">; :meta {:name :user/order-by-id}</span>
|
||||
<span class="hljs-comment">; :result nil</span>
|
||||
<span class="hljs-comment">; :params nil</span>
|
||||
<span class="hljs-comment">; :required #{:id}}</span>
|
||||
|
||||
(<span class="hljs-name">r/partial-match?</span> (<span class="hljs-name">r/match-by-name</span> router <span class="hljs-symbol">::order-by-id</span>))
|
||||
<span class="hljs-comment">; true</span>
|
||||
|
||||
(<span class="hljs-name">r/match-by-name</span> router <span class="hljs-symbol">::order-by-id</span> {<span class="hljs-symbol">:id</span> <span class="hljs-number">2</span>})
|
||||
<span class="hljs-comment">; #Match{:template "/api/orders/:id",</span>
|
||||
<span class="hljs-comment">; :meta {:name ::order-by-id},</span>
|
||||
<span class="hljs-comment">; :result nil,</span>
|
||||
<span class="hljs-comment">; :params {:id 2},</span>
|
||||
<span class="hljs-comment">; :path "/api/orders/2"}</span>
|
||||
</code></pre>
|
||||
<h2 id="ring-router">Ring-router</h2>
|
||||
<p>Ring-router adds support for <code>:handler</code> functions, <code>:middleware</code> and routing based on <code>:request-method</code>. It also supports pluggable parameter coercion (<code>clojure.spec</code>), data-driven middleware, route and middleware compilation, dynamic extensions and more.</p>
|
||||
<pre><code class="lang-clj">(<span class="hljs-name">require</span> '[reitit.ring <span class="hljs-symbol">:as</span> ring])
|
||||
|
||||
(<span class="hljs-name"><span class="hljs-builtin-name">def</span></span> handler [_]
|
||||
{<span class="hljs-symbol">:status</span> <span class="hljs-number">200</span>, <span class="hljs-symbol">:body</span> <span class="hljs-string">"ok"</span>})
|
||||
|
||||
(<span class="hljs-name"><span class="hljs-builtin-name">defn</span></span> wrap [handler id]
|
||||
(<span class="hljs-name"><span class="hljs-builtin-name">fn</span></span> [request]
|
||||
(<span class="hljs-name">update</span> (<span class="hljs-name">handler</span> request) <span class="hljs-symbol">:wrap</span> (<span class="hljs-name">fnil</span> conj '()) id)))
|
||||
|
||||
(<span class="hljs-name"><span class="hljs-builtin-name">def</span></span> app
|
||||
(<span class="hljs-name">ring/ring-handler</span>
|
||||
(<span class="hljs-name">ring/router</span>
|
||||
[<span class="hljs-string">"/api"</span> {<span class="hljs-symbol">:middleware</span> [[wrap <span class="hljs-symbol">:api</span>]]}
|
||||
[<span class="hljs-string">"/ping"</span> {<span class="hljs-symbol">:get</span> handler
|
||||
<span class="hljs-symbol">:name</span> <span class="hljs-symbol">::ping</span>}]
|
||||
[<span class="hljs-string">"/admin"</span> {<span class="hljs-symbol">:middleware</span> [[wrap <span class="hljs-symbol">:admin</span>]]}
|
||||
[<span class="hljs-string">"/users"</span> {<span class="hljs-symbol">:get</span> handler
|
||||
<span class="hljs-symbol">:post</span> handler}]]])))
|
||||
</code></pre>
|
||||
<p>Routing:</p>
|
||||
<pre><code class="lang-clj">(<span class="hljs-name">app</span> {<span class="hljs-symbol">:request-method</span> <span class="hljs-symbol">:get</span>, <span class="hljs-symbol">:uri</span> <span class="hljs-string">"/api/admin/users"</span>})
|
||||
<span class="hljs-comment">; {:status 200, :body "ok", :wrap (:api :admin}</span>
|
||||
|
||||
(<span class="hljs-name">app</span> {<span class="hljs-symbol">:request-method</span> <span class="hljs-symbol">:put</span>, <span class="hljs-symbol">:uri</span> <span class="hljs-string">"/api/admin/users"</span>})
|
||||
<span class="hljs-comment">; nil</span>
|
||||
</code></pre>
|
||||
<p>Reverse-routing:</p>
|
||||
<pre><code class="lang-clj">(<span class="hljs-name">require</span> '[reitit.core <span class="hljs-symbol">:as</span> r])
|
||||
|
||||
(<span class="hljs-name"><span class="hljs-builtin-name">-></span></span> app (<span class="hljs-name">ring/get-router</span>) (<span class="hljs-name">r/match-by-name</span> <span class="hljs-symbol">::ping</span>))
|
||||
<span class="hljs-comment">; #Match{:template "/api/ping"</span>
|
||||
<span class="hljs-comment">; :meta {:middleware [[#object[user$wrap] :api]]</span>
|
||||
<span class="hljs-comment">; :get {:handler #object[user$handler]}</span>
|
||||
<span class="hljs-comment">; :name ::ping}</span>
|
||||
<span class="hljs-comment">; :result #Methods{...}</span>
|
||||
<span class="hljs-comment">; :params nil</span>
|
||||
<span class="hljs-comment">; :path "/api/ping"}</span>
|
||||
</code></pre>
|
||||
|
||||
|
||||
</section>
|
||||
|
|
@ -367,7 +540,7 @@
|
|||
<script>
|
||||
var gitbook = gitbook || [];
|
||||
gitbook.push(function() {
|
||||
gitbook.page.hasChanged({"page":{"title":"Introduction","level":"1.1","depth":1,"next":{"title":"Routing","level":"1.2","depth":1,"ref":"","articles":[{"title":"Route syntax","level":"1.2.1","depth":2,"path":"routing/route_syntax.md","ref":"routing/route_syntax.md","articles":[]},{"title":"Routers","level":"1.2.2","depth":2,"path":"routing/routers.md","ref":"routing/routers.md","articles":[]},{"title":"Route metadata","level":"1.2.3","depth":2,"path":"routing/route_metadata.md","ref":"routing/route_metadata.md","articles":[]},{"title":"Route conflicts","level":"1.2.4","depth":2,"path":"routing/route_conflicts.md","ref":"routing/route_conflicts.md","articles":[]}]},"dir":"ltr"},"config":{"plugins":["editlink","github","highlight"],"root":"doc","styles":{"website":"styles/website.css","pdf":"styles/pdf.css","epub":"styles/epub.css","mobi":"styles/mobi.css","ebook":"styles/ebook.css","print":"styles/print.css"},"pluginsConfig":{"editlink":{"label":"Edit This Page","multilingual":false,"base":"https://github.com/metosin/reitit/tree/master/doc"},"github":{"url":"https://github.com/metosin/reitit"},"highlight":{},"search":{},"lunr":{"maxIndexSize":1000000,"ignoreSpecialCharacters":false},"sharing":{"facebook":true,"twitter":true,"google":false,"weibo":false,"instapaper":false,"vk":false,"all":["facebook","google","twitter","weibo","instapaper"]},"fontsettings":{"theme":"white","family":"sans","size":2},"theme-default":{"styles":{"website":"styles/website.css","pdf":"styles/pdf.css","epub":"styles/epub.css","mobi":"styles/mobi.css","ebook":"styles/ebook.css","print":"styles/print.css"},"showLevel":false}},"theme":"default","pdf":{"pageNumbers":true,"fontSize":12,"fontFamily":"Arial","paperSize":"a4","chapterMark":"pagebreak","pageBreaksBefore":"/","margin":{"right":62,"left":62,"top":56,"bottom":56}},"structure":{"langs":"LANGS.md","readme":"README.md","glossary":"GLOSSARY.md","summary":"SUMMARY.md"},"variables":{},"gitbook":"*"},"file":{"path":"README.md","mtime":"2017-09-14T15:08:32.263Z","type":"markdown"},"gitbook":{"version":"3.2.3","time":"2017-09-14T15:08:59.979Z"},"basePath":".","book":{"language":""}});
|
||||
gitbook.page.hasChanged({"page":{"title":"Introduction","level":"1.1","depth":1,"next":{"title":"Basics","level":"1.2","depth":1,"ref":"","articles":[{"title":"Route syntax","level":"1.2.1","depth":2,"anchor":"#route-syntax","path":"basics.md","ref":"basics.md#route-syntax","articles":[]},{"title":"Router","level":"1.2.2","depth":2,"anchor":"#router","path":"basics.md","ref":"basics.md#router","articles":[]},{"title":"Path-based Routing","level":"1.2.3","depth":2,"anchor":"#path-based-routing","path":"basics.md","ref":"basics.md#path-based-routing","articles":[]},{"title":"Name-based Routing","level":"1.2.4","depth":2,"anchor":"#name-based-routing","path":"basics.md","ref":"basics.md#name-based-routing","articles":[]},{"title":"Route data","level":"1.2.5","depth":2,"anchor":"#route-data","path":"basics.md","ref":"basics.md#route-data","articles":[]},{"title":"Different Routers","level":"1.2.6","depth":2,"anchor":"#different-routers","path":"basics.md","ref":"basics.md#different-routers","articles":[]}]},"dir":"ltr"},"config":{"plugins":["editlink","github","highlight"],"root":"doc","styles":{"website":"styles/website.css","pdf":"styles/pdf.css","epub":"styles/epub.css","mobi":"styles/mobi.css","ebook":"styles/ebook.css","print":"styles/print.css"},"pluginsConfig":{"editlink":{"label":"Edit This Page","multilingual":false,"base":"https://github.com/metosin/reitit/tree/master/doc"},"github":{"url":"https://github.com/metosin/reitit"},"highlight":{},"search":{},"lunr":{"maxIndexSize":1000000,"ignoreSpecialCharacters":false},"sharing":{"facebook":true,"twitter":true,"google":false,"weibo":false,"instapaper":false,"vk":false,"all":["facebook","google","twitter","weibo","instapaper"]},"fontsettings":{"theme":"white","family":"sans","size":2},"theme-default":{"styles":{"website":"styles/website.css","pdf":"styles/pdf.css","epub":"styles/epub.css","mobi":"styles/mobi.css","ebook":"styles/ebook.css","print":"styles/print.css"},"showLevel":false}},"theme":"default","pdf":{"pageNumbers":true,"fontSize":12,"fontFamily":"Arial","paperSize":"a4","chapterMark":"pagebreak","pageBreaksBefore":"/","margin":{"right":62,"left":62,"top":56,"bottom":56}},"structure":{"langs":"LANGS.md","readme":"README.md","glossary":"GLOSSARY.md","summary":"SUMMARY.md"},"variables":{},"gitbook":"*"},"file":{"path":"README.md","mtime":"2017-09-18T05:30:25.732Z","type":"markdown"},"gitbook":{"version":"3.2.3","time":"2017-09-18T05:30:51.447Z"},"basePath":".","book":{"language":""}});
|
||||
});
|
||||
</script>
|
||||
</div>
|
||||
|
|
|
|||
34
middleware_records.md
Normal file
34
middleware_records.md
Normal file
|
|
@ -0,0 +1,34 @@
|
|||
# Middleware Records
|
||||
|
||||
Reitit supports first-class data-driven middleware via `reitit.middleware/Middleware` records, created with `reitit.middleware/create` function. The following keys have special purpose:
|
||||
|
||||
| key | description |
|
||||
| -----------|-------------|
|
||||
| `:name` | Name of the middleware as qualified keyword (optional,recommended for libs)
|
||||
| `:wrap` | The actual middleware function of `handler args? => request => response`
|
||||
| `:gen` | Middleware compile function, see [compiling middleware](#compiling-middleware).
|
||||
|
||||
When routes are compiled, all middleware are expanded (and optionally compiled) into `Middleware` and stored in compilation results for later use (api-docs etc). For actual request processing, they are unwrapped into normal middleware functions producing zero runtime performance penalty. Middleware expansion is backed by `reitit.middleware/IntoMiddleware` protocol, enabling plain clojure(script) maps to be used.
|
||||
|
||||
A Record:
|
||||
|
||||
```clj
|
||||
(require '[reitit.middleware :as middleware])
|
||||
|
||||
(def wrap2
|
||||
(middleware/create
|
||||
{:name ::wrap2
|
||||
:description "a nice little mw, takes 1 arg."
|
||||
:wrap wrap}))
|
||||
```
|
||||
|
||||
As plain map:
|
||||
|
||||
```clj
|
||||
;; plain map
|
||||
(def wrap3
|
||||
{:name ::wrap3
|
||||
:description "a nice little mw, :api as arg"
|
||||
:wrap (fn [handler]
|
||||
(wrap handler :api))})
|
||||
```
|
||||
|
|
@ -60,7 +60,7 @@
|
|||
<link rel="next" href="compiling_middleware.html" />
|
||||
|
||||
|
||||
<link rel="prev" href="ring.html" />
|
||||
<link rel="prev" href="dynamic_extensions.html" />
|
||||
|
||||
|
||||
</head>
|
||||
|
|
@ -107,7 +107,7 @@
|
|||
<span>
|
||||
|
||||
|
||||
Routing
|
||||
Basics
|
||||
|
||||
</span>
|
||||
|
||||
|
|
@ -116,9 +116,9 @@
|
|||
<ul class="articles">
|
||||
|
||||
|
||||
<li class="chapter " data-level="1.2.1" data-path="routing/route_syntax.html">
|
||||
<li class="chapter " data-level="1.2.1" data-path="basics.html">
|
||||
|
||||
<a href="routing/route_syntax.html">
|
||||
<a href="basics.html#route-syntax">
|
||||
|
||||
|
||||
Route syntax
|
||||
|
|
@ -129,12 +129,12 @@
|
|||
|
||||
</li>
|
||||
|
||||
<li class="chapter " data-level="1.2.2" data-path="routing/routers.html">
|
||||
<li class="chapter " data-level="1.2.2" data-path="basics.html">
|
||||
|
||||
<a href="routing/routers.html">
|
||||
<a href="basics.html#router">
|
||||
|
||||
|
||||
Routers
|
||||
Router
|
||||
|
||||
</a>
|
||||
|
||||
|
|
@ -142,12 +142,12 @@
|
|||
|
||||
</li>
|
||||
|
||||
<li class="chapter " data-level="1.2.3" data-path="routing/route_metadata.html">
|
||||
<li class="chapter " data-level="1.2.3" data-path="basics.html">
|
||||
|
||||
<a href="routing/route_metadata.html">
|
||||
<a href="basics.html#path-based-routing">
|
||||
|
||||
|
||||
Route metadata
|
||||
Path-based Routing
|
||||
|
||||
</a>
|
||||
|
||||
|
|
@ -155,12 +155,38 @@
|
|||
|
||||
</li>
|
||||
|
||||
<li class="chapter " data-level="1.2.4" data-path="routing/route_conflicts.html">
|
||||
<li class="chapter " data-level="1.2.4" data-path="basics.html">
|
||||
|
||||
<a href="routing/route_conflicts.html">
|
||||
<a href="basics.html#name-based-routing">
|
||||
|
||||
|
||||
Route conflicts
|
||||
Name-based Routing
|
||||
|
||||
</a>
|
||||
|
||||
|
||||
|
||||
</li>
|
||||
|
||||
<li class="chapter " data-level="1.2.5" data-path="basics.html">
|
||||
|
||||
<a href="basics.html#route-data">
|
||||
|
||||
|
||||
Route data
|
||||
|
||||
</a>
|
||||
|
||||
|
||||
|
||||
</li>
|
||||
|
||||
<li class="chapter " data-level="1.2.6" data-path="basics.html">
|
||||
|
||||
<a href="basics.html#different-routers">
|
||||
|
||||
|
||||
Different Routers
|
||||
|
||||
</a>
|
||||
|
||||
|
|
@ -173,12 +199,26 @@
|
|||
|
||||
</li>
|
||||
|
||||
<li class="chapter " data-level="1.3" data-path="ring.html">
|
||||
<li class="chapter " data-level="1.3" >
|
||||
|
||||
<a href="ring.html">
|
||||
<span>
|
||||
|
||||
|
||||
Ring support
|
||||
Advanced
|
||||
|
||||
</span>
|
||||
|
||||
|
||||
|
||||
<ul class="articles">
|
||||
|
||||
|
||||
<li class="chapter " data-level="1.3.1" data-path="route_conflicts.html">
|
||||
|
||||
<a href="route_conflicts.html">
|
||||
|
||||
|
||||
Route conflicts
|
||||
|
||||
</a>
|
||||
|
||||
|
|
@ -186,12 +226,12 @@
|
|||
|
||||
</li>
|
||||
|
||||
<li class="chapter active" data-level="1.4" data-path="parameter_coercion.html">
|
||||
<li class="chapter " data-level="1.3.2" data-path="route_validation.html">
|
||||
|
||||
<a href="parameter_coercion.html">
|
||||
<a href="route_validation.html">
|
||||
|
||||
|
||||
Parameter coercion
|
||||
Route Validation
|
||||
|
||||
</a>
|
||||
|
||||
|
|
@ -199,33 +239,7 @@
|
|||
|
||||
</li>
|
||||
|
||||
<li class="chapter " data-level="1.5" data-path="compiling_middleware.html">
|
||||
|
||||
<a href="compiling_middleware.html">
|
||||
|
||||
|
||||
Compiling middleware
|
||||
|
||||
</a>
|
||||
|
||||
|
||||
|
||||
</li>
|
||||
|
||||
<li class="chapter " data-level="1.6" data-path="validating.html">
|
||||
|
||||
<a href="validating.html">
|
||||
|
||||
|
||||
Validating route-trees
|
||||
|
||||
</a>
|
||||
|
||||
|
||||
|
||||
</li>
|
||||
|
||||
<li class="chapter " data-level="1.7" data-path="configuring_routers.html">
|
||||
<li class="chapter " data-level="1.3.3" data-path="configuring_routers.html">
|
||||
|
||||
<a href="configuring_routers.html">
|
||||
|
||||
|
|
@ -238,20 +252,83 @@
|
|||
|
||||
</li>
|
||||
|
||||
<li class="chapter " data-level="1.8" >
|
||||
|
||||
</ul>
|
||||
|
||||
</li>
|
||||
|
||||
<li class="chapter " data-level="1.4" >
|
||||
|
||||
<span>
|
||||
|
||||
|
||||
TODO: Merging route-trees
|
||||
Ring
|
||||
|
||||
</span>
|
||||
|
||||
|
||||
|
||||
<ul class="articles">
|
||||
|
||||
|
||||
<li class="chapter " data-level="1.4.1" data-path="ring.html">
|
||||
|
||||
<a href="ring.html">
|
||||
|
||||
|
||||
Ring-router
|
||||
|
||||
</a>
|
||||
|
||||
|
||||
|
||||
</li>
|
||||
|
||||
<li class="chapter " data-level="1.9" >
|
||||
<li class="chapter " data-level="1.4.2" data-path="dynamic_extensions.html">
|
||||
|
||||
<a href="dynamic_extensions.html">
|
||||
|
||||
|
||||
Dynamic extensions
|
||||
|
||||
</a>
|
||||
|
||||
|
||||
|
||||
</li>
|
||||
|
||||
<li class="chapter active" data-level="1.4.3" data-path="parameter_coercion.html">
|
||||
|
||||
<a href="parameter_coercion.html">
|
||||
|
||||
|
||||
Parameter coercion
|
||||
|
||||
</a>
|
||||
|
||||
|
||||
|
||||
</li>
|
||||
|
||||
<li class="chapter " data-level="1.4.4" data-path="compiling_middleware.html">
|
||||
|
||||
<a href="compiling_middleware.html">
|
||||
|
||||
|
||||
Compiling middleware
|
||||
|
||||
</a>
|
||||
|
||||
|
||||
|
||||
</li>
|
||||
|
||||
|
||||
</ul>
|
||||
|
||||
</li>
|
||||
|
||||
<li class="chapter " data-level="1.5" >
|
||||
|
||||
<span>
|
||||
|
||||
|
|
@ -264,7 +341,7 @@
|
|||
|
||||
</li>
|
||||
|
||||
<li class="chapter " data-level="1.10" >
|
||||
<li class="chapter " data-level="1.6" >
|
||||
|
||||
<span>
|
||||
|
||||
|
|
@ -425,7 +502,7 @@
|
|||
|
||||
|
||||
|
||||
<a href="ring.html" class="navigation navigation-prev " aria-label="Previous page: Ring support">
|
||||
<a href="dynamic_extensions.html" class="navigation navigation-prev " aria-label="Previous page: Dynamic extensions">
|
||||
<i class="fa fa-angle-left"></i>
|
||||
</a>
|
||||
|
||||
|
|
@ -441,7 +518,7 @@
|
|||
<script>
|
||||
var gitbook = gitbook || [];
|
||||
gitbook.push(function() {
|
||||
gitbook.page.hasChanged({"page":{"title":"Parameter coercion","level":"1.4","depth":1,"next":{"title":"Compiling middleware","level":"1.5","depth":1,"path":"compiling_middleware.md","ref":"compiling_middleware.md","articles":[]},"previous":{"title":"Ring support","level":"1.3","depth":1,"path":"ring.md","ref":"ring.md","articles":[]},"dir":"ltr"},"config":{"plugins":["editlink","github","highlight"],"root":"doc","styles":{"website":"styles/website.css","pdf":"styles/pdf.css","epub":"styles/epub.css","mobi":"styles/mobi.css","ebook":"styles/ebook.css","print":"styles/print.css"},"pluginsConfig":{"editlink":{"label":"Edit This Page","multilingual":false,"base":"https://github.com/metosin/reitit/tree/master/doc"},"github":{"url":"https://github.com/metosin/reitit"},"highlight":{},"search":{},"lunr":{"maxIndexSize":1000000,"ignoreSpecialCharacters":false},"sharing":{"facebook":true,"twitter":true,"google":false,"weibo":false,"instapaper":false,"vk":false,"all":["facebook","google","twitter","weibo","instapaper"]},"fontsettings":{"theme":"white","family":"sans","size":2},"theme-default":{"styles":{"website":"styles/website.css","pdf":"styles/pdf.css","epub":"styles/epub.css","mobi":"styles/mobi.css","ebook":"styles/ebook.css","print":"styles/print.css"},"showLevel":false}},"theme":"default","pdf":{"pageNumbers":true,"fontSize":12,"fontFamily":"Arial","paperSize":"a4","chapterMark":"pagebreak","pageBreaksBefore":"/","margin":{"right":62,"left":62,"top":56,"bottom":56}},"structure":{"langs":"LANGS.md","readme":"README.md","glossary":"GLOSSARY.md","summary":"SUMMARY.md"},"variables":{},"gitbook":"*"},"file":{"path":"parameter_coercion.md","mtime":"2017-09-14T15:08:32.263Z","type":"markdown"},"gitbook":{"version":"3.2.3","time":"2017-09-14T15:08:59.979Z"},"basePath":".","book":{"language":""}});
|
||||
gitbook.page.hasChanged({"page":{"title":"Parameter coercion","level":"1.4.3","depth":2,"next":{"title":"Compiling middleware","level":"1.4.4","depth":2,"path":"compiling_middleware.md","ref":"compiling_middleware.md","articles":[]},"previous":{"title":"Dynamic extensions","level":"1.4.2","depth":2,"path":"dynamic_extensions.md","ref":"dynamic_extensions.md","articles":[]},"dir":"ltr"},"config":{"plugins":["editlink","github","highlight"],"root":"doc","styles":{"website":"styles/website.css","pdf":"styles/pdf.css","epub":"styles/epub.css","mobi":"styles/mobi.css","ebook":"styles/ebook.css","print":"styles/print.css"},"pluginsConfig":{"editlink":{"label":"Edit This Page","multilingual":false,"base":"https://github.com/metosin/reitit/tree/master/doc"},"github":{"url":"https://github.com/metosin/reitit"},"highlight":{},"search":{},"lunr":{"maxIndexSize":1000000,"ignoreSpecialCharacters":false},"sharing":{"facebook":true,"twitter":true,"google":false,"weibo":false,"instapaper":false,"vk":false,"all":["facebook","google","twitter","weibo","instapaper"]},"fontsettings":{"theme":"white","family":"sans","size":2},"theme-default":{"styles":{"website":"styles/website.css","pdf":"styles/pdf.css","epub":"styles/epub.css","mobi":"styles/mobi.css","ebook":"styles/ebook.css","print":"styles/print.css"},"showLevel":false}},"theme":"default","pdf":{"pageNumbers":true,"fontSize":12,"fontFamily":"Arial","paperSize":"a4","chapterMark":"pagebreak","pageBreaksBefore":"/","margin":{"right":62,"left":62,"top":56,"bottom":56}},"structure":{"langs":"LANGS.md","readme":"README.md","glossary":"GLOSSARY.md","summary":"SUMMARY.md"},"variables":{},"gitbook":"*"},"file":{"path":"parameter_coercion.md","mtime":"2017-09-18T05:30:25.732Z","type":"markdown"},"gitbook":{"version":"3.2.3","time":"2017-09-18T05:30:51.447Z"},"basePath":".","book":{"language":""}});
|
||||
});
|
||||
</script>
|
||||
</div>
|
||||
|
|
|
|||
279
ring.html
279
ring.html
|
|
@ -4,7 +4,7 @@
|
|||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta content="text/html; charset=utf-8" http-equiv="Content-Type">
|
||||
<title>Ring support · GitBook</title>
|
||||
<title>Ring-router · GitBook</title>
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
|
||||
<meta name="description" content="">
|
||||
<meta name="generator" content="GitBook 3.2.3">
|
||||
|
|
@ -57,11 +57,9 @@
|
|||
<link rel="shortcut icon" href="gitbook/images/favicon.ico" type="image/x-icon">
|
||||
|
||||
|
||||
<link rel="next" href="parameter_coercion.html" />
|
||||
<link rel="next" href="dynamic_extensions.html" />
|
||||
|
||||
|
||||
<link rel="prev" href="routing/route_conflicts.html" />
|
||||
|
||||
|
||||
</head>
|
||||
<body>
|
||||
|
|
@ -107,7 +105,7 @@
|
|||
<span>
|
||||
|
||||
|
||||
Routing
|
||||
Basics
|
||||
|
||||
</span>
|
||||
|
||||
|
|
@ -116,9 +114,9 @@
|
|||
<ul class="articles">
|
||||
|
||||
|
||||
<li class="chapter " data-level="1.2.1" data-path="routing/route_syntax.html">
|
||||
<li class="chapter " data-level="1.2.1" data-path="basics.html">
|
||||
|
||||
<a href="routing/route_syntax.html">
|
||||
<a href="basics.html#route-syntax">
|
||||
|
||||
|
||||
Route syntax
|
||||
|
|
@ -129,12 +127,12 @@
|
|||
|
||||
</li>
|
||||
|
||||
<li class="chapter " data-level="1.2.2" data-path="routing/routers.html">
|
||||
<li class="chapter " data-level="1.2.2" data-path="basics.html">
|
||||
|
||||
<a href="routing/routers.html">
|
||||
<a href="basics.html#router">
|
||||
|
||||
|
||||
Routers
|
||||
Router
|
||||
|
||||
</a>
|
||||
|
||||
|
|
@ -142,12 +140,12 @@
|
|||
|
||||
</li>
|
||||
|
||||
<li class="chapter " data-level="1.2.3" data-path="routing/route_metadata.html">
|
||||
<li class="chapter " data-level="1.2.3" data-path="basics.html">
|
||||
|
||||
<a href="routing/route_metadata.html">
|
||||
<a href="basics.html#path-based-routing">
|
||||
|
||||
|
||||
Route metadata
|
||||
Path-based Routing
|
||||
|
||||
</a>
|
||||
|
||||
|
|
@ -155,12 +153,38 @@
|
|||
|
||||
</li>
|
||||
|
||||
<li class="chapter " data-level="1.2.4" data-path="routing/route_conflicts.html">
|
||||
<li class="chapter " data-level="1.2.4" data-path="basics.html">
|
||||
|
||||
<a href="routing/route_conflicts.html">
|
||||
<a href="basics.html#name-based-routing">
|
||||
|
||||
|
||||
Route conflicts
|
||||
Name-based Routing
|
||||
|
||||
</a>
|
||||
|
||||
|
||||
|
||||
</li>
|
||||
|
||||
<li class="chapter " data-level="1.2.5" data-path="basics.html">
|
||||
|
||||
<a href="basics.html#route-data">
|
||||
|
||||
|
||||
Route data
|
||||
|
||||
</a>
|
||||
|
||||
|
||||
|
||||
</li>
|
||||
|
||||
<li class="chapter " data-level="1.2.6" data-path="basics.html">
|
||||
|
||||
<a href="basics.html#different-routers">
|
||||
|
||||
|
||||
Different Routers
|
||||
|
||||
</a>
|
||||
|
||||
|
|
@ -173,12 +197,26 @@
|
|||
|
||||
</li>
|
||||
|
||||
<li class="chapter active" data-level="1.3" data-path="ring.html">
|
||||
<li class="chapter " data-level="1.3" >
|
||||
|
||||
<a href="ring.html">
|
||||
<span>
|
||||
|
||||
|
||||
Ring support
|
||||
Advanced
|
||||
|
||||
</span>
|
||||
|
||||
|
||||
|
||||
<ul class="articles">
|
||||
|
||||
|
||||
<li class="chapter " data-level="1.3.1" data-path="route_conflicts.html">
|
||||
|
||||
<a href="route_conflicts.html">
|
||||
|
||||
|
||||
Route conflicts
|
||||
|
||||
</a>
|
||||
|
||||
|
|
@ -186,12 +224,12 @@
|
|||
|
||||
</li>
|
||||
|
||||
<li class="chapter " data-level="1.4" data-path="parameter_coercion.html">
|
||||
<li class="chapter " data-level="1.3.2" data-path="route_validation.html">
|
||||
|
||||
<a href="parameter_coercion.html">
|
||||
<a href="route_validation.html">
|
||||
|
||||
|
||||
Parameter coercion
|
||||
Route Validation
|
||||
|
||||
</a>
|
||||
|
||||
|
|
@ -199,33 +237,7 @@
|
|||
|
||||
</li>
|
||||
|
||||
<li class="chapter " data-level="1.5" data-path="compiling_middleware.html">
|
||||
|
||||
<a href="compiling_middleware.html">
|
||||
|
||||
|
||||
Compiling middleware
|
||||
|
||||
</a>
|
||||
|
||||
|
||||
|
||||
</li>
|
||||
|
||||
<li class="chapter " data-level="1.6" data-path="validating.html">
|
||||
|
||||
<a href="validating.html">
|
||||
|
||||
|
||||
Validating route-trees
|
||||
|
||||
</a>
|
||||
|
||||
|
||||
|
||||
</li>
|
||||
|
||||
<li class="chapter " data-level="1.7" data-path="configuring_routers.html">
|
||||
<li class="chapter " data-level="1.3.3" data-path="configuring_routers.html">
|
||||
|
||||
<a href="configuring_routers.html">
|
||||
|
||||
|
|
@ -238,20 +250,83 @@
|
|||
|
||||
</li>
|
||||
|
||||
<li class="chapter " data-level="1.8" >
|
||||
|
||||
</ul>
|
||||
|
||||
</li>
|
||||
|
||||
<li class="chapter " data-level="1.4" >
|
||||
|
||||
<span>
|
||||
|
||||
|
||||
TODO: Merging route-trees
|
||||
Ring
|
||||
|
||||
</span>
|
||||
|
||||
|
||||
|
||||
<ul class="articles">
|
||||
|
||||
|
||||
<li class="chapter active" data-level="1.4.1" data-path="ring.html">
|
||||
|
||||
<a href="ring.html">
|
||||
|
||||
|
||||
Ring-router
|
||||
|
||||
</a>
|
||||
|
||||
|
||||
|
||||
</li>
|
||||
|
||||
<li class="chapter " data-level="1.9" >
|
||||
<li class="chapter " data-level="1.4.2" data-path="dynamic_extensions.html">
|
||||
|
||||
<a href="dynamic_extensions.html">
|
||||
|
||||
|
||||
Dynamic extensions
|
||||
|
||||
</a>
|
||||
|
||||
|
||||
|
||||
</li>
|
||||
|
||||
<li class="chapter " data-level="1.4.3" data-path="parameter_coercion.html">
|
||||
|
||||
<a href="parameter_coercion.html">
|
||||
|
||||
|
||||
Parameter coercion
|
||||
|
||||
</a>
|
||||
|
||||
|
||||
|
||||
</li>
|
||||
|
||||
<li class="chapter " data-level="1.4.4" data-path="compiling_middleware.html">
|
||||
|
||||
<a href="compiling_middleware.html">
|
||||
|
||||
|
||||
Compiling middleware
|
||||
|
||||
</a>
|
||||
|
||||
|
||||
|
||||
</li>
|
||||
|
||||
|
||||
</ul>
|
||||
|
||||
</li>
|
||||
|
||||
<li class="chapter " data-level="1.5" >
|
||||
|
||||
<span>
|
||||
|
||||
|
|
@ -264,7 +339,7 @@
|
|||
|
||||
</li>
|
||||
|
||||
<li class="chapter " data-level="1.10" >
|
||||
<li class="chapter " data-level="1.6" >
|
||||
|
||||
<span>
|
||||
|
||||
|
|
@ -307,7 +382,7 @@
|
|||
<!-- Title -->
|
||||
<h1>
|
||||
<i class="fa fa-circle-o-notch fa-spin"></i>
|
||||
<a href="." >Ring support</a>
|
||||
<a href="." >Ring-router</a>
|
||||
</h1>
|
||||
</div>
|
||||
|
||||
|
|
@ -322,8 +397,8 @@
|
|||
|
||||
<section class="normal markdown-section">
|
||||
|
||||
<h1 id="ring-support">Ring support</h1>
|
||||
<p><a href="https://github.com/ring-clojure/ring" target="_blank">Ring</a>-router adds support for ring concepts like <a href="https://github.com/ring-clojure/ring/wiki/Concepts#handlers" target="_blank">handlers</a>, <a href="https://github.com/ring-clojure/ring/wiki/Concepts#middleware" target="_blank">middleware</a> and routing based on <code>:request-method</code>. Ring-router is created with <code>reitit.ring/router</code> function. It runs a custom route compiler, creating a optimized stucture for handling route matches, with compiled middleware chain & handlers for all request methods. It also ensures that all routes have a <code>:handler</code> defined.</p>
|
||||
<h1 id="ring-router">Ring Router</h1>
|
||||
<p><a href="https://github.com/ring-clojure/ring" target="_blank">Ring</a>-router adds support for <a href="https://github.com/ring-clojure/ring/wiki/Concepts#handlers" target="_blank">handlers</a>, <a href="https://github.com/ring-clojure/ring/wiki/Concepts#middleware" target="_blank">middleware</a> and routing based on <code>:request-method</code>. Ring-router is created with <code>reitit.ring/router</code> function. It runs a custom route compiler, creating a optimized stucture for handling route matches, with compiled middleware chain & handlers for all request methods. It also ensures that all routes have a <code>:handler</code> defined.</p>
|
||||
<p>Simple Ring app:</p>
|
||||
<pre><code class="lang-clj">(<span class="hljs-name">require</span> '[reitit.ring <span class="hljs-symbol">:as</span> ring])
|
||||
|
||||
|
|
@ -351,7 +426,7 @@
|
|||
<span class="hljs-comment">; :middleware []}}]]</span>
|
||||
</code></pre>
|
||||
<p>Note that the compiled resuts as third element in the route vector.</p>
|
||||
<h3 id="request-method-based-routing">Request-method based routing</h3>
|
||||
<h1 id="request-method-based-routing">Request-method based routing</h1>
|
||||
<p>Handler are also looked under request-method keys: <code>:get</code>, <code>:head</code>, <code>:patch</code>, <code>:delete</code>, <code>:options</code>, <code>:post</code> or <code>:put</code>. Top-level handler is used if request-method based handler is not found.</p>
|
||||
<pre><code class="lang-clj">(<span class="hljs-name"><span class="hljs-builtin-name">def</span></span> app
|
||||
(<span class="hljs-name">ring/ring-handler</span>
|
||||
|
|
@ -373,7 +448,7 @@
|
|||
<span class="hljs-symbol">:path</span>)
|
||||
<span class="hljs-comment">; "/ping"</span>
|
||||
</code></pre>
|
||||
<h3 id="middleware">Middleware</h3>
|
||||
<h1 id="middleware">Middleware</h1>
|
||||
<p>Middleware can be added with a <code>:middleware</code> key, with a vector value of the following:</p>
|
||||
<ol>
|
||||
<li>ring middleware function <code>handler -> request -> response</code></li>
|
||||
|
|
@ -405,86 +480,8 @@
|
|||
<pre><code class="lang-clj">(<span class="hljs-name">app</span> {<span class="hljs-symbol">:request-method</span> <span class="hljs-symbol">:delete</span>, <span class="hljs-symbol">:uri</span> <span class="hljs-string">"/api/admin/db"</span>})
|
||||
<span class="hljs-comment">; {:status 200, :body [:api :admin :db :delete :handler]}</span>
|
||||
</code></pre>
|
||||
<h3 id="middleware-records">Middleware Records</h3>
|
||||
<p>Reitit supports first-class data-driven middleware via <code>reitit.middleware/Middleware</code> records, created with <code>reitit.middleware/create</code> function. The following keys have special purpose:</p>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>key</th>
|
||||
<th>description</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td><code>:name</code></td>
|
||||
<td>Name of the middleware as qualified keyword (optional,recommended for libs)</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>:wrap</code></td>
|
||||
<td>The actual middleware function of <code>handler args? => request => response</code></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>:gen</code></td>
|
||||
<td>Middleware compile function, see <a href="#compiling-middleware">compiling middleware</a>.</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<p>When routes are compiled, all middleware are expanded (and optionally compiled) into <code>Middleware</code> and stored in compilation results for later use (api-docs etc). For actual request processing, they are unwrapped into normal middleware functions producing zero runtime performance penalty. Middleware expansion is backed by <code>reitit.middleware/IntoMiddleware</code> protocol, enabling plain clojure(script) maps to be used.</p>
|
||||
<p>A Record:</p>
|
||||
<pre><code class="lang-clj">(<span class="hljs-name">require</span> '[reitit.middleware <span class="hljs-symbol">:as</span> middleware])
|
||||
|
||||
(<span class="hljs-name"><span class="hljs-builtin-name">def</span></span> wrap2
|
||||
(<span class="hljs-name">middleware/create</span>
|
||||
{<span class="hljs-symbol">:name</span> <span class="hljs-symbol">::wrap2</span>
|
||||
<span class="hljs-symbol">:description</span> <span class="hljs-string">"a nice little mw, takes 1 arg."</span>
|
||||
<span class="hljs-symbol">:wrap</span> wrap}))
|
||||
</code></pre>
|
||||
<p>As plain map:</p>
|
||||
<pre><code class="lang-clj"><span class="hljs-comment">;; plain map</span>
|
||||
(<span class="hljs-name"><span class="hljs-builtin-name">def</span></span> wrap3
|
||||
{<span class="hljs-symbol">:name</span> <span class="hljs-symbol">::wrap3</span>
|
||||
<span class="hljs-symbol">:description</span> <span class="hljs-string">"a nice little mw, :api as arg"</span>
|
||||
<span class="hljs-symbol">:wrap</span> (<span class="hljs-name"><span class="hljs-builtin-name">fn</span></span> [handler]
|
||||
(<span class="hljs-name">wrap</span> handler <span class="hljs-symbol">:api</span>))})
|
||||
</code></pre>
|
||||
<h3 id="async-ring">Async Ring</h3>
|
||||
<h1 id="async-ring">Async Ring</h1>
|
||||
<p>All built-in middleware provide both 2 and 3-arity and are compiled for both Clojure & ClojureScript, so they work with <a href="https://www.booleanknot.com/blog/2016/07/15/asynchronous-ring.html" target="_blank">Async Ring</a> and <a href="https://nodejs.org" target="_blank">Node.js</a> too.</p>
|
||||
<h3 id="meta-data-based-extensions">Meta-data based extensions</h3>
|
||||
<p><code>ring-handler</code> injects the <code>Match</code> into a request and it can be extracted at runtime with <code>reitit.ring/get-match</code>. This can be used to build dynamic extensions to the system.</p>
|
||||
<p>Example middleware to guard routes based on user roles:</p>
|
||||
<pre><code class="lang-clj">(<span class="hljs-name">require</span> '[clojure.set <span class="hljs-symbol">:as</span> set])
|
||||
|
||||
(<span class="hljs-name"><span class="hljs-builtin-name">defn</span></span> wrap-enforce-roles [handler]
|
||||
(<span class="hljs-name"><span class="hljs-builtin-name">fn</span></span> [{<span class="hljs-symbol">:keys</span> [<span class="hljs-symbol">::roles</span>] <span class="hljs-symbol">:as</span> request}]
|
||||
(<span class="hljs-name"><span class="hljs-builtin-name">let</span></span> [required (<span class="hljs-name">some-></span> request (<span class="hljs-name">ring/get-match</span>) <span class="hljs-symbol">:meta</span> <span class="hljs-symbol">::roles</span>)]
|
||||
(<span class="hljs-name"><span class="hljs-builtin-name">if</span></span> (<span class="hljs-name"><span class="hljs-builtin-name">and</span></span> (<span class="hljs-name"><span class="hljs-builtin-name">seq</span></span> required) (<span class="hljs-name"><span class="hljs-builtin-name">not</span></span> (<span class="hljs-name">set/intersection</span> required roles)))
|
||||
{<span class="hljs-symbol">:status</span> <span class="hljs-number">403</span>, <span class="hljs-symbol">:body</span> <span class="hljs-string">"forbidden"</span>}
|
||||
(<span class="hljs-name">handler</span> request)))))
|
||||
</code></pre>
|
||||
<p>Mounted to an app via router meta-data (effecting all routes):</p>
|
||||
<pre><code class="lang-clj">(<span class="hljs-name"><span class="hljs-builtin-name">def</span></span> handler (<span class="hljs-name"><span class="hljs-builtin-name">constantly</span></span> {<span class="hljs-symbol">:status</span> <span class="hljs-number">200</span>, <span class="hljs-symbol">:body</span> <span class="hljs-string">"ok"</span>}))
|
||||
|
||||
(<span class="hljs-name"><span class="hljs-builtin-name">def</span></span> app
|
||||
(<span class="hljs-name">ring/ring-handler</span>
|
||||
(<span class="hljs-name">ring/router</span>
|
||||
[[<span class="hljs-string">"/api"</span>
|
||||
[<span class="hljs-string">"/ping"</span> handler]
|
||||
[<span class="hljs-string">"/admin"</span> {<span class="hljs-symbol">::roles</span> #{<span class="hljs-symbol">:admin</span>}}
|
||||
[<span class="hljs-string">"/ping"</span> handler]]]]
|
||||
{<span class="hljs-symbol">:meta</span> {<span class="hljs-symbol">:middleware</span> [wrap-enforce-roles]}})))
|
||||
</code></pre>
|
||||
<p>Anonymous access to public route:</p>
|
||||
<pre><code class="lang-clj">(<span class="hljs-name">app</span> {<span class="hljs-symbol">:request-method</span> <span class="hljs-symbol">:get</span>, <span class="hljs-symbol">:uri</span> <span class="hljs-string">"/api/ping"</span>})
|
||||
<span class="hljs-comment">; {:status 200, :body "ok"}</span>
|
||||
</code></pre>
|
||||
<p>Anonymous access to guarded route:</p>
|
||||
<pre><code class="lang-clj">(<span class="hljs-name">app</span> {<span class="hljs-symbol">:request-method</span> <span class="hljs-symbol">:get</span>, <span class="hljs-symbol">:uri</span> <span class="hljs-string">"/api/admin/ping"</span>})
|
||||
<span class="hljs-comment">; {:status 403, :body "forbidden"}</span>
|
||||
</code></pre>
|
||||
<p>Authorized access to guarded route:</p>
|
||||
<pre><code class="lang-clj">(<span class="hljs-name">app</span> {<span class="hljs-symbol">:request-method</span> <span class="hljs-symbol">:get</span>, <span class="hljs-symbol">:uri</span> <span class="hljs-string">"/api/admin/ping"</span>, <span class="hljs-symbol">::roles</span> #{<span class="hljs-symbol">:admin</span>}})
|
||||
<span class="hljs-comment">; {:status 200, :body "ok"}</span>
|
||||
</code></pre>
|
||||
|
||||
|
||||
</section>
|
||||
|
|
@ -512,12 +509,8 @@
|
|||
|
||||
|
||||
|
||||
<a href="routing/route_conflicts.html" class="navigation navigation-prev " aria-label="Previous page: Route conflicts">
|
||||
<i class="fa fa-angle-left"></i>
|
||||
</a>
|
||||
|
||||
|
||||
<a href="parameter_coercion.html" class="navigation navigation-next " aria-label="Next page: Parameter coercion">
|
||||
<a href="dynamic_extensions.html" class="navigation navigation-next navigation-unique" aria-label="Next page: Dynamic extensions">
|
||||
<i class="fa fa-angle-right"></i>
|
||||
</a>
|
||||
|
||||
|
|
@ -528,7 +521,7 @@
|
|||
<script>
|
||||
var gitbook = gitbook || [];
|
||||
gitbook.push(function() {
|
||||
gitbook.page.hasChanged({"page":{"title":"Ring support","level":"1.3","depth":1,"next":{"title":"Parameter coercion","level":"1.4","depth":1,"path":"parameter_coercion.md","ref":"parameter_coercion.md","articles":[]},"previous":{"title":"Route conflicts","level":"1.2.4","depth":2,"path":"routing/route_conflicts.md","ref":"routing/route_conflicts.md","articles":[]},"dir":"ltr"},"config":{"plugins":["editlink","github","highlight"],"root":"doc","styles":{"website":"styles/website.css","pdf":"styles/pdf.css","epub":"styles/epub.css","mobi":"styles/mobi.css","ebook":"styles/ebook.css","print":"styles/print.css"},"pluginsConfig":{"editlink":{"label":"Edit This Page","multilingual":false,"base":"https://github.com/metosin/reitit/tree/master/doc"},"github":{"url":"https://github.com/metosin/reitit"},"highlight":{},"search":{},"lunr":{"maxIndexSize":1000000,"ignoreSpecialCharacters":false},"sharing":{"facebook":true,"twitter":true,"google":false,"weibo":false,"instapaper":false,"vk":false,"all":["facebook","google","twitter","weibo","instapaper"]},"fontsettings":{"theme":"white","family":"sans","size":2},"theme-default":{"styles":{"website":"styles/website.css","pdf":"styles/pdf.css","epub":"styles/epub.css","mobi":"styles/mobi.css","ebook":"styles/ebook.css","print":"styles/print.css"},"showLevel":false}},"theme":"default","pdf":{"pageNumbers":true,"fontSize":12,"fontFamily":"Arial","paperSize":"a4","chapterMark":"pagebreak","pageBreaksBefore":"/","margin":{"right":62,"left":62,"top":56,"bottom":56}},"structure":{"langs":"LANGS.md","readme":"README.md","glossary":"GLOSSARY.md","summary":"SUMMARY.md"},"variables":{},"gitbook":"*"},"file":{"path":"ring.md","mtime":"2017-09-14T15:08:32.263Z","type":"markdown"},"gitbook":{"version":"3.2.3","time":"2017-09-14T15:08:59.979Z"},"basePath":".","book":{"language":""}});
|
||||
gitbook.page.hasChanged({"page":{"title":"Ring-router","level":"1.4.1","depth":2,"next":{"title":"Dynamic extensions","level":"1.4.2","depth":2,"path":"dynamic_extensions.md","ref":"dynamic_extensions.md","articles":[]},"previous":{"title":"Ring","level":"1.4","depth":1,"ref":"","articles":[{"title":"Ring-router","level":"1.4.1","depth":2,"path":"ring.md","ref":"ring.md","articles":[]},{"title":"Dynamic extensions","level":"1.4.2","depth":2,"path":"dynamic_extensions.md","ref":"dynamic_extensions.md","articles":[]},{"title":"Parameter coercion","level":"1.4.3","depth":2,"path":"parameter_coercion.md","ref":"parameter_coercion.md","articles":[]},{"title":"Compiling middleware","level":"1.4.4","depth":2,"path":"compiling_middleware.md","ref":"compiling_middleware.md","articles":[]}]},"dir":"ltr"},"config":{"plugins":["editlink","github","highlight"],"root":"doc","styles":{"website":"styles/website.css","pdf":"styles/pdf.css","epub":"styles/epub.css","mobi":"styles/mobi.css","ebook":"styles/ebook.css","print":"styles/print.css"},"pluginsConfig":{"editlink":{"label":"Edit This Page","multilingual":false,"base":"https://github.com/metosin/reitit/tree/master/doc"},"github":{"url":"https://github.com/metosin/reitit"},"highlight":{},"search":{},"lunr":{"maxIndexSize":1000000,"ignoreSpecialCharacters":false},"sharing":{"facebook":true,"twitter":true,"google":false,"weibo":false,"instapaper":false,"vk":false,"all":["facebook","google","twitter","weibo","instapaper"]},"fontsettings":{"theme":"white","family":"sans","size":2},"theme-default":{"styles":{"website":"styles/website.css","pdf":"styles/pdf.css","epub":"styles/epub.css","mobi":"styles/mobi.css","ebook":"styles/ebook.css","print":"styles/print.css"},"showLevel":false}},"theme":"default","pdf":{"pageNumbers":true,"fontSize":12,"fontFamily":"Arial","paperSize":"a4","chapterMark":"pagebreak","pageBreaksBefore":"/","margin":{"right":62,"left":62,"top":56,"bottom":56}},"structure":{"langs":"LANGS.md","readme":"README.md","glossary":"GLOSSARY.md","summary":"SUMMARY.md"},"variables":{},"gitbook":"*"},"file":{"path":"ring.md","mtime":"2017-09-18T05:30:25.732Z","type":"markdown"},"gitbook":{"version":"3.2.3","time":"2017-09-18T05:30:51.447Z"},"basePath":".","book":{"language":""}});
|
||||
});
|
||||
</script>
|
||||
</div>
|
||||
|
|
|
|||
528
route_conflicts.html
Normal file
528
route_conflicts.html
Normal file
|
|
@ -0,0 +1,528 @@
|
|||
|
||||
<!DOCTYPE HTML>
|
||||
<html lang="" >
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta content="text/html; charset=utf-8" http-equiv="Content-Type">
|
||||
<title>Route conflicts · GitBook</title>
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
|
||||
<meta name="description" content="">
|
||||
<meta name="generator" content="GitBook 3.2.3">
|
||||
|
||||
|
||||
|
||||
|
||||
<link rel="stylesheet" href="gitbook/style.css">
|
||||
|
||||
|
||||
|
||||
|
||||
<link rel="stylesheet" href="gitbook/gitbook-plugin-highlight/website.css">
|
||||
|
||||
|
||||
|
||||
<link rel="stylesheet" href="gitbook/gitbook-plugin-search/search.css">
|
||||
|
||||
|
||||
|
||||
<link rel="stylesheet" href="gitbook/gitbook-plugin-fontsettings/website.css">
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<meta name="HandheldFriendly" content="true"/>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=no">
|
||||
<meta name="apple-mobile-web-app-capable" content="yes">
|
||||
<meta name="apple-mobile-web-app-status-bar-style" content="black">
|
||||
<link rel="apple-touch-icon-precomposed" sizes="152x152" href="gitbook/images/apple-touch-icon-precomposed-152.png">
|
||||
<link rel="shortcut icon" href="gitbook/images/favicon.ico" type="image/x-icon">
|
||||
|
||||
|
||||
<link rel="next" href="route_validation.html" />
|
||||
|
||||
|
||||
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<div class="book">
|
||||
<div class="book-summary">
|
||||
|
||||
|
||||
<div id="book-search-input" role="search">
|
||||
<input type="text" placeholder="Type to search" />
|
||||
</div>
|
||||
|
||||
|
||||
<nav role="navigation">
|
||||
|
||||
|
||||
|
||||
<ul class="summary">
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<li class="chapter " data-level="1.1" data-path="./">
|
||||
|
||||
<a href="./">
|
||||
|
||||
|
||||
Introduction
|
||||
|
||||
</a>
|
||||
|
||||
|
||||
|
||||
</li>
|
||||
|
||||
<li class="chapter " data-level="1.2" >
|
||||
|
||||
<span>
|
||||
|
||||
|
||||
Basics
|
||||
|
||||
</span>
|
||||
|
||||
|
||||
|
||||
<ul class="articles">
|
||||
|
||||
|
||||
<li class="chapter " data-level="1.2.1" data-path="basics.html">
|
||||
|
||||
<a href="basics.html#route-syntax">
|
||||
|
||||
|
||||
Route syntax
|
||||
|
||||
</a>
|
||||
|
||||
|
||||
|
||||
</li>
|
||||
|
||||
<li class="chapter " data-level="1.2.2" data-path="basics.html">
|
||||
|
||||
<a href="basics.html#router">
|
||||
|
||||
|
||||
Router
|
||||
|
||||
</a>
|
||||
|
||||
|
||||
|
||||
</li>
|
||||
|
||||
<li class="chapter " data-level="1.2.3" data-path="basics.html">
|
||||
|
||||
<a href="basics.html#path-based-routing">
|
||||
|
||||
|
||||
Path-based Routing
|
||||
|
||||
</a>
|
||||
|
||||
|
||||
|
||||
</li>
|
||||
|
||||
<li class="chapter " data-level="1.2.4" data-path="basics.html">
|
||||
|
||||
<a href="basics.html#name-based-routing">
|
||||
|
||||
|
||||
Name-based Routing
|
||||
|
||||
</a>
|
||||
|
||||
|
||||
|
||||
</li>
|
||||
|
||||
<li class="chapter " data-level="1.2.5" data-path="basics.html">
|
||||
|
||||
<a href="basics.html#route-data">
|
||||
|
||||
|
||||
Route data
|
||||
|
||||
</a>
|
||||
|
||||
|
||||
|
||||
</li>
|
||||
|
||||
<li class="chapter " data-level="1.2.6" data-path="basics.html">
|
||||
|
||||
<a href="basics.html#different-routers">
|
||||
|
||||
|
||||
Different Routers
|
||||
|
||||
</a>
|
||||
|
||||
|
||||
|
||||
</li>
|
||||
|
||||
|
||||
</ul>
|
||||
|
||||
</li>
|
||||
|
||||
<li class="chapter " data-level="1.3" >
|
||||
|
||||
<span>
|
||||
|
||||
|
||||
Advanced
|
||||
|
||||
</span>
|
||||
|
||||
|
||||
|
||||
<ul class="articles">
|
||||
|
||||
|
||||
<li class="chapter active" data-level="1.3.1" data-path="route_conflicts.html">
|
||||
|
||||
<a href="route_conflicts.html">
|
||||
|
||||
|
||||
Route conflicts
|
||||
|
||||
</a>
|
||||
|
||||
|
||||
|
||||
</li>
|
||||
|
||||
<li class="chapter " data-level="1.3.2" data-path="route_validation.html">
|
||||
|
||||
<a href="route_validation.html">
|
||||
|
||||
|
||||
Route Validation
|
||||
|
||||
</a>
|
||||
|
||||
|
||||
|
||||
</li>
|
||||
|
||||
<li class="chapter " data-level="1.3.3" data-path="configuring_routers.html">
|
||||
|
||||
<a href="configuring_routers.html">
|
||||
|
||||
|
||||
Configuring routers
|
||||
|
||||
</a>
|
||||
|
||||
|
||||
|
||||
</li>
|
||||
|
||||
|
||||
</ul>
|
||||
|
||||
</li>
|
||||
|
||||
<li class="chapter " data-level="1.4" >
|
||||
|
||||
<span>
|
||||
|
||||
|
||||
Ring
|
||||
|
||||
</span>
|
||||
|
||||
|
||||
|
||||
<ul class="articles">
|
||||
|
||||
|
||||
<li class="chapter " data-level="1.4.1" data-path="ring.html">
|
||||
|
||||
<a href="ring.html">
|
||||
|
||||
|
||||
Ring-router
|
||||
|
||||
</a>
|
||||
|
||||
|
||||
|
||||
</li>
|
||||
|
||||
<li class="chapter " data-level="1.4.2" data-path="dynamic_extensions.html">
|
||||
|
||||
<a href="dynamic_extensions.html">
|
||||
|
||||
|
||||
Dynamic extensions
|
||||
|
||||
</a>
|
||||
|
||||
|
||||
|
||||
</li>
|
||||
|
||||
<li class="chapter " data-level="1.4.3" data-path="parameter_coercion.html">
|
||||
|
||||
<a href="parameter_coercion.html">
|
||||
|
||||
|
||||
Parameter coercion
|
||||
|
||||
</a>
|
||||
|
||||
|
||||
|
||||
</li>
|
||||
|
||||
<li class="chapter " data-level="1.4.4" data-path="compiling_middleware.html">
|
||||
|
||||
<a href="compiling_middleware.html">
|
||||
|
||||
|
||||
Compiling middleware
|
||||
|
||||
</a>
|
||||
|
||||
|
||||
|
||||
</li>
|
||||
|
||||
|
||||
</ul>
|
||||
|
||||
</li>
|
||||
|
||||
<li class="chapter " data-level="1.5" >
|
||||
|
||||
<span>
|
||||
|
||||
|
||||
TODO: Swagger & OpenAPI
|
||||
|
||||
</span>
|
||||
|
||||
|
||||
|
||||
</li>
|
||||
|
||||
<li class="chapter " data-level="1.6" >
|
||||
|
||||
<span>
|
||||
|
||||
|
||||
TODO: Interceptors
|
||||
|
||||
</span>
|
||||
|
||||
|
||||
|
||||
</li>
|
||||
|
||||
|
||||
|
||||
|
||||
<li class="divider"></li>
|
||||
|
||||
<li>
|
||||
<a href="https://www.gitbook.com" target="blank" class="gitbook-link">
|
||||
Published with GitBook
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
|
||||
</nav>
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
<div class="book-body">
|
||||
|
||||
<div class="body-inner">
|
||||
|
||||
|
||||
|
||||
<div class="book-header" role="navigation">
|
||||
|
||||
|
||||
<!-- Title -->
|
||||
<h1>
|
||||
<i class="fa fa-circle-o-notch fa-spin"></i>
|
||||
<a href="." >Route conflicts</a>
|
||||
</h1>
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
|
||||
<div class="page-wrapper" tabindex="-1" role="main">
|
||||
<div class="page-inner">
|
||||
|
||||
<div id="book-search-results">
|
||||
<div class="search-noresults">
|
||||
|
||||
<section class="normal markdown-section">
|
||||
|
||||
<h1 id="route-conflicts">Route conflicts</h1>
|
||||
<p>Many routing libraries allow single path lookup could match multiple routes. Usually, first match is used. This is not good, especially if route tree is merged from multiple sources - routes might regress to be unreachable without a warning.</p>
|
||||
<p>Reitit resolves this by running explicit conflicit resolution when a <code>Router</code> is created. Conflicting routes are passed into a <code>:conflicts</code> callback. Default implementation throws <code>ex-info</code> with a descriptive message.</p>
|
||||
<p>Examples routes with conflicts:</p>
|
||||
<pre><code class="lang-clj">(<span class="hljs-name">require</span> '[reitit.core <span class="hljs-symbol">:as</span> reitit])
|
||||
|
||||
(<span class="hljs-name"><span class="hljs-builtin-name">def</span></span> routes
|
||||
[[<span class="hljs-string">"/ping"</span>]
|
||||
[<span class="hljs-string">"/:user-id/orders"</span>]
|
||||
[<span class="hljs-string">"/bulk/:bulk-id"</span>]
|
||||
[<span class="hljs-string">"/public/*path"</span>]
|
||||
[<span class="hljs-string">"/:version/status"</span>]])
|
||||
</code></pre>
|
||||
<p>By default, <code>ExceptionInfo</code> is thrown:</p>
|
||||
<pre><code class="lang-clj">(<span class="hljs-name">reitit/router</span> routes)
|
||||
<span class="hljs-comment">; CompilerException clojure.lang.ExceptionInfo: Router contains conflicting routes:</span>
|
||||
<span class="hljs-comment">;</span>
|
||||
<span class="hljs-comment">; /:user-id/orders</span>
|
||||
<span class="hljs-comment">; -> /public/*path</span>
|
||||
<span class="hljs-comment">; -> /bulk/:bulk-id</span>
|
||||
<span class="hljs-comment">;</span>
|
||||
<span class="hljs-comment">; /bulk/:bulk-id</span>
|
||||
<span class="hljs-comment">; -> /:version/status</span>
|
||||
<span class="hljs-comment">;</span>
|
||||
<span class="hljs-comment">; /public/*path</span>
|
||||
<span class="hljs-comment">; -> /:version/status</span>
|
||||
<span class="hljs-comment">;</span>
|
||||
</code></pre>
|
||||
<p>Just logging the conflicts:</p>
|
||||
<pre><code class="lang-clj">(<span class="hljs-name">reitit/router</span>
|
||||
routes
|
||||
{<span class="hljs-symbol">:conflicts</span> (<span class="hljs-name"><span class="hljs-builtin-name">comp</span></span> println reitit/conflicts-str)})
|
||||
<span class="hljs-comment">; Router contains conflicting routes:</span>
|
||||
<span class="hljs-comment">;</span>
|
||||
<span class="hljs-comment">; /:user-id/orders</span>
|
||||
<span class="hljs-comment">; -> /public/*path</span>
|
||||
<span class="hljs-comment">; -> /bulk/:bulk-id</span>
|
||||
<span class="hljs-comment">;</span>
|
||||
<span class="hljs-comment">; /bulk/:bulk-id</span>
|
||||
<span class="hljs-comment">; -> /:version/status</span>
|
||||
<span class="hljs-comment">;</span>
|
||||
<span class="hljs-comment">; /public/*path</span>
|
||||
<span class="hljs-comment">; -> /:version/status</span>
|
||||
<span class="hljs-comment">;</span>
|
||||
</code></pre>
|
||||
|
||||
|
||||
</section>
|
||||
|
||||
</div>
|
||||
<div class="search-results">
|
||||
<div class="has-results">
|
||||
|
||||
<h1 class="search-results-title"><span class='search-results-count'></span> results matching "<span class='search-query'></span>"</h1>
|
||||
<ul class="search-results-list"></ul>
|
||||
|
||||
</div>
|
||||
<div class="no-results">
|
||||
|
||||
<h1 class="search-results-title">No results matching "<span class='search-query'></span>"</h1>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
|
||||
<a href="route_validation.html" class="navigation navigation-next navigation-unique" aria-label="Next page: Route Validation">
|
||||
<i class="fa fa-angle-right"></i>
|
||||
</a>
|
||||
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
<script>
|
||||
var gitbook = gitbook || [];
|
||||
gitbook.push(function() {
|
||||
gitbook.page.hasChanged({"page":{"title":"Route conflicts","level":"1.3.1","depth":2,"next":{"title":"Route Validation","level":"1.3.2","depth":2,"path":"route_validation.md","ref":"route_validation.md","articles":[]},"previous":{"title":"Advanced","level":"1.3","depth":1,"ref":"","articles":[{"title":"Route conflicts","level":"1.3.1","depth":2,"path":"route_conflicts.md","ref":"route_conflicts.md","articles":[]},{"title":"Route Validation","level":"1.3.2","depth":2,"path":"route_validation.md","ref":"route_validation.md","articles":[]},{"title":"Configuring routers","level":"1.3.3","depth":2,"path":"configuring_routers.md","ref":"configuring_routers.md","articles":[]}]},"dir":"ltr"},"config":{"plugins":["editlink","github","highlight"],"root":"doc","styles":{"website":"styles/website.css","pdf":"styles/pdf.css","epub":"styles/epub.css","mobi":"styles/mobi.css","ebook":"styles/ebook.css","print":"styles/print.css"},"pluginsConfig":{"editlink":{"label":"Edit This Page","multilingual":false,"base":"https://github.com/metosin/reitit/tree/master/doc"},"github":{"url":"https://github.com/metosin/reitit"},"highlight":{},"search":{},"lunr":{"maxIndexSize":1000000,"ignoreSpecialCharacters":false},"sharing":{"facebook":true,"twitter":true,"google":false,"weibo":false,"instapaper":false,"vk":false,"all":["facebook","google","twitter","weibo","instapaper"]},"fontsettings":{"theme":"white","family":"sans","size":2},"theme-default":{"styles":{"website":"styles/website.css","pdf":"styles/pdf.css","epub":"styles/epub.css","mobi":"styles/mobi.css","ebook":"styles/ebook.css","print":"styles/print.css"},"showLevel":false}},"theme":"default","pdf":{"pageNumbers":true,"fontSize":12,"fontFamily":"Arial","paperSize":"a4","chapterMark":"pagebreak","pageBreaksBefore":"/","margin":{"right":62,"left":62,"top":56,"bottom":56}},"structure":{"langs":"LANGS.md","readme":"README.md","glossary":"GLOSSARY.md","summary":"SUMMARY.md"},"variables":{},"gitbook":"*"},"file":{"path":"route_conflicts.md","mtime":"2017-09-18T05:30:25.732Z","type":"markdown"},"gitbook":{"version":"3.2.3","time":"2017-09-18T05:30:51.447Z"},"basePath":".","book":{"language":""}});
|
||||
});
|
||||
</script>
|
||||
</div>
|
||||
|
||||
|
||||
<script src="gitbook/gitbook.js"></script>
|
||||
<script src="gitbook/theme.js"></script>
|
||||
|
||||
|
||||
<script src="gitbook/gitbook-plugin-editlink/plugin.js"></script>
|
||||
|
||||
|
||||
|
||||
<script src="gitbook/gitbook-plugin-github/plugin.js"></script>
|
||||
|
||||
|
||||
|
||||
<script src="gitbook/gitbook-plugin-search/search-engine.js"></script>
|
||||
|
||||
|
||||
|
||||
<script src="gitbook/gitbook-plugin-search/search.js"></script>
|
||||
|
||||
|
||||
|
||||
<script src="gitbook/gitbook-plugin-lunr/lunr.min.js"></script>
|
||||
|
||||
|
||||
|
||||
<script src="gitbook/gitbook-plugin-lunr/search-lunr.js"></script>
|
||||
|
||||
|
||||
|
||||
<script src="gitbook/gitbook-plugin-sharing/buttons.js"></script>
|
||||
|
||||
|
||||
|
||||
<script src="gitbook/gitbook-plugin-fontsettings/fontsettings.js"></script>
|
||||
|
||||
|
||||
|
||||
</body>
|
||||
</html>
|
||||
|
||||
644
route_validation.html
Normal file
644
route_validation.html
Normal file
|
|
@ -0,0 +1,644 @@
|
|||
|
||||
<!DOCTYPE HTML>
|
||||
<html lang="" >
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta content="text/html; charset=utf-8" http-equiv="Content-Type">
|
||||
<title>Route Validation · GitBook</title>
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
|
||||
<meta name="description" content="">
|
||||
<meta name="generator" content="GitBook 3.2.3">
|
||||
|
||||
|
||||
|
||||
|
||||
<link rel="stylesheet" href="gitbook/style.css">
|
||||
|
||||
|
||||
|
||||
|
||||
<link rel="stylesheet" href="gitbook/gitbook-plugin-highlight/website.css">
|
||||
|
||||
|
||||
|
||||
<link rel="stylesheet" href="gitbook/gitbook-plugin-search/search.css">
|
||||
|
||||
|
||||
|
||||
<link rel="stylesheet" href="gitbook/gitbook-plugin-fontsettings/website.css">
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<meta name="HandheldFriendly" content="true"/>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=no">
|
||||
<meta name="apple-mobile-web-app-capable" content="yes">
|
||||
<meta name="apple-mobile-web-app-status-bar-style" content="black">
|
||||
<link rel="apple-touch-icon-precomposed" sizes="152x152" href="gitbook/images/apple-touch-icon-precomposed-152.png">
|
||||
<link rel="shortcut icon" href="gitbook/images/favicon.ico" type="image/x-icon">
|
||||
|
||||
|
||||
<link rel="next" href="configuring_routers.html" />
|
||||
|
||||
|
||||
<link rel="prev" href="route_conflicts.html" />
|
||||
|
||||
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<div class="book">
|
||||
<div class="book-summary">
|
||||
|
||||
|
||||
<div id="book-search-input" role="search">
|
||||
<input type="text" placeholder="Type to search" />
|
||||
</div>
|
||||
|
||||
|
||||
<nav role="navigation">
|
||||
|
||||
|
||||
|
||||
<ul class="summary">
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<li class="chapter " data-level="1.1" data-path="./">
|
||||
|
||||
<a href="./">
|
||||
|
||||
|
||||
Introduction
|
||||
|
||||
</a>
|
||||
|
||||
|
||||
|
||||
</li>
|
||||
|
||||
<li class="chapter " data-level="1.2" >
|
||||
|
||||
<span>
|
||||
|
||||
|
||||
Basics
|
||||
|
||||
</span>
|
||||
|
||||
|
||||
|
||||
<ul class="articles">
|
||||
|
||||
|
||||
<li class="chapter " data-level="1.2.1" data-path="basics.html">
|
||||
|
||||
<a href="basics.html#route-syntax">
|
||||
|
||||
|
||||
Route syntax
|
||||
|
||||
</a>
|
||||
|
||||
|
||||
|
||||
</li>
|
||||
|
||||
<li class="chapter " data-level="1.2.2" data-path="basics.html">
|
||||
|
||||
<a href="basics.html#router">
|
||||
|
||||
|
||||
Router
|
||||
|
||||
</a>
|
||||
|
||||
|
||||
|
||||
</li>
|
||||
|
||||
<li class="chapter " data-level="1.2.3" data-path="basics.html">
|
||||
|
||||
<a href="basics.html#path-based-routing">
|
||||
|
||||
|
||||
Path-based Routing
|
||||
|
||||
</a>
|
||||
|
||||
|
||||
|
||||
</li>
|
||||
|
||||
<li class="chapter " data-level="1.2.4" data-path="basics.html">
|
||||
|
||||
<a href="basics.html#name-based-routing">
|
||||
|
||||
|
||||
Name-based Routing
|
||||
|
||||
</a>
|
||||
|
||||
|
||||
|
||||
</li>
|
||||
|
||||
<li class="chapter " data-level="1.2.5" data-path="basics.html">
|
||||
|
||||
<a href="basics.html#route-data">
|
||||
|
||||
|
||||
Route data
|
||||
|
||||
</a>
|
||||
|
||||
|
||||
|
||||
</li>
|
||||
|
||||
<li class="chapter " data-level="1.2.6" data-path="basics.html">
|
||||
|
||||
<a href="basics.html#different-routers">
|
||||
|
||||
|
||||
Different Routers
|
||||
|
||||
</a>
|
||||
|
||||
|
||||
|
||||
</li>
|
||||
|
||||
|
||||
</ul>
|
||||
|
||||
</li>
|
||||
|
||||
<li class="chapter " data-level="1.3" >
|
||||
|
||||
<span>
|
||||
|
||||
|
||||
Advanced
|
||||
|
||||
</span>
|
||||
|
||||
|
||||
|
||||
<ul class="articles">
|
||||
|
||||
|
||||
<li class="chapter " data-level="1.3.1" data-path="route_conflicts.html">
|
||||
|
||||
<a href="route_conflicts.html">
|
||||
|
||||
|
||||
Route conflicts
|
||||
|
||||
</a>
|
||||
|
||||
|
||||
|
||||
</li>
|
||||
|
||||
<li class="chapter active" data-level="1.3.2" data-path="route_validation.html">
|
||||
|
||||
<a href="route_validation.html">
|
||||
|
||||
|
||||
Route Validation
|
||||
|
||||
</a>
|
||||
|
||||
|
||||
|
||||
</li>
|
||||
|
||||
<li class="chapter " data-level="1.3.3" data-path="configuring_routers.html">
|
||||
|
||||
<a href="configuring_routers.html">
|
||||
|
||||
|
||||
Configuring routers
|
||||
|
||||
</a>
|
||||
|
||||
|
||||
|
||||
</li>
|
||||
|
||||
|
||||
</ul>
|
||||
|
||||
</li>
|
||||
|
||||
<li class="chapter " data-level="1.4" >
|
||||
|
||||
<span>
|
||||
|
||||
|
||||
Ring
|
||||
|
||||
</span>
|
||||
|
||||
|
||||
|
||||
<ul class="articles">
|
||||
|
||||
|
||||
<li class="chapter " data-level="1.4.1" data-path="ring.html">
|
||||
|
||||
<a href="ring.html">
|
||||
|
||||
|
||||
Ring-router
|
||||
|
||||
</a>
|
||||
|
||||
|
||||
|
||||
</li>
|
||||
|
||||
<li class="chapter " data-level="1.4.2" data-path="dynamic_extensions.html">
|
||||
|
||||
<a href="dynamic_extensions.html">
|
||||
|
||||
|
||||
Dynamic extensions
|
||||
|
||||
</a>
|
||||
|
||||
|
||||
|
||||
</li>
|
||||
|
||||
<li class="chapter " data-level="1.4.3" data-path="parameter_coercion.html">
|
||||
|
||||
<a href="parameter_coercion.html">
|
||||
|
||||
|
||||
Parameter coercion
|
||||
|
||||
</a>
|
||||
|
||||
|
||||
|
||||
</li>
|
||||
|
||||
<li class="chapter " data-level="1.4.4" data-path="compiling_middleware.html">
|
||||
|
||||
<a href="compiling_middleware.html">
|
||||
|
||||
|
||||
Compiling middleware
|
||||
|
||||
</a>
|
||||
|
||||
|
||||
|
||||
</li>
|
||||
|
||||
|
||||
</ul>
|
||||
|
||||
</li>
|
||||
|
||||
<li class="chapter " data-level="1.5" >
|
||||
|
||||
<span>
|
||||
|
||||
|
||||
TODO: Swagger & OpenAPI
|
||||
|
||||
</span>
|
||||
|
||||
|
||||
|
||||
</li>
|
||||
|
||||
<li class="chapter " data-level="1.6" >
|
||||
|
||||
<span>
|
||||
|
||||
|
||||
TODO: Interceptors
|
||||
|
||||
</span>
|
||||
|
||||
|
||||
|
||||
</li>
|
||||
|
||||
|
||||
|
||||
|
||||
<li class="divider"></li>
|
||||
|
||||
<li>
|
||||
<a href="https://www.gitbook.com" target="blank" class="gitbook-link">
|
||||
Published with GitBook
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
|
||||
</nav>
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
<div class="book-body">
|
||||
|
||||
<div class="body-inner">
|
||||
|
||||
|
||||
|
||||
<div class="book-header" role="navigation">
|
||||
|
||||
|
||||
<!-- Title -->
|
||||
<h1>
|
||||
<i class="fa fa-circle-o-notch fa-spin"></i>
|
||||
<a href="." >Route Validation</a>
|
||||
</h1>
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
|
||||
<div class="page-wrapper" tabindex="-1" role="main">
|
||||
<div class="page-inner">
|
||||
|
||||
<div id="book-search-results">
|
||||
<div class="search-noresults">
|
||||
|
||||
<section class="normal markdown-section">
|
||||
|
||||
<h1 id="route-validation">Route validation</h1>
|
||||
<p>Namespace <code>reitit.spec</code> contains <a href="https://clojure.org/about/spec" target="_blank">clojure.spec</a> definitions for raw-routes, routes, router and router options.</p>
|
||||
<p><strong>NOTE:</strong> Use of specs requires to use one of the following:</p>
|
||||
<ul>
|
||||
<li><code>[org.clojure/clojurescript "1.9.660"]</code></li>
|
||||
<li><code>[org.clojure/clojure "1.9.0-alpha19"]</code></li>
|
||||
<li><code>[clojure-future-spec "1.9.0-alpha17"]</code> (Clojure 1.8)</li>
|
||||
</ul>
|
||||
<h2 id="at-runtime">At runtime</h2>
|
||||
<p>If route trees are generated at runtime (e.g. from external source like the database), one can use directly the <code>clojure.spec</code> functions.</p>
|
||||
<pre><code class="lang-clj">(<span class="hljs-name">require</span> '[clojure.spec.alpha <span class="hljs-symbol">:as</span> s])
|
||||
(<span class="hljs-name">require</span> '[reitit.spec <span class="hljs-symbol">:as</span> spec])
|
||||
|
||||
(<span class="hljs-name"><span class="hljs-builtin-name">def</span></span> routes-from-db
|
||||
[<span class="hljs-string">"tenant1"</span> <span class="hljs-symbol">::tenant1</span>])
|
||||
|
||||
(<span class="hljs-name">s/valid?</span> <span class="hljs-symbol">::spec/raw-routes</span> routes-from-db)
|
||||
<span class="hljs-comment">; false</span>
|
||||
|
||||
(<span class="hljs-name">s/explain</span> <span class="hljs-symbol">::spec/raw-routes</span> routes-from-db)
|
||||
<span class="hljs-comment">; In: [0] val: "tenant1" fails spec: :reitit.spec/path at: [:route :path] predicate: (or (blank? %) (starts-with? % "/"))</span>
|
||||
<span class="hljs-comment">; In: [0] val: "tenant1" fails spec: :reitit.spec/raw-route at: [:routes] predicate: (cat :path :reitit.spec/path :arg (? :reitit.spec/arg) :childs (* (and (nilable :reitit.spec/raw-route))))</span>
|
||||
<span class="hljs-comment">; In: [1] val: :user/tenant1 fails spec: :reitit.spec/raw-route at: [:routes] predicate: (cat :path :reitit.spec/path :arg (? :reitit.spec/arg) :childs (* (and (nilable :reitit.spec/raw-route))))</span>
|
||||
<span class="hljs-comment">; :clojure.spec.alpha/spec :reitit.spec/raw-routes</span>
|
||||
<span class="hljs-comment">; :clojure.spec.alpha/value ["tenant1" :user/tenant1]</span>
|
||||
</code></pre>
|
||||
<h2 id="at-development-time">At development time</h2>
|
||||
<p><code>reitit.core/router</code> can be instrumented and use something like <a href="https://github.com/bhb/expound" target="_blank">expound</a> to pretty-print the spec problems.</p>
|
||||
<p>First add a <code>:dev</code> dependency to:</p>
|
||||
<pre><code class="lang-clj">[expound <span class="hljs-string">"0.3.0"</span>]
|
||||
</code></pre>
|
||||
<p>Some bootstrapping:</p>
|
||||
<pre><code class="lang-clj">(<span class="hljs-name">require</span> '[clojure.spec.test.alpha <span class="hljs-symbol">:as</span> stest])
|
||||
(<span class="hljs-name">require</span> '[expound.alpha <span class="hljs-symbol">:as</span> expound])
|
||||
(<span class="hljs-name">require</span> '[clojure.spec.alpha <span class="hljs-symbol">:as</span> s])
|
||||
(<span class="hljs-name">require</span> '[reitit.spec])
|
||||
|
||||
(<span class="hljs-name">stest/instrument</span> `reitit/router)
|
||||
(<span class="hljs-name"><span class="hljs-builtin-name">set!</span></span> s/*explain-out* expound/printer)
|
||||
</code></pre>
|
||||
<p>And we are ready to go:</p>
|
||||
<pre><code class="lang-clj">
|
||||
(<span class="hljs-name">reitit/router</span>
|
||||
[<span class="hljs-string">"/api"</span>
|
||||
[<span class="hljs-string">"/public"</span>
|
||||
[<span class="hljs-string">"/ping"</span>]
|
||||
[<span class="hljs-string">"pong"</span>]]])
|
||||
|
||||
<span class="hljs-comment">; CompilerException clojure.lang.ExceptionInfo: Call to #'reitit.core/router did not conform to spec:</span>
|
||||
<span class="hljs-comment">;</span>
|
||||
<span class="hljs-comment">; -- Spec failed --------------------</span>
|
||||
<span class="hljs-comment">;</span>
|
||||
<span class="hljs-comment">; Function arguments</span>
|
||||
<span class="hljs-comment">;</span>
|
||||
<span class="hljs-comment">; (["/api" ...])</span>
|
||||
<span class="hljs-comment">; ^^^^^^</span>
|
||||
<span class="hljs-comment">;</span>
|
||||
<span class="hljs-comment">; should satisfy</span>
|
||||
<span class="hljs-comment">;</span>
|
||||
<span class="hljs-comment">; (clojure.spec.alpha/cat</span>
|
||||
<span class="hljs-comment">; :path</span>
|
||||
<span class="hljs-comment">; :reitit.spec/path</span>
|
||||
<span class="hljs-comment">; :arg</span>
|
||||
<span class="hljs-comment">; (clojure.spec.alpha/? :reitit.spec/arg)</span>
|
||||
<span class="hljs-comment">; :childs</span>
|
||||
<span class="hljs-comment">; (clojure.spec.alpha/*</span>
|
||||
<span class="hljs-comment">; (clojure.spec.alpha/and</span>
|
||||
<span class="hljs-comment">; (clojure.spec.alpha/nilable :reitit.spec/raw-route))))</span>
|
||||
<span class="hljs-comment">;</span>
|
||||
<span class="hljs-comment">; or</span>
|
||||
<span class="hljs-comment">;</span>
|
||||
<span class="hljs-comment">; (clojure.spec.alpha/cat</span>
|
||||
<span class="hljs-comment">; :path</span>
|
||||
<span class="hljs-comment">; :reitit.spec/path</span>
|
||||
<span class="hljs-comment">; :arg</span>
|
||||
<span class="hljs-comment">; (clojure.spec.alpha/? :reitit.spec/arg)</span>
|
||||
<span class="hljs-comment">; :childs</span>
|
||||
<span class="hljs-comment">; (clojure.spec.alpha/*</span>
|
||||
<span class="hljs-comment">; (clojure.spec.alpha/and</span>
|
||||
<span class="hljs-comment">; (clojure.spec.alpha/nilable :reitit.spec/raw-route))))</span>
|
||||
<span class="hljs-comment">;</span>
|
||||
<span class="hljs-comment">; -- Relevant specs -------</span>
|
||||
<span class="hljs-comment">;</span>
|
||||
<span class="hljs-comment">; :reitit.spec/raw-route:</span>
|
||||
<span class="hljs-comment">; (clojure.spec.alpha/cat</span>
|
||||
<span class="hljs-comment">; :path</span>
|
||||
<span class="hljs-comment">; :reitit.spec/path</span>
|
||||
<span class="hljs-comment">; :arg</span>
|
||||
<span class="hljs-comment">; (clojure.spec.alpha/? :reitit.spec/arg)</span>
|
||||
<span class="hljs-comment">; :childs</span>
|
||||
<span class="hljs-comment">; (clojure.spec.alpha/*</span>
|
||||
<span class="hljs-comment">; (clojure.spec.alpha/and</span>
|
||||
<span class="hljs-comment">; (clojure.spec.alpha/nilable :reitit.spec/raw-route))))</span>
|
||||
<span class="hljs-comment">; :reitit.spec/raw-routes:</span>
|
||||
<span class="hljs-comment">; (clojure.spec.alpha/or</span>
|
||||
<span class="hljs-comment">; :route</span>
|
||||
<span class="hljs-comment">; :reitit.spec/raw-route</span>
|
||||
<span class="hljs-comment">; :routes</span>
|
||||
<span class="hljs-comment">; (clojure.spec.alpha/coll-of :reitit.spec/raw-route :into []))</span>
|
||||
<span class="hljs-comment">;</span>
|
||||
<span class="hljs-comment">; -- Spec failed --------------------</span>
|
||||
<span class="hljs-comment">;</span>
|
||||
<span class="hljs-comment">; Function arguments</span>
|
||||
<span class="hljs-comment">;</span>
|
||||
<span class="hljs-comment">; ([... [... ... ["pong"]]])</span>
|
||||
<span class="hljs-comment">; ^^^^^^</span>
|
||||
<span class="hljs-comment">;</span>
|
||||
<span class="hljs-comment">; should satisfy</span>
|
||||
<span class="hljs-comment">;</span>
|
||||
<span class="hljs-comment">; (fn</span>
|
||||
<span class="hljs-comment">; [%]</span>
|
||||
<span class="hljs-comment">; (or</span>
|
||||
<span class="hljs-comment">; (clojure.string/blank? %)</span>
|
||||
<span class="hljs-comment">; (clojure.string/starts-with? % "/")))</span>
|
||||
<span class="hljs-comment">;</span>
|
||||
<span class="hljs-comment">; or</span>
|
||||
<span class="hljs-comment">;</span>
|
||||
<span class="hljs-comment">; (fn</span>
|
||||
<span class="hljs-comment">; [%]</span>
|
||||
<span class="hljs-comment">; (or</span>
|
||||
<span class="hljs-comment">; (clojure.string/blank? %)</span>
|
||||
<span class="hljs-comment">; (clojure.string/starts-with? % "/")))</span>
|
||||
<span class="hljs-comment">;</span>
|
||||
<span class="hljs-comment">; -- Relevant specs -------</span>
|
||||
<span class="hljs-comment">;</span>
|
||||
<span class="hljs-comment">; :reitit.spec/path:</span>
|
||||
<span class="hljs-comment">; (clojure.spec.alpha/and</span>
|
||||
<span class="hljs-comment">; clojure.core/string?</span>
|
||||
<span class="hljs-comment">; (clojure.core/fn</span>
|
||||
<span class="hljs-comment">; [%]</span>
|
||||
<span class="hljs-comment">; (clojure.core/or</span>
|
||||
<span class="hljs-comment">; (clojure.string/blank? %)</span>
|
||||
<span class="hljs-comment">; (clojure.string/starts-with? % "/"))))</span>
|
||||
<span class="hljs-comment">; :reitit.spec/raw-route:</span>
|
||||
<span class="hljs-comment">; (clojure.spec.alpha/cat</span>
|
||||
<span class="hljs-comment">; :path</span>
|
||||
<span class="hljs-comment">; :reitit.spec/path</span>
|
||||
<span class="hljs-comment">; :arg</span>
|
||||
<span class="hljs-comment">; (clojure.spec.alpha/? :reitit.spec/arg)</span>
|
||||
<span class="hljs-comment">; :childs</span>
|
||||
<span class="hljs-comment">; (clojure.spec.alpha/*</span>
|
||||
<span class="hljs-comment">; (clojure.spec.alpha/and</span>
|
||||
<span class="hljs-comment">; (clojure.spec.alpha/nilable :reitit.spec/raw-route))))</span>
|
||||
<span class="hljs-comment">; :reitit.spec/raw-routes:</span>
|
||||
<span class="hljs-comment">; (clojure.spec.alpha/or</span>
|
||||
<span class="hljs-comment">; :route</span>
|
||||
<span class="hljs-comment">; :reitit.spec/raw-route</span>
|
||||
<span class="hljs-comment">; :routes</span>
|
||||
<span class="hljs-comment">; (clojure.spec.alpha/coll-of :reitit.spec/raw-route :into []))</span>
|
||||
<span class="hljs-comment">;</span>
|
||||
<span class="hljs-comment">; -------------------------</span>
|
||||
<span class="hljs-comment">; Detected 2 errors</span>
|
||||
</code></pre>
|
||||
<h1 id="validating-route-data">Validating route data</h1>
|
||||
<p><em>TODO</em></p>
|
||||
|
||||
|
||||
</section>
|
||||
|
||||
</div>
|
||||
<div class="search-results">
|
||||
<div class="has-results">
|
||||
|
||||
<h1 class="search-results-title"><span class='search-results-count'></span> results matching "<span class='search-query'></span>"</h1>
|
||||
<ul class="search-results-list"></ul>
|
||||
|
||||
</div>
|
||||
<div class="no-results">
|
||||
|
||||
<h1 class="search-results-title">No results matching "<span class='search-query'></span>"</h1>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
<a href="route_conflicts.html" class="navigation navigation-prev " aria-label="Previous page: Route conflicts">
|
||||
<i class="fa fa-angle-left"></i>
|
||||
</a>
|
||||
|
||||
|
||||
<a href="configuring_routers.html" class="navigation navigation-next " aria-label="Next page: Configuring routers">
|
||||
<i class="fa fa-angle-right"></i>
|
||||
</a>
|
||||
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
<script>
|
||||
var gitbook = gitbook || [];
|
||||
gitbook.push(function() {
|
||||
gitbook.page.hasChanged({"page":{"title":"Route Validation","level":"1.3.2","depth":2,"next":{"title":"Configuring routers","level":"1.3.3","depth":2,"path":"configuring_routers.md","ref":"configuring_routers.md","articles":[]},"previous":{"title":"Route conflicts","level":"1.3.1","depth":2,"path":"route_conflicts.md","ref":"route_conflicts.md","articles":[]},"dir":"ltr"},"config":{"plugins":["editlink","github","highlight"],"root":"doc","styles":{"website":"styles/website.css","pdf":"styles/pdf.css","epub":"styles/epub.css","mobi":"styles/mobi.css","ebook":"styles/ebook.css","print":"styles/print.css"},"pluginsConfig":{"editlink":{"label":"Edit This Page","multilingual":false,"base":"https://github.com/metosin/reitit/tree/master/doc"},"github":{"url":"https://github.com/metosin/reitit"},"highlight":{},"search":{},"lunr":{"maxIndexSize":1000000,"ignoreSpecialCharacters":false},"sharing":{"facebook":true,"twitter":true,"google":false,"weibo":false,"instapaper":false,"vk":false,"all":["facebook","google","twitter","weibo","instapaper"]},"fontsettings":{"theme":"white","family":"sans","size":2},"theme-default":{"styles":{"website":"styles/website.css","pdf":"styles/pdf.css","epub":"styles/epub.css","mobi":"styles/mobi.css","ebook":"styles/ebook.css","print":"styles/print.css"},"showLevel":false}},"theme":"default","pdf":{"pageNumbers":true,"fontSize":12,"fontFamily":"Arial","paperSize":"a4","chapterMark":"pagebreak","pageBreaksBefore":"/","margin":{"right":62,"left":62,"top":56,"bottom":56}},"structure":{"langs":"LANGS.md","readme":"README.md","glossary":"GLOSSARY.md","summary":"SUMMARY.md"},"variables":{},"gitbook":"*"},"file":{"path":"route_validation.md","mtime":"2017-09-18T05:30:25.732Z","type":"markdown"},"gitbook":{"version":"3.2.3","time":"2017-09-18T05:30:51.447Z"},"basePath":".","book":{"language":""}});
|
||||
});
|
||||
</script>
|
||||
</div>
|
||||
|
||||
|
||||
<script src="gitbook/gitbook.js"></script>
|
||||
<script src="gitbook/theme.js"></script>
|
||||
|
||||
|
||||
<script src="gitbook/gitbook-plugin-editlink/plugin.js"></script>
|
||||
|
||||
|
||||
|
||||
<script src="gitbook/gitbook-plugin-github/plugin.js"></script>
|
||||
|
||||
|
||||
|
||||
<script src="gitbook/gitbook-plugin-search/search-engine.js"></script>
|
||||
|
||||
|
||||
|
||||
<script src="gitbook/gitbook-plugin-search/search.js"></script>
|
||||
|
||||
|
||||
|
||||
<script src="gitbook/gitbook-plugin-lunr/lunr.min.js"></script>
|
||||
|
||||
|
||||
|
||||
<script src="gitbook/gitbook-plugin-lunr/search-lunr.js"></script>
|
||||
|
||||
|
||||
|
||||
<script src="gitbook/gitbook-plugin-sharing/buttons.js"></script>
|
||||
|
||||
|
||||
|
||||
<script src="gitbook/gitbook-plugin-fontsettings/fontsettings.js"></script>
|
||||
|
||||
|
||||
|
||||
</body>
|
||||
</html>
|
||||
|
||||
File diff suppressed because one or more lines are too long
Loading…
Reference in a new issue