Question

Suppose I have this handler:

(defroutes routes
  (DELETE    "/books"      [id]              (delete-book id)))

What can I do to make this app return HTTP 404 when request does not contain ID?

Was it helpful?

Solution

Firstly, you could make the id a part of the URI, which seems nice and RESTful and would allow you to use the route syntax to impose your condition:

(GET ["/books/:id" :id #"[0-9]+"] [] ...)

If you do prefer to use a parameter, something like

(if-not id
  (ring.util.response/not-found body-for-404)
  ...)

should work in the next Ring version, though this particular function has not been released yet (it simply returns {:status 404 :headers {} :body the-body} though).

Also,

(when id
  ...)

would result in the equivalent of a route match failure and the remaining routes would be tried; then you could use

(compojure.route/not-found body-for-404)

as the final route which would always match.

Finally, if you wish to apply filtering to a large group of Compojure handlers, you may wish to combine them into a single handler with Compojure's defroutes or routes (the latter is a function) and wrapping them in a piece of middleware:

(defn wrap-404 [handler]
  (fn wrap-404 [request]
    (when (-> request :params :id)
      (handler request))))

You can then include the wrapped handler as an entry in routes / defroutes forms.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top