Created
August 18, 2018 10:50
-
-
Save joinr/39b38ba8ea2bc908050aafa86b84e7be to your computer and use it in GitHub Desktop.
example of using spec to truncate keys....
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
;;So for my incoming API boundary, I only would retain keys defined in | |
;;spec after receiving data from client (to wholesale limit potentially | |
;;dangerous crafting of json/edn payload). | |
;;Likewise, at my outgoing boundary, I would similarly only retain keys | |
;;defined in spec (sending absolute minimum data necessary). | |
(ns incoming | |
(:require [clojure.spec.alpha :as s])) | |
(def incoming-data {:a 1 :b "2" :c :not-good! :malicious "ohno!"}) | |
;;there are better ways to define this, like with metosin's spec-tools. | |
;;I'll hack around spec though... | |
(s/def :incoming/a int?) | |
(s/def :incoming/b string?) | |
(def expected #{:incoming/a | |
:incoming/b}) | |
(defn unqualify [xs] | |
(map #(keyword (name %)) xs)) | |
(defn unqualified-keys [xs] | |
(into (empty xs) (unqualify xs))) | |
(def unqualified-expected (unqualified-keys expected)) | |
(defn only-expected [m] | |
(select-keys m unqualified-expected)) | |
(s/def ::only-expected | |
(s/conformer only-expected)) | |
(s/def ::incoming | |
(s/and (s/keys :req-un [:incoming/a :incoming/b]) | |
::only-expected)) | |
;;maybe we transform the input spec, but only want to retain keys... | |
;;we need ns-qualified keywords for the :req-un in s/keys, but | |
;;we can makeup a fake ns and they won't get used for checking | |
;;the values associated with the fields. | |
(s/def ::outgoing | |
(s/and (s/keys :req-un [:doesntmatter/a :doesntmatter/b]) | |
::only-expected)) | |
;; incoming> (s/valid? ::incoming incoming-data) | |
;; true | |
;; incoming> (s/valid? ::outgoing incoming-data) | |
;; true | |
;; ;;::incoming expects :b to be string? | |
;; incoming> (s/valid? ::incoming (assoc incoming-data :b 2)) | |
;; false | |
;; ;;Outgoing only cares about the keys...not speccing the values. | |
;; incoming> (s/valid? ::outgoing (assoc incoming-data :b 2)) | |
;; true |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment