Fork me on GitHub
#reitit
<
2020-05-10
>
Michael Thurmond18:05:51

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

dharrigan18:05:15

I have cors working with reitit

dharrigan18:05:24

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

dharrigan18:05:32

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

Michael Thurmond18:05:55

where do you place the def cors?

dharrigan18:05:56

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

dharrigan18:05:15

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

Michael Thurmond18:05:21

ah so create a custom fn

dharrigan18:05:33

All those are contained within one namespace

dharrigan18:05:39

then you can reuse eit

Michael Thurmond18:05:45

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

dharrigan18:05:54

/foobar also has a :post

dharrigan18:05:14

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.

Michael Thurmond18:05:56

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

dharrigan18:05:00

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

dharrigan18:05:15

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

dharrigan18:05:27

or a DELETE /foo an OPTIONS /foo

dharrigan18:05:36

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

dharrigan18:05:52

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

dharrigan18:05:16

worth trying! 🙂

dharrigan18:05:25

easy to test by moving the handler up a level.

dharrigan18:05:15

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

dharrigan18:05:12

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

Michael Thurmond19:05:00

bad luck for me, still being blocked

ikitommi19:05:18

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

Michael Thurmond19:05:59

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

ikitommi19:05:00

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

Michael Thurmond19:05:12

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

Michael Thurmond19:05:17

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

Michael Thurmond19:05:15

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

Michael Thurmond19:05:58

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

ikitommi20:05:01

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

ikitommi20:05:08

hope this helps.

Michaël Salihi20:05:21

@U9V3P92CF 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]]]}})

Michael Thurmond20:05:26

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

Michael Thurmond05:05:19

finally got it working, thanks

👍 8
polymeris02:05:28

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

ikitommi20:05:59

there is the log-bot?

polymeris00:05:04

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