Fork me on GitHub
#reitit
<
2021-12-05
>
Yevgeni Tsodikov16:12:54

Hey, Is it possible to decode/transform a UUID passed as a string into a java.util.UUID as part of the request coercion? The request is defined as:

[:map
  [:request_id :uuid]
  ; other fields
  ]
Clients send the request_id as a string. but I’d to work with a java.util.UUID in the handlers after setting the coerce-request-middleware

Ben Sless16:12:38

Yes, you need to use a string decoder though instead of the default json

Ben Sless16:12:19

https://github.com/metosin/reitit/blob/master/modules/reitit-malli/src/reitit/coercion/malli.cljc#L109 Override the default transformer to string instead of json transformer for content type

Yevgeni Tsodikov17:12:40

Do I need to specify all the inner keys? (`:body`, :string and :response )

Ben Sless17:12:34

I think you need body and string. If you respond with the uuid, that as well

Yevgeni Tsodikov17:12:06

Are there any side-effects to using the string decoder instead of the json decoder?

Yevgeni Tsodikov17:12:44

Am I doing it right? The request_id is still a string in the :body-params ..

(reitit-coercion-malli/create
  {:error-keys       #{:humanized}
   :compile          malli-util/open-schema
   :validate         true
   :enabled          true
   :encode-error     (fn [validation-body] {:errors (:humanized validation-body)})
   :default-values   false
   :strip-extra-keys true
   :transformers     {:body   {:default reitit-coercion-malli/string-transformer-provider
                               :formats {"application/json" reitit-coercion-malli/string-transformer-provider}}
                      :string {:default reitit-coercion-malli/string-transformer-provider}}})

juhoteperi08:12:10

Uhhh, yes, string deocder includes transformations that don't make sense with JSON. AND using string decoder here doesn't change anything, UUID transformer is part of json-decoders (and string-decoders includes all json-decoders + others).

juhoteperi08:12:21

@U02AH3D0HEV :body-params will never contain coerced values, those are always the raw params, coerced values are under req :parameters :body

Yevgeni Tsodikov11:12:50

@U061V0GG2, the :parameters field doesn’t exist in the req , the only relevant fields are :path-params, :headers and :body-params

juhoteperi11:12:32

Then you are missing the coercion middlewares

Yevgeni Tsodikov11:12:17

Ah, that’s my bad, I was in the wrong branch 😐 The :parameters exist an the request_id , once defined as a :uuid gets coerced into a java.util.UUID

Yevgeni Tsodikov11:12:48

I didn’t know about the :parameters field, though. Can you point me to the relevant docs?

juhoteperi12:12:01

https://cljdoc.org/d/metosin/reitit/0.5.15/doc/ring/pluggable-coercion#defining-parameters-and-responses > Handlers can access the coerced parameters via the :parameters key in the request.

juhoteperi12:12:28

The main Coercion page doesn't mention this, because this is Ring specific detail

Yevgeni Tsodikov16:12:08

What do I need to change to add a custom transformer? (A custom decoder with an :enter function) Is it the :transformers :body formats ?

juhoteperi10:12:49

You probably don't need customer tranformers. You can add custom decode fns to ~any schema: [:uuid {:decode/string (fn [s] (UUID. (str "foo" s)))}] (or :decode/json if this decoding is required for values from JSON).