We have a web application that uses HttpKit to serve requests and a handler wrapped with Ring middleware.
The handler is similar to:
(def handler
(-> #'req-handler
(wrap-defaults site-defaults)
(wrap-content-type-and-encoding)
(wrap-cookies)
(wrap-stacktrace)))
In the site-defaults one can find:
:security { ...
:anti-forgery anti-forgery-setting
... }
The application used to serve only requests coming from browsers, but now some of the endpoints respond to API requests, POST operations included.
In the documentation I can read:
This middleware will prevent all HTTP methods except for GET and HEAD from accessing your handler without a valid anti-forgery token.
You should therefore only apply this middleware to the parts of your application designed to be accessed through a web browser. This middleware should not be applied to handlers that define web services.
Is there any way to apply the anti-forgery setting conditionally, or give a different version of the site-defaults
depending on the request?.
You can use ring.middleware.conditional
's operators to conditionally add middleware. For example, to conditionally add the api-defaults
mentioned in the comment of Jochen Bedersdorfer:
(require '[ring.middleware.conditional :as middleware.conditional]
(require '[ring.middleware.defaults :refer [api-defaults site-defaults])
(defn wrap-api-defaults [handler]
(wrap-defaults handler api-defaults))
(defn wrap-site-defaults [handler]
(wrap-defaults handler site-defaults))
(def handler
(-> #'req-handler
(middleware.conditional/if-url-starts-with "/api" wrap-api-defaults)
(middleware.conditional/if-url-doesnt-start-with "/api" wrap-site-defaults)
(wrap-content-type-and-encoding)
(wrap-cookies)
(wrap-stacktrace)))