@@ -637,7 +637,7 @@ route to handle a web request to the root of our application.
637
637
:routes [["/" {:get :todo.routes/index}]]}}}
638
638
----
639
639
640
- Then we'll create a handler function for that route.
640
+ Then we'll create a Ring ** handler** function for that route.
641
641
642
642
.src/todo/routes.clj
643
643
[,clojure]
@@ -779,6 +779,112 @@ Or we could return the string directly:
779
779
All of these examples are equivalent, but returning a vector is the most
780
780
convenient and concise.
781
781
782
+
783
+ === Middleware
784
+
785
+ Ring **middleware** are functions that transform Ring handlers. These
786
+ are often used to parse information from the request map, such as
787
+ encoded parameters or session data, or to transform the response map, by
788
+ adding headers or formatting the response body.
789
+
790
+ In the previous section we saw how a Hiccup data structure could be
791
+ directly attached to the response body. This is possible because Duct
792
+ adds default middleware to look for Hiccup and format it into HTML.
793
+
794
+ Let's create some middleware that will add a map of custom headers to
795
+ every response:
796
+
797
+ .src/todo/middleware.clj
798
+ [,clojure]
799
+ ----
800
+ (ns todo.middleware)
801
+
802
+ (defn wrap-headers [headers]
803
+ (fn [handler]
804
+ (fn [request)
805
+ (let [response (handler request)]
806
+ (update response :headers merge headers)))))
807
+ ----
808
+
809
+ Once we've created the middleware function, we can give it to the web
810
+ module via the `:middleware` key:
811
+
812
+ .duct.edn
813
+ [,clojure]
814
+ ----
815
+ {:system
816
+ {:duct.module/logging {}
817
+ :duct.module/web
818
+ {:features #{:site}
819
+ :middleware [#ig/ref :todo.middleware/wrap-headers]
820
+ :routes [["/" {:get :todo.routes/index}]]}
821
+
822
+ :todo.middleware/wrap-headers {"X-Powered-By" "Duct"}}}
823
+ ----
824
+
825
+ We add a new key, `:todo.middleware/wrap-headers`, which configures and
826
+ creates the middleware function, then we use an Integrant ref to add
827
+ that function to a vector of middleware.
828
+
829
+ There three ways to apply middleware:
830
+
831
+ * Middleware is applied to all requests (via `:middleware`)
832
+ * Middleware is applied if any route matches (via `:route-middleware`)
833
+ * Middleware is applied if a **specific** route matches (via
834
+ `:middleware` attached to individual routes)
835
+
836
+ The previous example demonstrated how to apply middleware to all
837
+ requests. However, sometimes you only want middleware to apply if at
838
+ least one route matches. For example:
839
+
840
+ .duct.edn
841
+ [,clojure]
842
+ ----
843
+ {:system
844
+ {:duct.module/logging {}
845
+ :duct.module/web
846
+ {:features #{:site}
847
+ :route-middleware [#ig/ref :todo.middleware/wrap-headers]
848
+ :routes [["/" {:get :todo.routes/index}]]}
849
+
850
+ :todo.middleware/wrap-headers {"X-Route-Matches" "True"}}}
851
+ ----
852
+
853
+ This will add the extra header only if the route matches. It won't be
854
+ added to the default 404 response that is returned when all routes fail
855
+ to match.
856
+
857
+ Finally, you can attach middleware to specific routes, or groups of
858
+ nested routes by adding the `:middleware` key to the route itself:
859
+
860
+ .duct.edn
861
+ [,clojure]
862
+ ----
863
+ {:system
864
+ {:duct.module/logging {}
865
+ :duct.module/web
866
+ {:features #{:site}
867
+ :routes [["/" {:get :todo.routes/index
868
+ :middleware [#ig/ref :todo.middleware/wrap-headers]}]]}
869
+
870
+ :todo.middleware/wrap-headers {"X-Index-Route" "True"}}}
871
+ ----
872
+
873
+ The web module adds a lot of its own middleware, depending on the
874
+ `:features` you choose. Often this is enough, and so we'll remove the
875
+ custom middleware for now; it won't be needed for the rest of this
876
+ document.
877
+
878
+ .duct.edn
879
+ [,clojure]
880
+ ----
881
+ {:system
882
+ {:duct.module/logging {}
883
+ :duct.module/web
884
+ {:features #{:site}
885
+ :routes [["/" {:get :todo.routes/index}]]}}}
886
+ ----
887
+
782
888
=== SQL Database
783
889
784
890
The next step is to add a database to our application. We'll use
0 commit comments