From 165b8e117cb16d903aede65fba5b19e2f464b26a Mon Sep 17 00:00:00 2001 From: Tommi Reiman Date: Sat, 8 Sep 2018 10:42:01 +0300 Subject: [PATCH] Interceptor docs --- doc/SUMMARY.md | 12 ++-- doc/cljdoc.edn | 8 ++- doc/http/interceptors.md | 21 +++--- doc/http/pedestal.md | 25 +++++++ doc/http/sieppari.md | 71 +++++++++++++++++++ .../pedestal-swagger/src/example/server.clj | 6 +- 6 files changed, 120 insertions(+), 23 deletions(-) create mode 100644 doc/http/pedestal.md create mode 100644 doc/http/sieppari.md diff --git a/doc/SUMMARY.md b/doc/SUMMARY.md index 3dfea36a..e7909620 100644 --- a/doc/SUMMARY.md +++ b/doc/SUMMARY.md @@ -37,17 +37,19 @@ * [Compiling Middleware](ring/compiling_middleware.md) * [Swagger Support](ring/swagger.md) +## HTTP + +* [Interceptors](http/interceptors.md) +* [Pedestal](http/pedestal.md) +* [Sieppari](http/sieppari.md) +* [Default Interceptors](http/default_interceptors.md) + ## Frontend * [Basics](frontend/basics.md) * [Browser integration](frontend/browser.md) * [Controllers](frontend/controllers.md) -## HTTP - -* [Interceptors](http/interceptors.md) -* [Default Interceptors](http/default_interceptors.md) - ## Advanced * [Configuring Routers](advanced/configuring_routers.md) diff --git a/doc/cljdoc.edn b/doc/cljdoc.edn index 8ea31d14..29778524 100644 --- a/doc/cljdoc.edn +++ b/doc/cljdoc.edn @@ -35,13 +35,15 @@ ["Route Data Validation" {:file "doc/ring/route_data_validation.md"}] ["Compiling Middleware" {:file "doc/ring/compiling_middleware.md"}] ["Swagger Support" {:file "doc/ring/swagger.md"}]] + ["HTTP" {} + ["Interceptors" {:file "doc/http/interceptors.md"}] + ["Pedestal" {:file "doc/http/pedestal.md"}] + ["Sieppari" {:file "doc/http/sieppar.md"}] + ["Default Interceptors" {:file "doc/http/default_interceptors.md"}]] ["Frontend" {} ["Basics" {:file "doc/frontend/basics.md"}] ["Browser integration" {:file "doc/frontend/browser.md"}] ["Controllers" {:file "doc/frontend/controllers.md"}]] - ["HTTP" {} - ["Interceptors" {:file "doc/http/interceptors.md"}] - ["Default Interceptors" {:file "doc/http/default_interceptors.md"}]] ["Advanced" {} ["Configuring Routers" {:file "doc/advanced/configuring_routers.md"}] ["Composing Routers" {:file "doc/advanced/composing_routers.md"}] diff --git a/doc/http/interceptors.md b/doc/http/interceptors.md index 43273f2b..83d314ce 100644 --- a/doc/http/interceptors.md +++ b/doc/http/interceptors.md @@ -1,6 +1,6 @@ # Interceptors -Reitit also support for [Pedestal](pedestal.io)-style [interceptors](http://pedestal.io/reference/interceptors) as an alternative to using middleware. Basic interceptor handling is implemented in `reitit.interceptor` package. There is no interceptor executor shipped, but you can use libraries like [Pedestal Interceptor](https://github.com/pedestal/pedestal/tree/master/interceptor) or [Sieppari](https://github.com/metosin/sieppari) to execute the chains. +Reitit also support for [interceptors](http://pedestal.io/reference/interceptors) as an alternative to using middleware. Basic interceptor handling is implemented in `reitit.interceptor` package. There is no interceptor executor shipped, but you can use libraries like [Pedestal Interceptor](https://github.com/pedestal/pedestal/tree/master/interceptor) or [Sieppari](https://github.com/metosin/sieppari) to execute the chains. ## Reitit-http @@ -8,18 +8,15 @@ Reitit also support for [Pedestal](pedestal.io)-style [interceptors](http://pede [metosin/reitit-http "0.2.1"] ``` -An module for http-routing using interceptors instead of middleware. Builds on top of the [`reitit-ring`](../ring/ring.md) module. The differences: +An module for http-routing using interceptors instead of middleware. Builds on top of the [`reitit-ring`](../ring/ring.md) module having all the same features. + +The differences: * instead of `:middleware`, uses `:interceptors` -* compared to `reitit.http/http-router` takes an extra options map with mandatory key `:executor` (of type `reitit.interceptor/Executor`) and optional top level `:interceptors` - wrapping both routes and default handler. -* optional entry poitn `reitit.http/routing-interceptor` to provide a routing interceptor, to be used with Pedestal. +* compared to `reitit.ring/ring-router`, the `reitit.http/http-router` takes an extra options map with mandatory key `:executor` (of type `reitit.interceptor/Executor`) and optional top level `:interceptors` - wrapping both routes and default handler. +* instead of creating a ring-handler, apps can be wrapped into a routing interceptor that enqueues the matched interceptors into the context. For this, there is `reitit.http/routing-interceptor`. -## Examples +## Why interceptors? -### Sieppari - -See code at: https://github.com/metosin/reitit/tree/master/examples/http - -### Pedestal - -See example at: https://github.com/metosin/reitit/tree/master/examples/pedestal +* https://quanttype.net/posts/2018-08-03-why-interceptors.html +* https://www.reddit.com/r/Clojure/comments/9csmty/why_interceptors/ diff --git a/doc/http/pedestal.md b/doc/http/pedestal.md new file mode 100644 index 00000000..d5113be3 --- /dev/null +++ b/doc/http/pedestal.md @@ -0,0 +1,25 @@ +# Pedestal + +[Pedestal](http://pedestal.io/) is a well known interceptor implmementation for Clojure. To use `reitit-http` with it, we need to change the default routing interceptor into a new one. Currently, there isn't a separate Pedestal-module in reitit, but the examples have the example code how to do this. + +## Caveat + +`reitit-http` defines Interceptors as `reitit.interceptor/Interceptor`. Compared to Pedestal (2-arity), reitit uses a simplified (1-arity) model for handling errors, described in the [Sieppari README](https://github.com/metosin/sieppari#differences-to-pedestal). + +* you can use any [pedestal-style interceptor](http://pedestal.io/reference/interceptors) within reitit router (as Pedestal is executing those anyway) +* you can use any reitit-style interceptor that doesn't have `:error`-stage defined +* using a reitit-style interceptor with `:error` defined will cause `ArityException` if invoked + +See the [error handling guide](http://pedestal.io/reference/error-handling) on how to handle errors with Pedestal. + +## Examples + +### Simple + +* simple example, with both sync & async code: + * https://github.com/metosin/reitit/tree/master/examples/pedestal + +### With batteries + +* with [default interceptors](default_interceptors.md), [coercion](../coercion/coercion.md) and [swagger](../ring/swagger.md)-support (note: exception handling is disabled): + * https://github.com/metosin/reitit/tree/master/examples/pedestal-swagger diff --git a/doc/http/sieppari.md b/doc/http/sieppari.md new file mode 100644 index 00000000..ea979619 --- /dev/null +++ b/doc/http/sieppari.md @@ -0,0 +1,71 @@ +# Sieppari + +```clj +[metosin/reitit-sieppari "0.2.1"] +``` + +[Sieppari](https://github.com/metosin/sieppari) is a new and fast interceptor implementation with pluggable async ([core.async](https://github.com/clojure/core.async), [Manifold](https://github.com/ztellman/manifold) and [Promesa](http://funcool.github.io/promesa/latest)). + +To use Sieppari with `reitit-http`, there is `reitit-sieppari` module, which has an `reitit.interceptor.Executor` implementation for Sieppari. All reitit interceptors use the Sieppari Interceptor model, so they work seamlesly together. + +Synchronous Ring: + +```clj +(require '[reitit.http :as http]) +(require '[reitit.interceptor.sieppari :as sieppari]) + +(defn i [x] + {:enter (fn [ctx] (println "enter " x) ctx) + :leave (fn [ctx] (println "leave " x) ctx)}) + +(defn handler [_] + (future {:status 200, :body "pong"})) + +(def app + (http/ring-handler + (http/router + ["/api" + {:interceptors [(i :api)]} + + ["/ping" + {:interceptors [(i :ping)] + :get {:interceptors [(i :get)] + :handler handler}}]]) + {:executor sieppari/executor})) + +(app {:request-method :get, :uri "/api/ping"}) +;enter :api +;enter :ping +;enter :get +;leave :get +;leave :ping +;leave :api +;=> {:status 200, :body "pong"} +``` + +Ring-async: + +```clj +(let [respond (promise)] + (app {:request-method :get, :uri "/api/ping"} respond nil) + (deref respond 1000 ::timeout)) +;enter :api +;enter :ping +;enter :get +;leave :get +;leave :ping +;leave :api +;=> {:status 200, :body "pong"} +``` + +## Examples + +### Simple + +* simple example, with both sync & async code: + * https://github.com/metosin/reitit/tree/master/examples/http + +### With batteries + +* with [default interceptors](default_interceptors.md), [coercion](../coercion/coercion.md) and [swagger](../ring/swagger.md)-support: + * https://github.com/metosin/reitit/tree/master/examples/http-swagger diff --git a/examples/pedestal-swagger/src/example/server.clj b/examples/pedestal-swagger/src/example/server.clj index 2b41006e..6f80a29c 100644 --- a/examples/pedestal-swagger/src/example/server.clj +++ b/examples/pedestal-swagger/src/example/server.clj @@ -9,7 +9,7 @@ [reitit.coercion.spec :as spec-coercion] [reitit.http.interceptors.parameters :as parameters] [reitit.http.interceptors.muuntaja :as muuntaja] - [reitit.http.interceptors.exception :as exception] + #_[reitit.http.interceptors.exception :as exception] [reitit.http.interceptors.multipart :as multipart] [muuntaja.core :as m] [clojure.java.io :as io])) @@ -69,8 +69,8 @@ (muuntaja/format-negotiate-interceptor) ;; encoding response body (muuntaja/format-response-interceptor) - ;; exception handling - (exception/exception-interceptor) + ;; exception handling - doesn't work + ;;(exception/exception-interceptor) ;; decoding request body (muuntaja/format-request-interceptor) ;; coercing response bodys