Fork me on GitHub
#malli
<
2023-02-11
>
Varghiz clj14:02:13

Hi, We've a use case where we need to apply schema validation on the body based on the type value in the header. For example if the type is foo then should apply schema/foo . If the type is bar then should apply schema/bar.. dynamically

Ben Sless14:02:21

You can always add a middleware which adds it to the body from header before coercion

Varghiz clj14:02:03

Thank you @UK0810AQ2..I'm new to malli & reitit, can you please give me a reference or sample on middleware

Ben Sless14:02:42

You're using malli in http, are you using it with reitit?

Varghiz clj14:02:14

I use malli for schema validation and reitit.swagger for API definition and routes.

Ben Sless15:02:21

How does your ring handler look like?

Varghiz clj15:02:08

["/dosomething"
    {:swagger {:tags ["do something"]}
     :post    {:summary    "route the call after validating the payload based on foo or bar"
               :scope      [:api:write]
               :parameters {:header [:map
                                     [:authorization schema/authorization]
                                     [:type schema/type-header]]          ;; foo or bar
                            :body [:map
                                   [:events schema/general-body]]}        ;; this is the part we need to call schema/foo or schema/bar based on type
               :handler    (h/process-api config)}}]

Varghiz clj15:02:59

the part events is a generic such that based on the type, we will apply one schema vs the other

Ben Sless15:02:39

That's not the ring handler, just reitit routes

Varghiz clj15:02:31

(defn process-api [config]
  (fn [{{:keys [header body]} :parameters}]
    (let [events (body :events)
          total  (count events)]
      (let [results    (k/send-events config events header)
            successful (count (remove :error results))]
        {:status (cond
                   (zero? successful) 400
                   (= total successful) 200
                   :else 206)
         :body   {:events results}}))))

Ben Sless16:02:35

You should share your entire code, what about reitit.ring/ring-handler

Varghiz clj17:02:27

@UK0810AQ2, Thank you for your advice.. I resolved it.. this is what I did..

(defn process-api [config]
  (fn [{{:keys [header body]} :parameters}]
    (if-let [errors (m/explain i/custom-schema body)] ;; the additional validations
	   {:error 400
	    :body (-> errors m/humanize...)}
	   (let [events (body :events)
	         total  (count events)]
	      (let [results    (k/send-events config events header)
	            successful (count (remove :error results))]
	        {:status (cond
	                   (zero? successful) 400
	                   (= total successful) 200
	                   :else 206)
	         :body   {:events results}}))))) 

Ben Sless18:02:20

This is the very much not what I suggested You should build a full reitit ring handler like in the examples in the reitit repo, then add a middleware to add the parameter from the header to the body