reitit

https://cljdoc.org/d/metosin/reitit/ https://github.com/metosin/reitit/
2020-05-10T18:48:51.347700Z

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)))

dharrigan 2020-05-10T18:49:08.347900Z

Hello!

dharrigan 2020-05-10T18:49:15.348200Z

I have cors working with reitit

dharrigan 2020-05-10T18:49:24.348600Z

here is what I have (cut-down...)

dharrigan 2020-05-10T18:49:32.348800Z

(def cors {"Access-Control-Allow-Origin" "*"
           "Access-Control-Allow-Headers" "Origin, Accept, Access-Control-Request-Method, Access-Control-Allow-Headers, Content-Type, *"})

2020-05-10T18:49:55.349200Z

where do you place the def cors?

dharrigan 2020-05-10T18:49:56.349300Z

(defn cors-handler
  [_]
  {:headers cors :status ok})

dharrigan 2020-05-10T18:50:15.349800Z

(defn router
  [app-config]
  (ring/router
   [["/api"
     ["/ping" {:get {:handler pong}}]
     ["/foobar"
      ["" {:options {:handler cors-handler}
...
...
...

2020-05-10T18:50:21.350100Z

ah so create a custom fn

dharrigan 2020-05-10T18:50:33.350500Z

All those are contained within one namespace

dharrigan 2020-05-10T18:50:35.350700Z

yes

dharrigan 2020-05-10T18:50:39.351Z

then you can reuse eit

2020-05-10T18:50:45.351300Z

cool, I'll give it a shot! thanks!

dharrigan 2020-05-10T18:50:54.351500Z

/foobar also has a :post

dharrigan 2020-05-10T18:51:14.352100Z

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.

2020-05-10T18:51:56.352800Z

do you have to add this on every route? or can you add to the parent api/?

dharrigan 2020-05-10T18:53:00.353800Z

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

dharrigan 2020-05-10T18:53:15.354200Z

so, if you have POST /foo then the client would invoke a OPTIONS /foo

dharrigan 2020-05-10T18:53:27.354600Z

or a DELETE /foo an OPTIONS /foo

dharrigan 2020-05-10T18:53:36.354900Z

so maybe it has to go on each API, rather than the root

dharrigan 2020-05-10T18:53:52.355300Z

I only have one API endpoint atm, so have it against the /foobar route.

dharrigan 2020-05-10T18:54:16.355600Z

worth trying! 🙂

dharrigan 2020-05-10T18:54:25.355900Z

easy to test by moving the handler up a level.

dharrigan 2020-05-10T18:55:15.356400Z

(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}}}}]]

dharrigan 2020-05-10T18:56:12.357200Z

bbl - have to pop out - hope it works for you! 🙂

2020-05-10T19:06:00.357700Z

bad luck for me, still being blocked

ikitommi 2020-05-10T19:08:18.359700Z

There is :reitit.ring/default-options-handler in reitit.ring/router to set custom/cors handling for all routes.

polymeris 2020-05-12T02:05:28.369200Z

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 :(

ikitommi 2020-05-12T20:46:59.389500Z

there is the log-bot?

ikitommi 2020-05-12T20:47:08.389700Z

@logbot <-- this one.

polymeris 2020-05-16T00:52:04.415Z

For some reason I thought it wasn't working anymore and/or that it didn't log threads, but apparently it does

2020-05-10T19:11:59.360500Z

and add that to the :middleware or the :options of each endpoint?

ikitommi 2020-05-10T19:21:00.360800Z

It's a router option, effecting all routes. So, if you want cors for all routes, you can use that.

ikitommi 2020-05-10T19:21:44.361Z

some cors-related discussion here: https://github.com/metosin/reitit/issues/236

2020-05-10T19:25:12.361300Z

thanks, still having a little trouble understanding. Does the default-options-handler go in the :data map?

2020-05-10T19:25:17.361500Z

:options :reitit.ring/default-options-handler

2020-05-10T19:33:15.361700Z

nm :reitit.ring/default-options-handler cord-handler

2020-05-10T19:50:58.362Z

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

ikitommi 2020-05-10T20:16:01.362200Z

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

ikitommi 2020-05-10T20:16:08.362400Z

hope this helps.

2020-05-10T20:30:21.362700Z

@thurmondmb If it can help, it's how I do for eg. with ring-cors:

(ring/router
    [["/todos" {:get (fn [_] (-&gt; (store/get-all-todos)
                                (#(map append-todo-url %))
                                ok))
                :post (fn [{:keys [body]}] (-&gt; 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]}] (-&gt; (store/get-todo (-&gt; parameters :path :id))
                                                       append-todo-url
                                                       ok))
                    :patch (fn [{:keys [parameters body]}] (-&gt; body
                                                              (#(store/update-todo (-&gt; parameters :path :id) %))
                                                              append-todo-url
                                                              ok))
                    :delete (fn [{:keys [parameters]}] (store/delete-todos (-&gt; 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]]]}})

2020-05-10T20:58:26.362900Z

thanks for the help, for some reason, none of this stuff is working