Fork me on GitHub
#reitit
<
2023-05-31
>
grahamcarlyle16:05:37

I was wanting to check the expected params for the reitit-ring/router function and I see in the relevant https://cljdoc.org/d/metosin/reitit/0.7.0-alpha4/api/reitit.ring#router that it refers to the reitit.core/router for available options, but this namespace doesnt have any generated docs i can see, though the https://github.com/metosin/reitit/blob/master/modules/reitit-core/src/reitit/core.cljc#L313 , are the reitit.core docs unintentionally missing?

jmckitrick22:05:04

I have an app packed with most of the reitit features, so everything is wrapped in middleware, including coercion. But I have a handler where I need to access the raw request body for signature verification. Is there a way to either suppress coercion of json only for this endpoint, or better yet, have access to both formats of the body while in the handler?

Ben Sless04:06:15

The uncoerced body should be in :body-params, no?

opqdonut07:06:11

at least for Jetty, the :body is a read-once inputstream, so once sombody has parsed the body it's no longer available

opqdonut07:06:29

I've worked around this with an early middleware that does something like (update req :body slurp)

opqdonut07:06:51

the other middlewares know how to work with a string just as well as an inputstream

opqdonut07:06:00

I think there was a thread about this here just a while ago

Ben Sless10:06:46

If you're using all the reitit middlewares, including the parameters middleware you'll have the parsed body after format negotiation under body-params. Read it from there, the body key belongs to the server

opqdonut11:06:41

Yeah, but the OP wanted the raw original request body

Ben Sless11:06:03

In the context of coercion, the impetus for the question, I assume raw means unprocessed data structures, not raw bytes as they came in over the wire

opqdonut11:06:18

right! I assumed raw bytes since signatures were mentioned, but I might be wrong

jmckitrick02:06:58

@UK0810AQ2 That’s close to what I want… I just want a JSON body in raw text, without JSON coercion so I can use it for calculating the signature. Text is fine, raw bytes are unnecessary.

jmckitrick10:06:31

Okay, that worked perfectly. The last piece of the puzzle is how to include this middleware in the app stack but only enable it for a small set of routes. If I have conditional logic inside the middleware functions, how can I get a simple flag to that middleware?

jmckitrick11:06:11

I don’t completely understand the reitit middleware-as-data completely, but it seems I should be able to have:

jmckitrick11:06:30

:middleware [[wrap-raw-body true]]

jmckitrick11:06:30

Or something like this in the routes where it is needed. But apparently my understanding of the routing is incorrect, because I’m getting stack traces when I hit those routes.

jmckitrick11:06:45

I assume I’m configuring that middleware incorrectly.

jussi11:06:18

You can define middleware per route, like

["/api/healthcheck" ;; affected only by general middleware
      {:no-doc true
       :get {:summary "Healthcheck for system status"
             :parameters {} ; Do not allow any query parameters.
             :responses {200 {:body string?}}}
       :handler (fn [_]
                  (if (db/in-sync? db)
                    {:status 200 :body "ok"}
                    {:status 503 :body "sync in process"}))}]
     ["/api"
      {:swagger {:tags ["api"]}
       :middleware [wrap-request-audit-log ;; special middleware for everything unded /api not affecting other routes
                    (api-key/create-verification-middleware get-db)
                    validate-response-with-logging]}
      ["/some-fn-under-api"
       {:put {:summary "Affected by middleware defined in previous level"
              :handler
              (fn [a]
                (put-handler/do-something a))}}]

jussi11:06:30

The :middleware key is the magic and defined middlewares only apply to that level and levels below.

jmckitrick13:06:14

Thanks! I figured it out, and it’s exactly like you said. It works great now.

2