I wrote a custom safe-response-middleware (see code below) to replace coerce-response-middleware. It validates responses against the Reitit schema, logs errors, and returns the original response instead of a Reitit error response.
(defn safe-response-middleware
"Middleware that tries to coerce the response but logs and returns
the original data if mismatch occurs."
[handler]
(fn [request]
(let [response (handler request)
status (or (:status response) 200)
route (:reitit.core/match request)
route-data (:data route)
method-key (keyword (-> request
:request-method
name))
method-data (get route-data method-key)
route-responses (:responses method-data)
response-schema (get-in route-responses [status :body])]
(if (nil? response-schema)
response
(try
(let [coercers (coercion/response-coercers
rcm/coercion
{status {:body response-schema}}
{})]
(coercion/coerce-response coercers request response))
(catch Exception e
(let [data (ex-data e)
encoded-error (coercion/encode-error data)
humanized (:humanized encoded-error)]
(log/error-with-stacktrace e "Reitit response schema validation failed " humanized)
(if (utils/in-prod?)
response
{:status 200 :body humanized}))))))))
I’m wondering if there is a built-in way in Reitit (or its coercion library) to automatically remove invalid parts of a response instead of failing validation entirely.