Skip to content

Instantly share code, notes, and snippets.

@joinr
Created August 18, 2018 10:50
Show Gist options
  • Save joinr/39b38ba8ea2bc908050aafa86b84e7be to your computer and use it in GitHub Desktop.
Save joinr/39b38ba8ea2bc908050aafa86b84e7be to your computer and use it in GitHub Desktop.
example of using spec to truncate keys....
;;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