pedestal

Santiago 2020-03-23T17:18:31.046700Z

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 ?

Santiago 2020-03-24T08:04:55.047200Z

@ddeaguiar 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

Santiago 2020-03-24T08:07:40.047500Z

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?

mavbozo 2020-03-24T09:29:45.047800Z

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

Santiago 2020-03-24T16:58:56.055900Z

@mavbozo

(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)))

mavbozo 2020-03-24T20:31:31.056700Z

nothing's wrong in your code above.

mavbozo 2020-03-24T20:53:28.056900Z

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?

Santiago 2020-03-25T08:07:33.000100Z

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

mavbozo 2020-03-25T11:45:33.000300Z

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.

Santiago 2020-03-25T18:55:01.005300Z

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

mavbozo 2020-03-26T04:41:59.005500Z

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

2020-03-23T17:24:47.046800Z

Hi @slack.jcpsantiago, 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

Santiago 2020-03-23T17:26:32.047Z

nice thanks, I can work with this 😉