Fork me on GitHub
#reitit
<
2021-03-07
>
lispyclouds20:03:36

Hello! I'm using reitit with malli coercion and currently getting errors like this whenever coercion fails:

{
    "message": "Request coercion failed: #reitit.coercion.CoercionError{:schema [:map {:closed false} [:url string?]], :value {:invalid-key &quot;&quot;}, :errors (#Error{:path [:url], :in [:url], :schema [:map {:closed false} [:url string?]], :type :malli.core/missing-key}), :transformed {:invalid-key &quot;&quot;}}",
    "url": "/resource-providers/resource-git",
    "status": "500"
}
along with the status as 500 instead of 400 as I would like. This is my data config:
{:data {:coercion     malli/coercion
                         :muuntaja     m/instance
                         :interceptors [(parameters/parameters-interceptor)
                                        (muuntaja/format-negotiate-interceptor)
                                        (muuntaja/format-response-interceptor)
                                        (muuntaja/format-request-interceptor)
                                        (coercion/coerce-response-interceptor)
                                        (coercion/coerce-request-interceptor)
                                        (coercion/coerce-exceptions-interceptor)]}}
Is there a way to prettify/humanize these errors like the examples of spec on the site? and how do i make it return 400? Thanks! 😄

Matheus Moreira13:03:10

Hello. I have an app with a similar setup and I use an exception middleware; maybe that could help in your case:

(def exception-middleware
  (reitit.ring.middleware.exception/create-exception-middleware
    (merge
      reitit.ring.middleware.exception/default-handlers
      {:reitit.ring.middleware.exception/default default-exception-handler})))

:middleware [...
             muuntaja/format-negotiate-middleware
             muuntaja/format-response-middleware
             exception-middleware
             muuntaja/format-request-middleware
             ...]

Matheus Moreira13:03:48

Check the reitit.ring.middleware.exception/default-handlers to discover the keys you want to override. In my case it was the default-exception-handler because I wanted to add to the body of the response the exception’s message.

willier01:03:04

(malli/create {:error-keys #{:humanized}}) for the :coercion key above

willier01:03:06

instead of malli/coercion as u have

lispyclouds06:03:59

Hey @U440E3Q0K thanks, i tried this

(ns main
  (:require [muuntaja.core :as m]
            [reitit.ring :as ring]
            [reitit.http :as http]
            [reitit.coercion.malli :as malli]
            [reitit.http.coercion :as coercion]
            [reitit.http.interceptors.parameters :as parameters]
            [reitit.http.interceptors.muuntaja :as muuntaja]
            [reitit.interceptor.sieppari :as sieppari]
            [ring.adapter.jetty :as jetty]))

(def routes
  [["/add/{n1}/{n2}"
    {:get
     {:handler (fn [{{{:keys [n1 n2]} :path} :parameters}]
                {:status 200
                 :body   {:message (+ n1 n2)}})
      :parameters
      {:path
       [:map
        [:n1 int?]
        [:n2 int?]]}}}]])

(def server
  (http/ring-handler
    (http/router routes
                 {:data {:coercion     (malli/create {:error-keys #{:humanized}})
                         :muuntaja     m/instance
                         :interceptors [(parameters/parameters-interceptor)
                                        (muuntaja/format-negotiate-interceptor)
                                        (muuntaja/format-response-interceptor)
                                        (muuntaja/format-request-interceptor)
                                        (coercion/coerce-response-interceptor)
                                        (coercion/coerce-request-interceptor)]}})
    (ring/routes
      (ring/create-default-handler
        {:not-found (constantly {:status  404
                                 :headers {"Content-Type" "application/json"}
                                 :body    "{\"message\": \"Took a wrong turn?\"}"})}))
    {:executor sieppari/executor}))

(comment
  (def s
    (jetty/run-jetty (var server)
                     {:host   "0.0.0.0"
                      :port   7777
                      :join?  false
                      :async? true}))

  (.stop s))
still get
http  Accept:application/json
HTTP/1.1 500 Server Error
Cache-Control: must-revalidate,no-cache,no-store
Content-Length: 316
Content-Type: application/json
Server: Jetty(9.4.36.v20210114)

{
    "message": "Request coercion failed: #reitit.coercion.CoercionError{:schema [:map {:closed true} [:n1 int?] [:n2 int?]], :value {:n1 1, :n2 &quot;aa&quot;}, :errors (#Error{:path [:n2], :in [:n2], :schema int?, :value &quot;aa&quot;}), :transformed {:n1 1, :n2 &quot;aa&quot;}}",
    "status": "500",
    "url": "/add/1/aa"
}
Am i missing/using some interceptors wrongly?