Fork me on GitHub
#pedestal
<
2020-03-23
>
Santiago17:03:31

I’m new to pedestal (new-ish to clojure). to create a 404 response when a route doesn’t exist like

{:body {:code 404
        :message "Not found"}
 :status 404}
I guess this is done as a interceptor, but what should I look for? Is this an :error ?

ddeaguiar17:03:47

Hi @UFPEDL1LY, If you include default-interceptors, there’s a default 404 interceptor provided. It can be overridden. Refer to http://pedestal.io/reference/default-interceptors and this response map footnote http://pedestal.io/reference/response-map#_footnotedef_1

Santiago17:03:32

nice thanks, I can work with this 😉

Santiago08:03:55

@U0FL657GR I was able to make the changes I wanted, but I don’t understand how to make the response JSON. Adding (update ::server/interceptors conj server/json-body) after

(-> service-map
    default-interceptors
    <line above>
    create-server
    start)
converts good responses to JSON, but not the 404 responses. I added this ::http/not-found-interceptor my-not-found to my service-map

Santiago08:03:40

so it responds with 404 in the correct format, but as EDN, not JSON:

{:code 404, :message "Not Found :("}
I guess because the JSON interceptor is before the not-found?

mavbozo09:03:45

What is the code for your my-not-found interceptor?

Santiago16:03:56

@U075CCMPY

(def my-not-found
  "An interceptor that returns a 404 when routing failed to resolve a route."
  (interceptor/after
    ::not-found
    (fn [context]
      (if-not (http/response? (:response context))
        (do (log/meter ::not-found)
          (assoc context :response (not-found "Not Found :(")))
        context))))
and this is not-found
(defn bad-body
  [code message]
  {:code code 
   :message message})

(def not-found
  "Returns a fn that creates a response map with status 404"
  (comp ring-resp/not-found (partial bad-body 404)))

mavbozo20:03:31

nothing's wrong in your code above.

mavbozo20:03:28

Your initial guess might be right, the chain of interceptors for your app looks like this [... my-not-found .. routes ... json-body] so, if the interceptor can not found any route, the execution goes back through :leave stages without entering json-body. But, I'm curious about good responses returning JSON, do you use any special functions to generate JSON for good responses?

Santiago08:03:33

@U075CCMPY no, I use the json-body interceptor packaged with pedestal, nothing special

mavbozo11:03:33

so, I've just tried it myself. I'm not so sure about the execution flow of interceptors I describe above. But, here's what I know so far: the chain of interceptors is like this (with irrelevant parts omitted) [... my-not-found .. routes ... json-body] for successful responses, the flow goes through :enter stages, passing routes then passing`json-body` then goes back through :leave stages then we get the http response. for 404 response because of route not found, the flow goes through routes, but the :response is nil , that's why the json-body doesn't do anything. Then, the execution goes through :leave stages, passing my-not-found , then my-not-found created your 404 custom response. but since no json-body before my-not-found , the custom 404 response is not transformed to json.

Santiago18:03:01

so a way around this would be to create the 404 body in case of a nil response?

mavbozo04:03:59

or your could modify your custom 404 by creating the json string yourself and put it in to the body also put application/json as content type in headers