Fork me on GitHub
#reitit
<
2019-06-11
>
Jarrod Taylor (Clojure team)01:06:09

Given the following app definition what is the recommend way to not have the middleware run when making an options request to the /example route?

(def app
  (ring/ring-handler
    (ring/router
      [["/example" {:middleware [(fn [handler]
                                   (fn [request]
                                     (println "Unexpected Middleware?")
                                     (handler request)))]
                    :get (fn [_] {:status 200 :body "The Example"})}]]
      {:reitit.ring/default-options-handler (fn [_] {:status 200 :body ""})})))
Attempting to use some middleware that is expecting header data not present on the options request.

ikitommi07:06:48

@jarrodctaylor there are many options, if you wan’t to remove all middleware from :options, you can add {:options {:middleware ^:replace []}}.

Jarrod Taylor (Clojure team)12:06:03

Thanks for the options options 🙂! +1 for being a good example to include in the docs.

ikitommi07:06:52

or, you could create a custom wrapper to wrap the mw’s into another mw that checks the :request-method and doesn’t call the child mw if it’s options.

ikitommi07:06:56

or, you could annotate the mw with something like :methods #{:get :post ...} and have a middleware chain transformer remove the middleware from all the methods, that are not listed in the middleware definition. the middleware definition would look like:

:middleware [{:methods #{:get :post}, :wrap (fn [handler] ...)}]

ikitommi07:06:25

or, we could add the method as a key for the middleware compiler, so one use it instead of the middleware chain transformer

ikitommi07:06:33

or, you could have a simple function that is used to generate or modify the endpoint data, it’s all data in the end.

ikitommi07:06:10

something like:

(-> {:get (fn [_] {:status 200 :body "The Example"})}
    (merge-to-all-but-options {:middleware [(fn [handler]
                                              (fn [request]
                                                (println "Unexpected Middleware?")
                                                (handler request)))]}))

ikitommi07:06:29

I think it’s a good case to have an example in the docs.

ikitommi07:06:14

two more simple options: 1) just add an if to the mw for the request-method 2) mount the mw manually to all endpoints but :options

dotemacs09:06:05

Hi, been using reitit for a while now, loving it, thank you for the great library. I have a bit of an odd question: I have a large JSON object that needs to be returned to a user. It takes a while to process it and due to that, the connection times out with 504, because it takes longer than 30 seconds for the server to respond with all the data processed. So a question is would a streaming response be a good workaround in this case, so that the data is sent in smaller chunks as it comes in, rather than waiting for all of it to be processed? If it is, is there something that I could look at to get an idea how to do it? On the other hand, if this is not the right way to go about it, what would you suggest? Thanks in advance

valerauko10:06:28

Are you considering something like websocket?

dotemacs14:06:29

No, not websockets. I was hoping for something else. I’ve seen this example with aleph (scroll down to streaming-numbers-handler function(s)): https://aleph.io/examples/literate.html#aleph.examples.http

ikitommi17:06:35

@dotemacs I think it would require two things: 1) a streaming JSON writer and 2) no return mw/interceptors. Currently, reitit-http supports Manifold oob, but none of the :leave stage interceptors would be able to access the body as it's just a stream. E.g. response coercion would not work

ikitommi17:06:44

for the streaming JSON... if you would send a stream of independent JSON chunks, it would be easy, if you have a huge map/array, you would need to construct the beginning of the payload somehow and then stream the chuncks and close again somehow.

ikitommi17:06:22

If Jackson can do that, happy to add support to Jsonista. Or a PR for the support.

ikitommi17:06:37

If there is an easy way, would like to hear it!

dotemacs17:06:20

This is what I’ve been trying today. Let me see what works for this use case that I’ve got and I’ll report back here. Thanks for the reply @ikitommi