Skip to content

Instantly share code, notes, and snippets.

@RickMoynihan
Created June 11, 2016 12:37
Show Gist options
  • Save RickMoynihan/d8024bb9dd00c34235cf5cd9c561125a to your computer and use it in GitHub Desktop.
Save RickMoynihan/d8024bb9dd00c34235cf5cd9c561125a to your computer and use it in GitHub Desktop.
(ns specing.uri
(:require [clojure.spec :as s]))
;; crude specing of URI/URL objects - rules are actually more complex & nuanced
;; than this ... just experimenting with clojure.spec rather than adding it for
;; real... though when I do it will probably be in grafter.url / core.rdf
(def domain? string?)
(s/def ::scheme #{"http" "https" "urn"})
(s/def ::domain (s/+ domain?))
(s/def ::authority (s/+ ::domain))
(s/def ::port integer?)
(s/def ::hier-part (s/cat :authority ::authority
:port (s/? ::port)))
(s/def ::path-segment string?)
(s/def ::path (s/+ ::path-segment))
(def query-key? string?)
(def query-val? string?)
(s/def ::query (s/and
#(<= 1 (count %))
(s/map-of query-key? query-val?)))
(s/def ::fragment string?)
(s/def ::uri (s/keys :req [::scheme ::hier-part]
:opt [::path ::query ::fragment]))
(comment
(def valid-uri {::scheme "http" ::hier-part ["blog" "swirrl" "com"] ::path ["articles" "new-speakers-data-driven-decisions-event"]} )
(s/valid? ::uri valid-uri)
;; => true
(s/conform ::uri valid-uri)
;;=>
'{:specing.uri/scheme "http",
:specing.uri/hier-part {:authority [["blog" "swirrl" "com"]]},
:specing.uri/path ["articles" "new-speakers-data-driven-decisions-event"]}
(let [valid-uri-with-port (update valid-uri ::hier-part #(conj % 8080))]
(s/conform ::uri valid-uri-with-port))
;; =>
'{:specing.uri/scheme "http",
:specing.uri/hier-part {:authority [["blog" "swirrl" "com"]], :port 8080},
:specing.uri/path ["articles" "new-speakers-data-driven-decisions-event"]}
(let [invalid-url (dissoc valid-uri ::scheme)]
(s/explain-data ::uri invalid-url))
;; =>
'{:clojure.spec/problems
{[]
{:pred [(contains? % :specing.uri/scheme)],
:val
{:specing.uri/hier-part ["blog" "swirrl" "com"],
:specing.uri/path ["articles" "new-speakers-data-driven-decisions-event"]},
:via [:specing.uri/uri],
:in []}}}
)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment