mirror of
https://github.com/metosin/reitit.git
synced 2025-12-16 16:01:11 +00:00
better docs
This commit is contained in:
parent
cef7de58d3
commit
7b3aa5e631
7 changed files with 106 additions and 94 deletions
|
|
@ -27,6 +27,7 @@
|
|||
* [Static Resources](ring/static.md)
|
||||
* [Dynamic Extensions](ring/dynamic_extensions.md)
|
||||
* [Data-driven Middleware](ring/data_driven_middleware.md)
|
||||
* [Transformations Middleware Chain](ring/transformating_middleware_chain.md)
|
||||
* [Middleware Registry](ring/middleware_registry.md)
|
||||
* [Default Middleware](ring/default_middleware.md)
|
||||
* [Pluggable Coercion](ring/coercion.md)
|
||||
|
|
|
|||
Binary file not shown.
|
Before Width: | Height: | Size: 203 KiB After Width: | Height: | Size: 228 KiB |
|
|
@ -6,6 +6,7 @@
|
|||
* [Static Resources](static.md)
|
||||
* [Dynamic Extensions](dynamic_extensions.md)
|
||||
* [Data-driven Middleware](data_driven_middleware.md)
|
||||
* [Transformations Middleware Chain](transformating_middleware_chain.md)
|
||||
* [Middleware Registry](middleware_registry.md)
|
||||
* [Default Middleware](default_middleware.md)
|
||||
* [Pluggable Coercion](coercion.md)
|
||||
|
|
|
|||
|
|
@ -88,49 +88,8 @@ All the middleware are applied correctly:
|
|||
|
||||
Middleware can be optimized against an endpoint using [middleware compilation](compiling_middleware.md).
|
||||
|
||||
## Transforming the middleware chain
|
||||
|
||||
There is an extra option in ring-router (actually, in the undelaying middleware-router): `:reitit.middleware/transform` to transform the middleware chain per endpoint. It sees the vector of compiled middleware and should return a new vector of middleware.
|
||||
|
||||
#### Adding debug middleware between all other middleware
|
||||
|
||||
```clj
|
||||
(def app
|
||||
(ring/ring-handler
|
||||
(ring/router
|
||||
["/api" {:middleware [[wrap 1] [wrap2 2]]}
|
||||
["/ping" {:get {:middleware [[wrap3 3]]
|
||||
:handler handler}}]]
|
||||
{::middleware/transform #(interleave % (repeat [wrap :debug]))})))
|
||||
```
|
||||
|
||||
```clj
|
||||
(app {:request-method :get, :uri "/api/ping"})
|
||||
; {:status 200, :body [1 :debug 2 :debug 3 :debug :handler]}
|
||||
```
|
||||
|
||||
#### Reversing the middleware chain
|
||||
|
||||
```clj
|
||||
(def app
|
||||
(ring/ring-handler
|
||||
(ring/router
|
||||
["/api" {:middleware [[wrap 1] [wrap2 2]]}
|
||||
["/ping" {:get {:middleware [[wrap3 3]]
|
||||
:handler handler}}]]
|
||||
{::middleware/transform reverse)})))
|
||||
```
|
||||
|
||||
```clj
|
||||
(app {:request-method :get, :uri "/api/ping"})
|
||||
; {:status 200, :body [3 2 1 :handler]}
|
||||
```
|
||||
|
||||
## Ideas for the future
|
||||
|
||||
* Re-package all useful middleware into (optimized) data-driven Middleware
|
||||
* just package or a new community-repo with rehosting stuff?
|
||||
* Support `Keyword` expansion into Middleware, enabling external Middleware Registries (duct/integrant/macchiato -style)
|
||||
* Support Middleware dependency resolution with new keys `:requires` and `:provides`. Values are set of top-level keys of the request. e.g.
|
||||
* `InjectUserIntoRequestMiddleware` requires `#{:session}` and provides `#{:user}`
|
||||
* `AuthorizationMiddleware` requires `#{:user}`
|
||||
|
|
|
|||
|
|
@ -108,80 +108,95 @@ Swagger-ui:
|
|||
|
||||
### More complete example
|
||||
|
||||
* `clojure.spec` and `Schema` coercion
|
||||
* swagger data (`:tags`, `:produces`, `:consumes`)
|
||||
* swagger-spec served from `"/api/swagger.json"`
|
||||
* `clojure.spec` coercion
|
||||
* swagger data (`:tags`, `:produces`, `:summary`)
|
||||
* swagger-spec served from `"/swagger.json"`
|
||||
* swagger-ui mounted to `"/"`
|
||||
* [Muuntaja](https://github.com/metosin/muuntaja) for request & response formatting
|
||||
* `wrap-params` to capture query & path parameters
|
||||
* set of middleware for content negotiation, exceptions, multipart etc.
|
||||
* missed routes are handled by `create-default-handler`
|
||||
* served via [ring-jetty](https://github.com/ring-clojure/ring/tree/master/ring-jetty-adapter)
|
||||
|
||||
Whole example project is in [`/examples/ring-swagger`](https://github.com/metosin/reitit/tree/master/examples/ring-swagger).
|
||||
|
||||
```clj
|
||||
(require '[reitit.ring :as ring]
|
||||
(require '[reitit.swagger :as swagger]
|
||||
(require '[reitit.swagger-ui :as swagger-ui]
|
||||
;; coercion
|
||||
(require '[reitit.ring.coercion :as rrc]
|
||||
(require '[reitit.coercion.spec :as spec]
|
||||
(require '[reitit.coercion.schema :as schema]
|
||||
(require '[schema.core :refer [Int]]
|
||||
;; web server
|
||||
(require '[ring.adapter.jetty :as jetty]
|
||||
(require '[ring.middleware.params]
|
||||
(require '[muuntaja.middleware]))
|
||||
(ns example.server
|
||||
(:require [reitit.ring :as ring]
|
||||
[reitit.swagger :as swagger]
|
||||
[reitit.swagger-ui :as swagger-ui]
|
||||
[reitit.ring.coercion :as coercion]
|
||||
[reitit.coercion.spec]
|
||||
[reitit.ring.middleware.muuntaja :as muuntaja]
|
||||
[reitit.ring.middleware.exception :as exception]
|
||||
[reitit.ring.middleware.multipart :as multipart]
|
||||
[ring.middleware.params :as params]
|
||||
[ring.adapter.jetty :as jetty]
|
||||
[muuntaja.core :as m]
|
||||
[clojure.java.io :as io]))
|
||||
|
||||
(def app
|
||||
(ring/ring-handler
|
||||
(ring/router
|
||||
["/api"
|
||||
|
||||
["/swagger.json"
|
||||
[["/swagger.json"
|
||||
{:get {:no-doc true
|
||||
:swagger {:info {:title "my-api"}}
|
||||
:handler (swagger/create-swagger-handler)}}]
|
||||
|
||||
["/spec"
|
||||
{:coercion spec/coercion
|
||||
:swagger {:tags ["spec"]}}
|
||||
["/files"
|
||||
{:swagger {:tags ["files"]}}
|
||||
|
||||
["/upload"
|
||||
{:post {:summary "upload a file"
|
||||
:parameters {:multipart {:file multipart/temp-file-part}}
|
||||
:responses {200 {:body {:file multipart/temp-file-part}}}
|
||||
:handler (fn [{{{:keys [file]} :multipart} :parameters}]
|
||||
{:status 200
|
||||
:body {:file file}})}}]
|
||||
|
||||
["/download"
|
||||
{:get {:summary "downloads a file"
|
||||
:swagger {:produces ["image/png"]}
|
||||
:handler (fn [_]
|
||||
{:status 200
|
||||
:headers {"Content-Type" "image/png"}
|
||||
:body (io/input-stream (io/resource "reitit.png"))})}}]]
|
||||
|
||||
["/math"
|
||||
{:swagger {:tags ["math"]}}
|
||||
|
||||
["/plus"
|
||||
{:get {:summary "plus with spec"
|
||||
{:get {:summary "plus with spec query parameters"
|
||||
:parameters {:query {:x int?, :y int?}}
|
||||
:responses {200 {:body {:total int?}}}
|
||||
:handler (fn [{{{:keys [x y]} :query} :parameters}]
|
||||
{:status 200
|
||||
:body {:total (+ x y)}})}}]]
|
||||
:body {:total (+ x y)}})}
|
||||
:post {:summary "plus with spec body parameters"
|
||||
:parameters {:body {:x int?, :y int?}}
|
||||
:responses {200 {:body {:total int?}}}
|
||||
:handler (fn [{{{:keys [x y]} :body} :parameters}]
|
||||
{:status 200
|
||||
:body {:total (+ x y)}})}}]]]
|
||||
|
||||
["/schema"
|
||||
{:coercion schema/coercion
|
||||
:swagger {:tags ["schema"]}}
|
||||
|
||||
["/plus"
|
||||
{:get {:summary "plus with schema"
|
||||
:parameters {:query {:x Int, :y Int}}
|
||||
:responses {200 {:body {:total Int}}}
|
||||
:handler (fn [{{{:keys [x y]} :query} :parameters}]
|
||||
{:status 200
|
||||
:body {:total (+ x y)}})}}]]]
|
||||
|
||||
{:data {:middleware [ring.middleware.params/wrap-params
|
||||
muuntaja.middleware/wrap-format
|
||||
swagger/swagger-feature
|
||||
rrc/coerce-exceptions-middleware
|
||||
rrc/coerce-request-middleware
|
||||
rrc/coerce-response-middleware]
|
||||
:swagger {:produces #{"application/json"
|
||||
"application/edn"
|
||||
"application/transit+json"}
|
||||
:consumes #{"application/json"
|
||||
"application/edn"
|
||||
"application/transit+json"}}}})
|
||||
{:data {:coercion reitit.coercion.spec/coercion
|
||||
:muuntaja m/instance
|
||||
:middleware [;; query-params & form-params
|
||||
params/wrap-params
|
||||
;; content-negotiation
|
||||
muuntaja/format-negotiate-middleware
|
||||
;; encoding response body
|
||||
muuntaja/format-response-middleware
|
||||
;; exception handling
|
||||
exception/exception-middleware
|
||||
;; decoding request body
|
||||
muuntaja/format-request-middleware
|
||||
;; coercing response bodys
|
||||
coercion/coerce-response-middleware
|
||||
;; coercing request parameters
|
||||
coercion/coerce-request-middleware
|
||||
;; multipart
|
||||
multipart/multipart-middleware]}})
|
||||
(ring/routes
|
||||
(swagger-ui/create-swagger-ui-handler
|
||||
{:path "/", :url "/api/swagger.json"})
|
||||
(swagger-ui/create-swagger-ui-handler {:path "/"})
|
||||
(ring/create-default-handler))))
|
||||
|
||||
(defn start []
|
||||
|
|
@ -242,7 +257,6 @@ Example with:
|
|||
|
||||
### TODO
|
||||
|
||||
* create a data-driven version of [Muuntaja](https://github.com/metosin/muuntaja) that integrates into `:produces` and `:consumes`
|
||||
* ClojureScript
|
||||
* example for [Macchiato](https://github.com/macchiato-framework)
|
||||
* body formatting
|
||||
|
|
|
|||
37
doc/ring/transforming_middleware_chain.md
Normal file
37
doc/ring/transforming_middleware_chain.md
Normal file
|
|
@ -0,0 +1,37 @@
|
|||
# Transformation Middleware Chain
|
||||
|
||||
There is an extra option in ring-router (actually, in the underlying middleware-router): `:reitit.middleware/transform` to transform the middleware chain per endpoint. It gets the vector of compiled middleware and should return a new vector of middleware.
|
||||
|
||||
## Adding debug middleware between all other middleware
|
||||
|
||||
```clj
|
||||
(def app
|
||||
(ring/ring-handler
|
||||
(ring/router
|
||||
["/api" {:middleware [[wrap 1] [wrap2 2]]}
|
||||
["/ping" {:get {:middleware [[wrap3 3]]
|
||||
:handler handler}}]]
|
||||
{::middleware/transform #(interleave % (repeat [wrap :debug]))})))
|
||||
```
|
||||
|
||||
```clj
|
||||
(app {:request-method :get, :uri "/api/ping"})
|
||||
; {:status 200, :body [1 :debug 2 :debug 3 :debug :handler]}
|
||||
```
|
||||
|
||||
## Reversing the middleware chain
|
||||
|
||||
```clj
|
||||
(def app
|
||||
(ring/ring-handler
|
||||
(ring/router
|
||||
["/api" {:middleware [[wrap 1] [wrap2 2]]}
|
||||
["/ping" {:get {:middleware [[wrap3 3]]
|
||||
:handler handler}}]]
|
||||
{::middleware/transform reverse)})))
|
||||
```
|
||||
|
||||
```clj
|
||||
(app {:request-method :get, :uri "/api/ping"})
|
||||
; {:status 200, :body [3 2 1 :handler]}
|
||||
```
|
||||
|
|
@ -63,7 +63,7 @@
|
|||
(if muuntaja
|
||||
{:data {:swagger {:consumes (displace (m/decodes muuntaja))}}
|
||||
:wrap #(muuntaja.middleware/wrap-format-request % muuntaja)}))})
|
||||
©
|
||||
|
||||
(def format-response-middleware
|
||||
"Middleware for response formatting.
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue