reitit 2024-12-18

I'm trying to figure out how to stop muuntaja from doing request parsing on a single route. It's a file upload route, I need access to the untouched body inputstream... I thought this might do it

["/foo" {:put {:muuntaja nil, :handler PUT-foo}}]
but so far that doesn't do much...

Is the content-type one that Muuntaja handles?

could it be the coercion that's parsing the request? try :coercion nil

If it is multipart, zip or image or such, I don't think Muuntaja should be touching the req body. I don't remember having to do much special tricks with Muuntaja when handling uploads.

Though maybe I've added a multipart mw before muuntaja

yeah I have an upload here in my current project as well and no tricks needed

it's not multipart, it's an API call, just a plain request body

if I comment out the muuntaja request middleware I get what I want, so muuntaja is the culprit, not coercion

✅ 1

Hhmhm. Not sure why removing the muuntaja instance doesn't work. Might depend on how the mw is applied to routes.

ok, so it's supposed to work this way. That's already good to know, then I can dig into why it's not 🙂

yeah it should get disabled by a nil muuntaja instance looking at the code

If you can modify request :muuntaja/request property between format-negotiate-middleware and format-request-middleware that should also disable the request parsing for that request.

just checking: which muuntaja middleware? reitit.ring.middleware.muuntaja/format-middleware is the one I'm looking at

👍 1

I tried to dig through the code but the route compilation I find confusing...

https://github.com/metosin/reitit/blob/master/modules/reitit-middleware/src/reitit/ring/middleware/muuntaja.clj#L72 Yeah this should correctly apply the mw to the route only if route data has muuntaja instance

try moving :muuntaja property outside of :put data

http methods are special case... routing happens with only the path information, so maybe mw are applied before the method is checked

the mw is looking for muuntaja on the same level as parameters, so I doubt that'll help

I wonder if there's a nice way to print out the compiled routes...

tried moving it up but no luck

route-data is merged using meta-merge... does the nil value need a ^:replace?

you could try using r/match-by-path to see if the match contains a muuntaja instance

💯 1

great suggestion! I don't think nil can take metadata.

yeah just realised that as well...

and yeah, meta-merge ignores nils

false might work

user=> (require '[meta-merge.core :refer [meta-merge]])
nil
user=> (meta-merge {:a 1} {:a nil})
{:a 1}
user=> (meta-merge {:a nil} {:a 1})
{:a 1}

but didn't we have our own meta-merge like merge for reitit 😄

let me check, I thought we use the official one...

yeah it is the regular meta-merge

user=> (require '[reitit.impl :refer [meta-merge]])
nil
user=> (meta-merge {:a 1} {:a nil} {})
{:a 1}
user=> (meta-merge {:a nil} {:a 1} {})
{:a 1}
user=> (meta-merge {:a 1} {:a false} {})
{:a false}
(extra param is opts)

Oh right the reitit meta-merge opts also allows you to replace meta-merge impl...

YES false does the trick

THANK YOU 🙏

And update-paths option is to handle Malli schema merge IIRC

ugh such an annoying meta-merge sharp edge

😿 1

pro tip: use :muuntaja false in route data to disable muuntaja (or anything else) for a single route. :muuntaja nil doesn't work

it wouldn't hurt to have an example in there of how to override something like muuntaja, it's not always obvious where the keys should go