This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2023-01-20
Channels
- # adventofcode (8)
- # aleph (2)
- # announcements (10)
- # aws (5)
- # aws-lambda (2)
- # babashka (23)
- # beginners (23)
- # biff (9)
- # calva (4)
- # cider (8)
- # clj-kondo (21)
- # clojure (77)
- # clojure-boston (1)
- # clojure-dev (50)
- # clojure-europe (36)
- # clojure-gamedev (3)
- # clojure-nl (1)
- # clojure-norway (3)
- # clojure-spec (33)
- # clojure-uk (3)
- # clojurescript (22)
- # core-async (3)
- # cursive (10)
- # datahike (18)
- # datalevin (1)
- # datascript (9)
- # deps-new (21)
- # emacs (11)
- # events (1)
- # graphql (11)
- # guix (26)
- # java (7)
- # jobs (3)
- # lsp (12)
- # malli (6)
- # pathom (33)
- # pedestal (3)
- # polylith (15)
- # reagent (5)
- # releases (3)
- # remote-jobs (1)
- # scittle (9)
- # sql (27)
- # tools-build (9)
- # vim (7)
I have a route path that should support both get and delete http methods.
Thing is if I put it under :routes
, GET works but not DELETE (I'm getting a 403). I definitely don't want to put :delete under api-routes because I need CSRF protection.
I believe I need to set up CORS for htmx: https://htmx.org/docs/#cors but I'm not sure that's it or how to do it. My routes (simplified) in ๐งต
(def features
{:routes ["/app" {:middleware [anti-forgery/wrap-anti-forgery
biff/wrap-anti-forgery-websockets
mid/wrap-signed-in
[cors/wrap-cors
:access-control-allow-origin #".*"
:access-control-allow-methods [:delete]]]}
["/match/:match-id" {:get (partial app-wrapper match)
:delete match-delete}]
["/settings" {:get (partial app-wrapper settings)}]]})
/app/settings
contains two buttons. One makes an htmx call to GET /app/match/:match-id
and another to DELETE /app/match/:match-id
. The former works but not the latterIt doesn't make any difference whether I include the wrap-cors middleware or not
the htmx request probably isn't including the csrf token. if the request happens inside of a (biff/form ...)
then the token should get included, but in other cases you need to do more stuff to include the token. you can check the request headers/form parameters to see if the token is there.
here's an example from the tutorial: https://github.com/jacobobryant/eelchat/blob/184bbd32fd86f608bb8bc8a82247df47d2456249/src/com/eelchat/ui.clj#L60
I've been thinking I should make biff do that by default
Not on my machine now but from the sounds of it I'm pretty sure that's it. The request doesn't come from a form and I didn't realize I had to add the headers explicitly
Why does it only happen with delete though?
I believe GET
requests don't require a csrf token because they shouldn't be changing anything in your database.
Right, that's what I thought, thanks for confirming, but who decides whether a csrf token is necessary? Is this a web server (e.g. jetty) or a browser thing (i.e. web standard)?
Ooh, that's a good question. It looks like the Ring anti-forgery middleware that Biff wraps all the non-`api-routes` in is doing the checking: https://github.com/ring-clojure/ring-anti-forgery/blob/master/src/ring/middleware/anti_forgery.clj
In fact, in addition to GET
requests, it lets HEAD
and OPTIONS
requests through, too:
(defn- get-request? [{method :request-method}]
(or (= method :head)
(= method :get)
(= method :options)))
(defn- valid-request? [strategy request read-token]
(or (get-request? request)
(when-let [token (read-token request)]
(strategy/valid-token? strategy request token))))