I have a reitit server and a reagent template and I'm trying to allow CORS. I've tried using wrap-cors from ring middleware but am having trouble getting it to work. Has anyone else experience this?
(def app2
(ring/ring-handler
(ring/router
[["/" {:get {:handler index-handler}}]
["/items"
["" {:get {:handler index-handler}}]
["/:item-id" {:get {:handler index-handler
:parameters {:path {:item-id int?}}}}]]
["/about" {:get {:handler index-handler}}]]
{:data {:coercion reitit.coercion.spec/coercion
:muuntaja m/instance
:middleware [params/wrap-params
muuntaja/format-middleware
coercion/coerce-exceptions-middleware
coercion/coerce-request-middleware
coercion/coerce-response-middleware]}})
(ring/create-default-handler)))
Hello!
I have cors working with reitit
here is what I have (cut-down...)
(def cors {"Access-Control-Allow-Origin" "*"
"Access-Control-Allow-Headers" "Origin, Accept, Access-Control-Request-Method, Access-Control-Allow-Headers, Content-Type, *"})
where do you place the def cors?
(defn cors-handler
[_]
{:headers cors :status ok})
(defn router
[app-config]
(ring/router
[["/api"
["/ping" {:get {:handler pong}}]
["/foobar"
["" {:options {:handler cors-handler}
...
...
...
ah so create a custom fn
All those are contained within one namespace
yes
then you can reuse eit
cool, I'll give it a shot! thanks!
/foobar
also has a :post
so when the client does an options first, before the post, it'll hit the cors handler, get back a nice responsee, then invoke the post.
do you have to add this on every route? or can you add to the parent api/?
Doesn't cors mandate that before any dangerous operation, i.e., anything that can modify anything, like POST/PUT/DELETE, then the "options" is hit for that API endpoint
so, if you have POST /foo then the client would invoke a OPTIONS /foo
or a DELETE /foo an OPTIONS /foo
so maybe it has to go on each API, rather than the root
I only have one API endpoint atm, so have it against the /foobar
route.
worth trying! 🙂
easy to test by moving the handler up a level.
(defn router
[app-config]
(ring/router
[["/api"
["/ping" {:get {:handler pong}}]
["/foobar"
["" {:options {:handler cors-handler}
:post {:handler (create-entry app-config)
:parameters {:body {:user-id s/Int
:age s/Int}}}}]]
bbl - have to pop out - hope it works for you! 🙂
bad luck for me, still being blocked
There is :reitit.ring/default-options-handler
in reitit.ring/router
to set custom/cors handling for all routes.
I wish we had a bot that saved threads or something... know I am going to need this info sooner or later, but by then this thread will have disappeared from slack :(
there is the log-bot?
@logbot <-- this one.
For some reason I thought it wasn't working anymore and/or that it didn't log threads, but apparently it does
https://github.com/metosin/reitit/blob/master/modules/reitit-ring/src/reitit/ring.cljc#L81
and add that to the :middleware or the :options of each endpoint?
It's a router option, effecting all routes. So, if you want cors for all routes, you can use that.
some cors-related discussion here: https://github.com/metosin/reitit/issues/236
thanks, still having a little trouble understanding. Does the default-options-handler go in the :data map?
:options :reitit.ring/default-options-handler
nm :reitit.ring/default-options-handler cord-handler
sorry, still confused on where the default-options-handler goes and what data is supposed to go with it. I don't mind added to the readme to help with others who are running into the same issues as me
The docs are lagging with this, but as the first code pointer showed, it's an option to reitit.ring/router
(options mal is the third argument to that fn). Value is a normal ring handler, answering to all OPTIONS
requests, if not explicitly defined for a route. You can do one of the following to enable CORS:
1) mount your custom CORS-ring-handler using that option
2) use a third party CORS mw (like ring-cors)
3) use the code from #236
hope this helps.
@thurmondmb If it can help, it's how I do for eg. with ring-cors:
(ring/router
[["/todos" {:get (fn [_] (-> (store/get-all-todos)
(#(map append-todo-url %))
ok))
:post (fn [{:keys [body]}] (-> body
store/create-todos
append-todo-url
ok))
:delete (fn [_] (store/delete-all-todos)
{:status 204})
:options (fn [_] {:status 200})}]
["/todos/:id" {:parameters {:path {:id s/Int}}
:get (fn [{:keys [parameters]}] (-> (store/get-todo (-> parameters :path :id))
append-todo-url
ok))
:patch (fn [{:keys [parameters body]}] (-> body
(#(store/update-todo (-> parameters :path :id) %))
append-todo-url
ok))
:delete (fn [{:keys [parameters]}] (store/delete-todos (-> parameters :path :id))
{:status 204})}]]
{:data {:coercion reitit.coercion.schema/coercion
:middleware [rrc/coerce-response-middleware
rrc/coerce-request-middleware
rrc/coerce-exceptions-middleware
wrap-keyword-params
wrap-json-response
[wrap-json-body {:keywords? true}]
[wrap-cors :access-control-allow-origin [#".*"]
:access-control-allow-methods [:get :put :post :patch :delete]]]}})
thanks for the help, for some reason, none of this stuff is working