Check 'POST /items' payload is application/json

This commit adds a middleware function that checks any POST endpoint is
called with Content-Type: application/json. Returns `HTTP 415
Unsupported Media Type` if this is not the case.

TODO: this commit does not check that the payload is actually
well-formed JSON. If the payload is *not* valid JSON, muutaja will fail,
which will result in an `HTTP 500 Server error`.
This commit is contained in:
2026-01-30 18:25:31 +01:00
parent c278633c66
commit b9ae9a8b56

View File

@@ -6,6 +6,8 @@
(:gen-class)) (:gen-class))
;; Handlers -------------------------------------------------------
(defn ahoy-handler (defn ahoy-handler
[_] [_]
{:status 200 {:status 200
@@ -29,6 +31,22 @@
:body {:id id, :name name, :email email}})) :body {:id id, :name name, :email email}}))
;; Custom middleware ----------------------------------------------
(defn wrap-content-type-json
"Middleware that checks is a POST request is bring sent data as JSON"
[handler]
(fn [request]
(let [http-verb (:request-method request)
is-post? (= :post http-verb)
content-type (get-in request [:headers "content-type"])
is-json? (= "application/json" content-type)]
(cond (not is-post?) (handler request)
(and is-post? is-json?) (handler request)
:else {:status 415
:body {:error "Unsupported Media Type"
:message "Content-Type must be application/json"}}))))
;; Routing --------------------------------------------------------
(def app (def app
(ring/ring-handler (ring/ring-handler
(ring/router (ring/router
@@ -37,13 +55,15 @@
:post post-items-handler}]] :post post-items-handler}]]
;; Use muuntaja middleware to automatically decode JSON ;; Use muuntaja middleware to automatically decode JSON
{:data {:muuntaja m/instance {:data {:muuntaja m/instance
:middleware [muuntaja/format-middleware]}}) :middleware [wrap-content-type-json
muuntaja/format-middleware]}})
;; Default route: anything not explicitely handled should give a 404 ;; Default route: anything not explicitely handled should give a 404
(ring/create-default-handler (ring/create-default-handler
{:not-found (constantly {:status 404 {:not-found (constantly {:status 404
:body {:error "Not Found"}})}))) :body {:error "Not Found"}})})))
;; Entry point ----------------------------------------------------
(defn -main (defn -main
"HolidayPirates take-home assignement. "HolidayPirates take-home assignement.
Goal: build a (very) small REST API that exposes to endpoints." Goal: build a (very) small REST API that exposes to endpoints."