This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2022-02-28
Channels
- # announcements (14)
- # autochrome-github (1)
- # babashka (4)
- # beginners (151)
- # biff (1)
- # calva (24)
- # cider (13)
- # clara (13)
- # clj-commons (1)
- # cljs-dev (24)
- # clojure (50)
- # clojure-europe (20)
- # clojure-france (13)
- # clojure-nl (4)
- # clojure-norway (12)
- # clojure-spec (43)
- # clojure-uk (6)
- # clojurescript (30)
- # cursive (2)
- # datahike (9)
- # editors (6)
- # emacs (2)
- # fulcro (29)
- # google-cloud (20)
- # graphql (2)
- # humbleui (2)
- # jobs (2)
- # juxt (4)
- # kaocha (5)
- # lsp (14)
- # malli (5)
- # membrane (10)
- # off-topic (39)
- # pathom (21)
- # polylith (10)
- # rdf (8)
- # reagent (4)
- # remote-jobs (3)
- # reveal (18)
- # shadow-cljs (27)
- # spacemacs (7)
- # tools-deps (30)
So here we have :req and :opt to be used in s/keys. That doesn’t stop other keys tht are not listed in opt or req from being accepted right? How do you limit the keys that can be accepted to only the req and opt keys?
that's deliberately not supported by spec. use select-keys
or similar.
why this design decision?
the focus was on enforcing minimum needs.
spec 2 does allow for this, because there are legitimate use cases for it. and the implicit checking of bonus keys with their own specs can be a DoS attack vector, if those other keys have slow specs.
worse, since it's extra data getting validated, you can send perfectly valid requests that take tens of seconds or more to validate, but don't stand out in monitoring or logs as errors or unusually large...
what’s the solution to the dos attack when comprehensively validating the input
https://github.com/clojure/spec-alpha2/wiki/Differences-from-spec.alpha#closed-spec-checking here's the spec 2 docs.
so we should use spec2 right?
well, perhaps not. it's still alpha. just mentioning it.
isn’t spec alpha too?
I'd say the most straightforward thing is to just select-keys
first, then validate with spec 1.
sure, but it's been battle tested in a way the spec 2 hasn't.
spec 2 has not been released, and you shouldn't use it for real stuff
Stating the obvious, but you can always use a custom predicate to limit the spec in addition to s/keys
Let’s say I’m trying to conform a map to a spec. I want each key of the map to have values of a certain type. How can I write a spec for that?
I have this:
(s/def ::create-sessions-params (s/and (s/keys :opt-un [::students ::start_date ::start_time ::timezone ::instructor])))
but then for each key, I want to impose a type to the key’s value too
how will I do that?
@ghadi what would be the best way to restrict the keys to just the keys in the opt?
like it shouldn’t conform if there are keys other than the ones in the :opt-un list
opt-un or req-un or opt or req
can I use one of these libraries to achieve the effect rather than select keys: https://github.com/metosin/spec-tools https://github.com/wilkerlucio/spec-coerce
So would this be good?:
(defn keys-conform? [m k]
(every? (set k) (keys m)))
(def create-sessions-keys [::students ::start_date ::start_time ::timezone ::instructor])
(s/def ::create-sessions-params (s/and (s/keys :opt-un create-sessions-keys) #(keys-conform? % create-sessions-keys)))
keys-conform makes sure that the keys in the map are only the ones that are in the keys vector
s/keys
is a macro and cannot be passed a var like that, as I recall.
unfortunately, that won't work in s/keys
that should definitely be a feature in clojure spec
how come we can’t use variables in it
spec forms are macros and at compile time, we wouldn't know your runtime key set. other choices have been made for spec 2. It is possible to retrieve the keys from the spec using specs on the spec forms themselves but it's pretty ugly to do so - most people end up just walking the form as data to do this
so you'd have to repeat the vector of keys there
btw, there is a faq entry about this here: https://clojure.org/guides/faq#exclusive_keys
What we do is get the spec form (via the Spec API) and lift the keys out of it to use in other contexts -- we treat the Spec itself as the "system of record".
@seancorfield can you please elaborate?