Add input validation
Input validation uses Malli coercion. Sadly enough, email is validated with a regexp.
This commit is contained in:
@@ -27,3 +27,5 @@ The following links proved more than useful when working on this assignment:
|
||||
|
||||
* <https://practical.li/clojure-web-services/building-api/>
|
||||
* <https://github.com/metosin/reitit/blob/master/doc/ring/content_negotiation.md>
|
||||
* <https://ostash.dev/posts/2021-08-22-data-validation-in-clojure/>
|
||||
* <https://clojurecivitas.github.io/malli/elements_of_malli.html>
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
[ring/ring-core "1.15.3"]
|
||||
[ring/ring-jetty-adapter "1.15.3"]
|
||||
[metosin/reitit "0.10.0"]
|
||||
[metosin/reitit-malli "0.10.0"]
|
||||
[metosin/muuntaja "0.6.11"]]
|
||||
:main ^:skip-aot yohoho.core
|
||||
:target-path "target/%s"
|
||||
|
||||
@@ -2,10 +2,26 @@
|
||||
(:require [reitit.ring :as ring]
|
||||
[ring.adapter.jetty :as http-server]
|
||||
[reitit.ring.middleware.muuntaja :as muuntaja]
|
||||
[muuntaja.core :as m])
|
||||
[muuntaja.core :as m]
|
||||
[reitit.coercion.malli :as malli]
|
||||
[reitit.ring.coercion :as coercion])
|
||||
(:gen-class))
|
||||
|
||||
|
||||
;; Data schema ----------------------------------------------------
|
||||
;; Malli schemas for validation
|
||||
|
||||
;; Validating an email address is hard.
|
||||
;; Regexp shamelessly taken from https://emailregex.com/
|
||||
(def email-regexp #"(?:[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*|\"(?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21\x23-\x5b\x5d-\x7f]|\\[\x01-\x09\x0b\x0c\x0e-\x7f])*\")@(?:(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?|\[(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?|[a-z0-9-]*[a-z0-9]:(?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21-\x5a\x53-\x7f]|\\[\x01-\x09\x0b\x0c\x0e-\x7f])+)\])")
|
||||
|
||||
(def Email [:re email-regexp])
|
||||
|
||||
(def Item
|
||||
[:map
|
||||
[:name :string]
|
||||
[:email Email]])
|
||||
|
||||
|
||||
;; Handlers -------------------------------------------------------
|
||||
(defn ahoy-handler
|
||||
@@ -52,11 +68,19 @@
|
||||
(ring/router
|
||||
[["/ahoy" {:get ahoy-handler}]
|
||||
["/items" {:get get-items-handler
|
||||
:post post-items-handler}]]
|
||||
;; Use muuntaja middleware to automatically decode JSON
|
||||
{:data {:muuntaja m/instance
|
||||
:post {:handler post-items-handler
|
||||
:parameters {:body Item}}}]]
|
||||
;; Middlewares:
|
||||
;; - wrap-content-type-json: ensure POST routes are sent JSON payload
|
||||
;; - muuntaja middleware to automatically decode JSON
|
||||
;; - malli + coercion: handle data validation
|
||||
{:data {:coercion malli/coercion
|
||||
:muuntaja m/instance
|
||||
:middleware [wrap-content-type-json
|
||||
muuntaja/format-middleware]}})
|
||||
muuntaja/format-middleware
|
||||
coercion/coerce-exceptions-middleware
|
||||
coercion/coerce-request-middleware
|
||||
coercion/coerce-response-middleware]}})
|
||||
;; Default route: anything not explicitely handled should give a 404
|
||||
(ring/create-default-handler
|
||||
{:not-found (constantly {:status 404
|
||||
|
||||
Reference in New Issue
Block a user