better docs

This commit is contained in:
Tommi Reiman 2018-08-22 21:51:02 +03:00
parent cef7de58d3
commit 7b3aa5e631
7 changed files with 106 additions and 94 deletions

View file

@ -27,6 +27,7 @@
* [Static Resources](ring/static.md) * [Static Resources](ring/static.md)
* [Dynamic Extensions](ring/dynamic_extensions.md) * [Dynamic Extensions](ring/dynamic_extensions.md)
* [Data-driven Middleware](ring/data_driven_middleware.md) * [Data-driven Middleware](ring/data_driven_middleware.md)
* [Transformations Middleware Chain](ring/transformating_middleware_chain.md)
* [Middleware Registry](ring/middleware_registry.md) * [Middleware Registry](ring/middleware_registry.md)
* [Default Middleware](ring/default_middleware.md) * [Default Middleware](ring/default_middleware.md)
* [Pluggable Coercion](ring/coercion.md) * [Pluggable Coercion](ring/coercion.md)

Binary file not shown.

Before

Width:  |  Height:  |  Size: 203 KiB

After

Width:  |  Height:  |  Size: 228 KiB

View file

@ -6,6 +6,7 @@
* [Static Resources](static.md) * [Static Resources](static.md)
* [Dynamic Extensions](dynamic_extensions.md) * [Dynamic Extensions](dynamic_extensions.md)
* [Data-driven Middleware](data_driven_middleware.md) * [Data-driven Middleware](data_driven_middleware.md)
* [Transformations Middleware Chain](transformating_middleware_chain.md)
* [Middleware Registry](middleware_registry.md) * [Middleware Registry](middleware_registry.md)
* [Default Middleware](default_middleware.md) * [Default Middleware](default_middleware.md)
* [Pluggable Coercion](coercion.md) * [Pluggable Coercion](coercion.md)

View file

@ -88,49 +88,8 @@ All the middleware are applied correctly:
Middleware can be optimized against an endpoint using [middleware compilation](compiling_middleware.md). 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 ## 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. * 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}` * `InjectUserIntoRequestMiddleware` requires `#{:session}` and provides `#{:user}`
* `AuthorizationMiddleware` requires `#{:user}` * `AuthorizationMiddleware` requires `#{:user}`

View file

@ -108,80 +108,95 @@ Swagger-ui:
### More complete example ### More complete example
* `clojure.spec` and `Schema` coercion * `clojure.spec` coercion
* swagger data (`:tags`, `:produces`, `:consumes`) * swagger data (`:tags`, `:produces`, `:summary`)
* swagger-spec served from `"/api/swagger.json"` * swagger-spec served from `"/swagger.json"`
* swagger-ui mounted to `"/"` * swagger-ui mounted to `"/"`
* [Muuntaja](https://github.com/metosin/muuntaja) for request & response formatting * set of middleware for content negotiation, exceptions, multipart etc.
* `wrap-params` to capture query & path parameters
* missed routes are handled by `create-default-handler` * missed routes are handled by `create-default-handler`
* served via [ring-jetty](https://github.com/ring-clojure/ring/tree/master/ring-jetty-adapter) * 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). Whole example project is in [`/examples/ring-swagger`](https://github.com/metosin/reitit/tree/master/examples/ring-swagger).
```clj ```clj
(require '[reitit.ring :as ring] (ns example.server
(require '[reitit.swagger :as swagger] (:require [reitit.ring :as ring]
(require '[reitit.swagger-ui :as swagger-ui] [reitit.swagger :as swagger]
;; coercion [reitit.swagger-ui :as swagger-ui]
(require '[reitit.ring.coercion :as rrc] [reitit.ring.coercion :as coercion]
(require '[reitit.coercion.spec :as spec] [reitit.coercion.spec]
(require '[reitit.coercion.schema :as schema] [reitit.ring.middleware.muuntaja :as muuntaja]
(require '[schema.core :refer [Int]] [reitit.ring.middleware.exception :as exception]
;; web server [reitit.ring.middleware.multipart :as multipart]
(require '[ring.adapter.jetty :as jetty] [ring.middleware.params :as params]
(require '[ring.middleware.params] [ring.adapter.jetty :as jetty]
(require '[muuntaja.middleware])) [muuntaja.core :as m]
[clojure.java.io :as io]))
(def app (def app
(ring/ring-handler (ring/ring-handler
(ring/router (ring/router
["/api" [["/swagger.json"
["/swagger.json"
{:get {:no-doc true {:get {:no-doc true
:swagger {:info {:title "my-api"}} :swagger {:info {:title "my-api"}}
:handler (swagger/create-swagger-handler)}}] :handler (swagger/create-swagger-handler)}}]
["/spec" ["/files"
{:coercion spec/coercion {:swagger {:tags ["files"]}}
:swagger {:tags ["spec"]}}
["/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" ["/plus"
{:get {:summary "plus with spec" {:get {:summary "plus with spec query parameters"
:parameters {:query {:x int?, :y int?}} :parameters {:query {:x int?, :y int?}}
:responses {200 {:body {:total int?}}} :responses {200 {:body {:total int?}}}
:handler (fn [{{{:keys [x y]} :query} :parameters}] :handler (fn [{{{:keys [x y]} :query} :parameters}]
{:status 200 {:status 200
:body {:total (+ x y)}})}}]] :body {:total (+ x y)}})}
:post {:summary "plus with spec body parameters"
["/schema" :parameters {:body {:x int?, :y int?}}
{:coercion schema/coercion :responses {200 {:body {:total int?}}}
:swagger {:tags ["schema"]}} :handler (fn [{{{:keys [x y]} :body} :parameters}]
["/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 {:status 200
:body {:total (+ x y)}})}}]]] :body {:total (+ x y)}})}}]]]
{:data {:middleware [ring.middleware.params/wrap-params {:data {:coercion reitit.coercion.spec/coercion
muuntaja.middleware/wrap-format :muuntaja m/instance
swagger/swagger-feature :middleware [;; query-params & form-params
rrc/coerce-exceptions-middleware params/wrap-params
rrc/coerce-request-middleware ;; content-negotiation
rrc/coerce-response-middleware] muuntaja/format-negotiate-middleware
:swagger {:produces #{"application/json" ;; encoding response body
"application/edn" muuntaja/format-response-middleware
"application/transit+json"} ;; exception handling
:consumes #{"application/json" exception/exception-middleware
"application/edn" ;; decoding request body
"application/transit+json"}}}}) muuntaja/format-request-middleware
;; coercing response bodys
coercion/coerce-response-middleware
;; coercing request parameters
coercion/coerce-request-middleware
;; multipart
multipart/multipart-middleware]}})
(ring/routes (ring/routes
(swagger-ui/create-swagger-ui-handler (swagger-ui/create-swagger-ui-handler {:path "/"})
{:path "/", :url "/api/swagger.json"})
(ring/create-default-handler)))) (ring/create-default-handler))))
(defn start [] (defn start []
@ -242,7 +257,6 @@ Example with:
### TODO ### TODO
* create a data-driven version of [Muuntaja](https://github.com/metosin/muuntaja) that integrates into `:produces` and `:consumes`
* ClojureScript * ClojureScript
* example for [Macchiato](https://github.com/macchiato-framework) * example for [Macchiato](https://github.com/macchiato-framework)
* body formatting * body formatting

View 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]}
```

View file

@ -63,7 +63,7 @@
(if muuntaja (if muuntaja
{:data {:swagger {:consumes (displace (m/decodes muuntaja))}} {:data {:swagger {:consumes (displace (m/decodes muuntaja))}}
:wrap #(muuntaja.middleware/wrap-format-request % muuntaja)}))}) :wrap #(muuntaja.middleware/wrap-format-request % muuntaja)}))})
©
(def format-response-middleware (def format-response-middleware
"Middleware for response formatting. "Middleware for response formatting.