At this point, standard-html-middleware
just uses ring.middleware.defaults/middleware-defaults
.
This is fine right up until we want to add our own middleware or understand what middleware is in place and what it does.
That is something we will want when adding user auth later.
Which means there would be value in moving away from ring.middleware.defaults/middleware-defaults
and explicitly writing out the middleware it implies.
middleware-defaults
into an explicit vector of middlewares
Figuring out what you actually get from site-defaults
is a bit of a detective game. You need to look
at the options set on site-defaults
and trace through middleware-defaults
to figure out what is going to be applied.
The following code is the result of that investigation, sans a few middleware whose purpose is just to serve over static files.
For now, we are going to rely on explicit entries in example.static.routes
for that.
(ns example.middleware
(:require
[ring.middleware.anti-forgery :refer [wrap-anti-forgery]]
[ring.middleware.content-type :refer [wrap-content-type]]
[ring.middleware.cookies :refer [wrap-cookies]]
[ring.middleware.default-charset :refer [wrap-default-charset]]
[ring.middleware.flash :refer [wrap-flash]]
[ring.middleware.keyword-params :refer [wrap-keyword-params]]
[ring.middleware.multipart-params :refer [wrap-multipart-params]]
[ring.middleware.nested-params :refer [wrap-nested-params]]
[ring.middleware.not-modified :refer [wrap-not-modified]]
[ring.middleware.params :refer [wrap-params]]
[ring.middleware.session :refer [wrap-session]]
[ring.middleware.session.cookie :refer [cookie-store]]
[ring.middleware.x-headers :as x]))
(def default-session-store (cookie-store))
(defn standard-html-route-middleware
[_system]
[#(x/wrap-content-type-options % :nosniff)
#(x/wrap-frame-options % :sameorigin)
wrap-not-modified
#(wrap-default-charset % "utf-8")
wrap-content-type
wrap-cookies
wrap-params
wrap-multipart-params
wrap-nested-params
wrap-keyword-params
#(wrap-session % {:cookie-attrs {:http-only true}
:store default-session-store})
wrap-flash
wrap-anti-forgery])
A huge vector of functions with somewhat generic names like "wrap-params
" can be hard
to navigate. Just like with dependencies, it can pay off later if we add comments now for what each of these
things do.
(ns example.middleware
(:require
...))
(defn standard-html-route-middleware
[{::system/keys [cookie-store]}]
[;; Prevents "media type confusion" attacks
#(x/wrap-content-type-options % :nosniff)
;; Prevents "clickjacking" attacks
#(x/wrap-frame-options % :sameorigin)
;; Returns "304 Not Modified" if appropriate
wrap-not-modified
;; Adds "; charset=utf-8" to responses if none specified
#(wrap-default-charset % "utf-8")
;; Guesses an appropriate Content-Type if none set
wrap-content-type
;; Parses out cookies from the request
wrap-cookies
;; Parses out urlencoded form and url parameters
wrap-params
;; Parses out multipart params.
;; Useful for things like file uploads
wrap-multipart-params
;; Handles "multi-value" form parameters
wrap-nested-params
;; Turns any string keys in :params into keywords
wrap-keyword-params
;; Handles reading and writing "session data"
#(wrap-session % {:cookie-attrs {:http-only true}
:store cookie-store})
;; Handles "flash" data which is around only until the
;; immediate next request.
wrap-flash
;; Ensures that POST requests contain an anti-forgery token
wrap-anti-forgery])
/cave
This is the route that currently makes the most use of the functionality added by all this middleware.
The anti-forgery token comes in from and is validated by the anti-forgery middleware and the :params
that /cave/create
reads from comes from wrap-params
.