-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathvalidator.html
More file actions
117 lines (114 loc) · 9.78 KB
/
Copy pathvalidator.html
File metadata and controls
117 lines (114 loc) · 9.78 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
<!DOCTYPE html>
<html lang="en" dir="ltr">
<head>
<title>Coast on Clojure</title>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<link href="/favicon.png" rel="icon" type="image/png">
<link rel="stylesheet" href="/bundle--6885699.css" />
</head>
<body>
<nav class="dt w-100 border-box pa3 ph5-ns">
<a class="dtc v-mid near-black link dim w-25" href="/" title="Home">
<img alt="Coast on Clojure" class="dib w2 h2 br-100" src="/favicon.png">
<span class="ml2 v-top mt2 dib near-black">Coast</span>
</a>
<div class="dtc v-mid w-75 tr">
<a class="link dim near-black f6 f5-ns dib mr3 mr4-ns" href="/docs" title="Docs">Docs</a>
<a class="link dim near-black f6 f5-ns dib mr3 mr4-ns" href="https://twitter.com/coastonclojure" title="Twitter">Twitter</a>
<a class="link dim near-black f6 f5-ns dib" href="https://github.com/coast-framework/coast" title="Github">Github</a>
</div>
</nav>
<div class="grid bg-nearest-white">
<div class="pa4 bg-nearest-white sidebar-container">
<div class="fr-l sidebar">
<h3 id="user-content-preface">Preface</h3>
<ul>
<li><a href="/docs/about">About</a></li>
<li><a href="/docs/credits">Credits</a></li>
<li><a href="/docs/upgrading">Upgrading from eta</a></li>
<li><a href="/docs/contribution">Contribution Guide</a></li>
</ul>
<h3 id="user-content-concept">Concept</h3>
<ul>
<li><a href="/docs/request-lifecycle">Request Lifecycle</a></li>
</ul>
<h3 id="user-content-getting-started">Getting Started</h3>
<ul>
<li><a href="/docs/installation">Installation</a></li>
<li><a href="/docs/configuration">Configuration</a></li>
<li><a href="/docs/directory-structure">Directory Structure</a></li>
</ul>
<h3 id="user-content-database">Database</h3>
<ul>
<li><a href="/docs/database-getting-started">Getting Started</a></li>
<li><a href="/docs/queries">Queries</a></li>
<li><a href="/docs/migrations">Migrations</a></li>
<li><a href="/docs/relationships">Relationships</a></li>
<li><a href="/docs/pull">Pull</a></li>
</ul>
<h3 id="user-content-basics">Basics</h3>
<ul>
<li><a href="/docs/routing">Routing</a></li>
<li><a href="/docs/middleware">Middleware</a></li>
<li><a href="/docs/handlers">Handlers</a></li>
<li><a href="/docs/request">Request</a></li>
<li><a href="/docs/response">Response</a></li>
<li><a href="/docs/views">Views</a></li>
<li><a href="/docs/sessions">Sessions</a></li>
<li><a href="/docs/validator">Validator</a></li>
<li><a href="/docs/error-handling">Error Handling</a></li>
<li><a href="/docs/logger">Logger</a></li>
</ul>
<h3 id="user-content-security">Security</h3>
<ul>
<li><a href="/docs/security-intro">Introduction</a></li>
<li><a href="/docs/authentication">Authentication</a></li>
<li><a href="/docs/csrf-protection">CSRF Protection</a></li>
<li><a href="/docs/password-hashing">Password Hashing</a></li>
<li><a href="/docs/security-outro">XSS, Sniffing, XFrame</a></li>
</ul>
<h3 id="user-content-miscellaneous">Miscellaneous</h3>
<ul>
<li><a href="/docs/older-versions">Older Versions</a></li>
</ul>
</div>
</div>
<div class="ph4 bg-white content">
<h1 id="user-content-validator">Validator</h1><ul><li><a href='#user-content-validating-input'>Validating Input</a></li><li><a href='#user-content-common-rules'>Common Rules</a></li></ul><p>Coast makes it simple to validate input with the help of a validate function.</p><p>In this guide you learn how to validate data <em>manually</em>.</p><p class="note">NOTE: Coast validation uses <a href='https://github.com/jkk/verily'>verily</a> under the hood. For full usage details, see the official verily <a href='https://github.com/jkk/verily'>documentation</a>.</p><h2 id="user-content-validating-input">Validating Input</h2><p>Let's start with the example of validating input received via HTML form:</p><p>Make the routes to show the form and handle the submission:</p><pre><code class="clojure">; src/routes.clj
(def routes
(coast/site
[:get "/posts/:post-id/edit" :post/edit]
[:put "/posts/:post-id" :post/change]
[:get "/posts/:post-id" :post/view])))
</code></pre><p>Make the handler functions to show the form</p><pre><code class="clojure">; src/customer.clj
(defn edit [{:keys [params errors]}]
[:div
(when (some? errors)
[:div
[:div (:customer/email errors)]])
(coast/form-for ::change {:customer/id (:customer/id params)}
[:input {:type "text" :name "customer/email"}]
[:button {:type "submit"} "Submit"])])
</code></pre><p>...handle the form submission and use the validator to validate the data:</p><pre><code class="clojure">; src/customer.clj
(defn change [{:keys [params]}]
(let [[_ errors] (-> (select-keys params [:customer/id :customer/email])
(coast/validate [[:email [:customer/email]]])
(coast/rescue))]
(if (nil? errors)
(coast/redirect-to ::view {:customer/id (:customer/id request)})
(edit (merge request errors)))))
</code></pre><p>Let's break down the above code into small steps:</p><ol><li>We <a href='https://clojure.org/guides/destructuring'>destructured</a> the request map into a params variable</li><li>We used the <code>validate</code> method to validate the params data against an <code>:email</code> rule</li><li>If validation fails, the form re-renders with any errors</li><li>If it succeeds, it redirects to the <code>::view</code> handler</li></ol><h2 id="user-content-common-rules">Common Rules</h2><p>Below is the list of available, built in validator rules</p><ul><li>:required <keys> [msg] - must not be absent, blank, or nil</li><li>:contains <keys> [msg] - must not be absent, but can be blank or nil</li><li>:not-blank <keys> [msg] - may be absent but not blank or nil</li><li>:exact <value> <keys> [msg] - must be a particular value</li><li>:equal <keys> [msg] - all keys must be equal</li><li>:email <keys> [msg] - must be a valid email</li><li>:url <keys> [msg] - must be a valid URL</li><li>:web-url <keys> [msg] - must be a valid website URL (http or https)</li><li>:link-url <keys> [msg] - must be a valid link URL (can be relative, http: or https: may be omitted)</li><li>:matches <regex> <keys> [msg] - must match a regular expression</li><li>:min-length <len> <keys> [msg] - must be a certain length (for strings or collections)</li><li>:max-length <len> <keys> [msg] - must not exceed a certain length (for strings or collections)</li><li>:complete <keys> [msg] - must be a collection with no blank or nil values</li><li>:min-val <min> <keys> [msg] - must be at least a certain value</li><li>:max-val <max> <keys> [msg] - must be at most a certain value</li><li>:within <min> <max> <keys> [msg] - must be within a certain range (inclusive)</li><li>:positive <keys> [msg] - must be a positive number</li><li>:negative <keys> [msg] - must be a negative number</li><li>:after <date> <keys> [msg] - must be after a certain date</li><li>:before <date> <keys> [msg] - must be before a certain date</li><li>:in <coll> <keys> [msg] - must be contained within a collection</li><li>:every-in <coll> <keys> [msg] - each value must be within a collection (for values that are themselves collections)</li><li>:us-zip <keys> [msg] - must be a valid US zip code</li><li>:luhn <keys> [msg] - must be pass the Luhn check (e.g., for credit card numbers)</li><li>Datatype validations: :string, :boolean, :integer, :float, :decimal, :date (plus aliases)</li><li>Datatype collection validations: :strings, :booleans, :integers, :floats, :decimals, :dates (plus aliases)</li></ul><h4 id="user-content-<code>(validate-map-rules)</code>"><code>(validate map rules)</code></h4><p>Validate required keys and one email key:</p><pre><code class="clojure">(coast/validate {:customer/id 123
:customer/email "sean@example.com"} [[:required [:customer/id :customer/email]]
[:email [:customer/email]]])
</code></pre><p class="note">NOTE: You can optionally pass custom error messages to return when your validation fails as the third value in each vector:</p><pre><code class="clojure">(coast/validate {} [[:required [:customer/id] "can't be blank"]
[:email [:customer/email] "needs to be an actual email"]])
</code></pre><p>The exception that is raised from the above failed <code>(coast/validate)</code> validation looks like this:</p><pre><code class="clojure">{:customer/email "Email needs to be an actual email"
:customer/id "Id can't be blank"}
</code></pre>
</div>
</div>
<script type="text/javascript" src="/bundle-2017277981.js"></script>
<script>hljs.initHighlightingOnLoad();</script>
</body>
</html>