UNPKG

18 kBMarkdownView Raw
1# express-validator
2
3[![npm version](https://img.shields.io/npm/v/express-validator.svg)](https://www.npmjs.com/package/express-validator)
4[![Build Status](https://img.shields.io/travis/ctavan/express-validator.svg)](http://travis-ci.org/ctavan/express-validator)
5[![Dependency Status](https://img.shields.io/david/ctavan/express-validator.svg)](https://david-dm.org/ctavan/express-validator)
6[![Coverage Status](https://img.shields.io/coveralls/ctavan/express-validator.svg)](https://coveralls.io/github/ctavan/express-validator?branch=master)
7
8An [express.js]( https://github.com/visionmedia/express ) middleware for
9[node-validator]( https://github.com/chriso/validator.js ).
10
11- [Installation](#installation)
12- [Usage](#usage)
13- [Middleware options](#middleware-options)
14- [Validation](#validation)
15- [Validation by schema](#validation-by-schema)
16- [Validation result](#validation-result)
17 + [Result API](#result-api)
18 + [Deprecated API](#deprecated-api)
19 + [String formatting for error messages](#string-formatting-for-error-messages)
20 + [Per-validation messages](#per-validation-messages)
21- [Optional input](#optional-input)
22- [Sanitizer](#sanitizer)
23- [Regex routes](#regex-routes)
24- [TypeScript](#typescript)
25- [Changelog](#changelog)
26- [License](#license)
27
28## Installation
29
30```
31npm install express-validator
32```
33
34## Usage
35
36```javascript
37var util = require('util'),
38 bodyParser = require('body-parser'),
39 express = require('express'),
40 expressValidator = require('express-validator'),
41 app = express();
42
43app.use(bodyParser.json());
44app.use(expressValidator([options])); // this line must be immediately after any of the bodyParser middlewares!
45
46app.post('/:urlparam', function(req, res) {
47
48 // VALIDATION
49 // checkBody only checks req.body; none of the other req parameters
50 // Similarly checkParams only checks in req.params (URL params) and
51 // checkQuery only checks req.query (GET params).
52 req.checkBody('postparam', 'Invalid postparam').notEmpty().isInt();
53 req.checkParams('urlparam', 'Invalid urlparam').isAlpha();
54 req.checkQuery('getparam', 'Invalid getparam').isInt();
55
56 // OR assert can be used to check on all 3 types of params.
57 // req.assert('postparam', 'Invalid postparam').notEmpty().isInt();
58 // req.assert('urlparam', 'Invalid urlparam').isAlpha();
59 // req.assert('getparam', 'Invalid getparam').isInt();
60
61 // SANITIZATION
62 // as with validation these will only validate the corresponding
63 // request object
64 req.sanitizeBody('postparam').toBoolean();
65 req.sanitizeParams('urlparam').toBoolean();
66 req.sanitizeQuery('getparam').toBoolean();
67
68 // OR find the relevent param in all areas
69 req.sanitize('postparam').toBoolean();
70
71 // Alternatively use `var result = yield req.getValidationResult();`
72 // when using generators e.g. with co-express
73 req.getValidationResult().then(function(result) {
74 if (!result.isEmpty()) {
75 res.send('There have been validation errors: ' + util.inspect(result.array()), 400);
76 return;
77 }
78 res.json({
79 urlparam: req.params.urlparam,
80 getparam: req.params.getparam,
81 postparam: req.params.postparam
82 });
83 });
84});
85
86app.listen(8888);
87```
88
89Which will result in:
90
91```
92$ curl -d 'postparam=1' http://localhost:8888/test?getparam=1
93{"urlparam":"test","getparam":"1","postparam":true}
94
95$ curl -d 'postparam=1' http://localhost:8888/t1est?getparam=1
96There have been validation errors: [
97 { param: 'urlparam', msg: 'Invalid urlparam', value: 't1est' } ]
98
99$ curl -d 'postparam=1' http://localhost:8888/t1est?getparam=1ab
100There have been validation errors: [
101 { param: 'getparam', msg: 'Invalid getparam', value: '1ab' },
102 { param: 'urlparam', msg: 'Invalid urlparam', value: 't1est' } ]
103
104$ curl http://localhost:8888/test?getparam=1&postparam=1
105There have been validation errors: [
106 { param: 'postparam', msg: 'Invalid postparam', value: undefined} ]
107```
108
109## Middleware Options
110#### `errorFormatter`
111_function(param,msg,value)_
112
113The `errorFormatter` option can be used to specify a function that must build the error objects used in the validation result returned by `req.getValidationResult()`.<br>
114It should return an `Object` that has `param`, `msg`, and `value` keys defined.
115
116```javascript
117// In this example, the formParam value is going to get morphed into form body format useful for printing.
118app.use(expressValidator({
119 errorFormatter: function(param, msg, value) {
120 var namespace = param.split('.')
121 , root = namespace.shift()
122 , formParam = root;
123
124 while(namespace.length) {
125 formParam += '[' + namespace.shift() + ']';
126 }
127 return {
128 param : formParam,
129 msg : msg,
130 value : value
131 };
132 }
133}));
134```
135
136####`customValidators`
137_{ "validatorName": function(value, [additional arguments]), ... }_
138
139
140The `customValidators` option can be used to add additional validation methods as needed. This option should be an `Object` defining the validator names and associated validation functions.
141
142Define your custom validators:
143
144```javascript
145app.use(expressValidator({
146 customValidators: {
147 isArray: function(value) {
148 return Array.isArray(value);
149 },
150 gte: function(param, num) {
151 return param >= num;
152 }
153 }
154}));
155```
156Use them with their validator name:
157```javascript
158req.checkBody('users', 'Users must be an array').isArray();
159req.checkQuery('time', 'Time must be an integer great than or equal to 5').isInt().gte(5)
160```
161####`customSanitizers`
162_{ "sanitizerName": function(value, [additional arguments]), ... }_
163
164The `customSanitizers` option can be used to add additional sanitizers methods as needed. This option should be an `Object` defining the sanitizer names and associated functions.
165
166Define your custom sanitizers:
167
168```javascript
169app.use(expressValidator({
170 customSanitizers: {
171 toSanitizeSomehow: function(value) {
172 var newValue = value;//some operations
173 return newValue;
174 },
175 }
176}));
177```
178Use them with their sanitizer name:
179```javascript
180req.sanitize('address').toSanitizeSomehow();
181```
182
183## Validation
184
185#### req.check();
186```javascript
187 req.check('testparam', 'Error Message').notEmpty().isInt();
188 req.check('testparam.child', 'Error Message').isInt(); // find nested params
189 req.check(['testparam', 'child'], 'Error Message').isInt(); // find nested params
190```
191
192Starts the validation of the specifed parameter, will look for the parameter in `req` in the order `params`, `query`, `body`, then validate, you can use 'dot-notation' or an array to access nested values.
193
194If a validator takes in params, you would call it like `req.assert('reqParam').contains('thisString');`.
195
196Validators are appended and can be chained. See [chriso/validator.js](https://github.com/chriso/validator.js) for available validators, or [add your own](#customvalidators).
197
198#### req.assert();
199Alias for [req.check()](#reqcheck).
200
201#### req.validate();
202Alias for [req.check()](#reqcheck).
203
204#### req.checkBody();
205Same as [req.check()](#reqcheck), but only looks in `req.body`.
206
207#### req.checkQuery();
208Same as [req.check()](#reqcheck), but only looks in `req.query`.
209
210#### req.checkParams();
211Same as [req.check()](#reqcheck), but only looks in `req.params`.
212
213#### req.checkHeaders();
214Only checks `req.headers`. This method is not covered by the general `req.check()`.
215
216#### req.checkCookies();
217Only checks `req.cookies`. This method is not covered by the general `req.check()`.
218
219## Validation by Schema
220
221Alternatively you can define all your validations at once using a simple schema.
222Schema validation will be used if you pass an object to any of the validator methods.
223
224You may pass per-validator error messages with the `errorMessage` key.
225Validator options may be passed via `options` key as an array when various values are needed,
226or as a single non-null value otherwise.
227
228```javascript
229req.checkBody({
230 'email': {
231 optional: {
232 options: { checkFalsy: true } // or: [{ checkFalsy: true }]
233 },
234 isEmail: {
235 errorMessage: 'Invalid Email'
236 }
237 },
238 'password': {
239 notEmpty: true,
240 matches: {
241 options: ['example', 'i'] // pass options to the validator with the options property as an array
242 // options: [/example/i] // matches also accepts the full expression in the first parameter
243 },
244 errorMessage: 'Invalid Password' // Error message for the parameter
245 },
246 'name.first': { //
247 optional: true, // won't validate if field is empty
248 isLength: {
249 options: [{ min: 2, max: 10 }],
250 errorMessage: 'Must be between 2 and 10 chars long' // Error message for the validator, takes precedent over parameter message
251 },
252 errorMessage: 'Invalid First Name'
253 }
254});
255```
256
257You can also define a specific location to validate against in the schema by adding `in` parameter as shown below:
258
259```javascript
260req.check({
261 'email': {
262 in: 'query',
263 notEmpty: true,
264 isEmail: {
265 errorMessage: 'Invalid Email'
266 }
267 }
268});
269```
270
271Please remember that the `in` attribute will have always highest priority. This mean if you use `in: 'query'` then checkQuery() will be called inside even if you do `checkParams()` or `checkBody()`. For example, all of these calls will check query params for email param:
272
273
274```javascript
275var schema = {
276 'email': {
277 in: 'query',
278 notEmpty: true,
279 isEmail: {
280 errorMessage: 'Invalid Email'
281 }
282 },
283 'password': {
284 notEmpty: true,
285 matches: {
286 options: ['example', 'i'] // pass options to the validator with the options property as an array
287 // options: [/example/i] // matches also accepts the full expression in the first parameter
288 },
289 errorMessage: 'Invalid Password' // Error message for the parameter
290 }
291};
292
293req.check(schema); // will check 'password' no matter where it is but 'email' in query params
294req.checkQuery(schema); // will check 'password' and 'email' in query params
295req.checkBody(schema); // will check 'password' in body but 'email' in query params
296req.checkParams(schema); // will check 'password' in path params but 'email' in query params
297req.checkHeaders(schema); // will check 'password' in headers but 'email' in query params
298```
299
300Currently supported location are `'body', 'params', 'query', 'headers'`. If you provide a location parameter that is not supported, the validation process for current parameter will be skipped.
301
302## Validation result
303
304### Result API
305The method `req.getValidationResult()` returns a Promise which resolves to a result object.
306
307```js
308req.assert('email', 'required').notEmpty();
309req.assert('email', 'valid email required').isEmail();
310req.assert('password', '6 to 20 characters required').len(6, 20);
311
312req.getValidationResult().then(function(result) {
313 // do something with the validation result
314});
315```
316
317The API for the result object is the following:
318
319#### `result.isEmpty()`
320Returns a boolean determining whether there were errors or not.
321
322#### `result.useFirstErrorOnly()`
323Sets the `firstErrorOnly` flag of this result object, which modifies the way
324other methods like `result.array()` and `result.mapped()` work.<br>
325
326This method is chainable, so the following is OK:
327
328```js
329result.useFirstErrorOnly().array();
330```
331
332#### `result.array()`
333Returns an array of errors.<br>
334All errors for all validated parameters will be included, unless you specify that you want only the first error of each param by invoking `result.useFirstErrorOnly()`.
335
336```javascript
337var errors = result.array();
338
339// errors will now contain something like this:
340[
341 {param: "email", msg: "required", value: "<received input>"},
342 {param: "email", msg: "valid email required", value: "<received input>"},
343 {param: "password", msg: "6 to 20 characters required", value: "<received input>"}
344]
345```
346
347#### `result.mapped()`
348Returns an object of errors, where the key is the parameter name, and the value is an error object as returned by the error formatter.
349
350Because of historical reasons, by default this method will return the last error of each parameter.<br>
351You can change this behavior by invoking `result.useFirstErrorOnly()`, so the first error is returned instead.
352
353```javascript
354var errors = result.mapped();
355
356// errors will now be similar to this:
357{
358 email: {
359 param: "email",
360 msg: "valid email required",
361 value: "<received input>"
362 },
363 password: {
364 param: "password",
365 msg: "6 to 20 characters required",
366 value: "<received input>"
367 }
368}
369```
370
371#### `result.throw()`
372If there are errors, throws an `Error` object which is decorated with the same API as the validation result object.<br>
373Useful for dealing with the validation errors in the `catch` block of a `try..catch` or promise.
374
375```js
376try {
377 result.throw();
378 res.send('success!');
379} catch (e) {
380 console.log(e.array());
381 res.send('oops, validation failed!');
382}
383```
384
385### Deprecated API
386The following methods are deprecated.<br>
387While they work, their API is unflexible and sometimes return weird results if compared to the bleeding edge `req.getValidationResult()`.
388
389Additionally, these methods may be removed in a future version.
390
391#### `req.validationErrors([mapped])`
392Returns synchronous errors in the form of an array, or an object that maps parameter to error in case `mapped` is passed as `true`.<br>
393If there are no errors, the returned value is `false`.
394
395```js
396var errors = req.validationErrors();
397if (errors) {
398 // do something with the errors
399}
400```
401
402#### `req.asyncValidationErrors([mapped])`
403Returns a promise that will either resolve if no validation errors happened, or reject with an errors array/mapping object. For reference on this, see `req.validationErrors()`.
404
405```js
406req.asyncValidationErrors().then(function() {
407 // all good here
408}, function(errors) {
409 // damn, validation errors!
410});
411```
412
413### String formatting for error messages
414
415Error messages can be customized to include both the value provided by the user, as well as the value of any parameters passed to the validation function, using a standard string replacement format:
416
417`%0` is replaced with user input
418`%1` is replaced with the first parameter to the validator
419`%2` is replaced with the second parameter to the validator
420etc...
421
422Example:
423```javascript
424req.assert('number', '%0 is not an integer').isInt();
425req.assert('number', '%0 is not divisible by %1').isDivisibleBy(5);
426```
427
428*Note:* string replacement does **not** work with the `.withMessage()` syntax. If you'd like to have per-validator error messages with string formatting, please use the [Validation by Schema](#validation-by-schema) method instead.
429
430### Per-validation messages
431
432You can provide an error message for a single validation with `.withMessage()`. This can be chained with the rest of your validation, and if you don't use it for one of the validations then it will fall back to the default.
433
434```javascript
435req.assert('email', 'Invalid email')
436 .notEmpty().withMessage('Email is required')
437 .isEmail();
438
439req.getValidationResult()
440 .then(function(result){
441 console.log(result.array());
442 });
443
444```
445
446prints:
447
448```javascript
449[
450 {param: 'email', msg: 'Email is required', value: '<received input>'}
451 {param: 'email', msg: 'Invalid Email', value: '<received input>'}
452]
453```
454
455## Optional input
456
457You can use the `optional()` method to skip validation. By default, it only skips validation if the key does not exist on the request object. If you want to skip validation based on the property being falsy (null, undefined, etc), you can pass in `{ checkFalsy: true }`.
458
459```javascript
460req.checkBody('email').optional().isEmail();
461//if there is no error, req.body.email is either undefined or a valid mail.
462```
463
464## Sanitizer
465
466#### req.sanitize();
467```javascript
468
469req.body.comment = 'a <span>comment</span>';
470req.body.username = ' a user ';
471
472req.sanitize('comment').escape(); // returns 'a &lt;span&gt;comment&lt;/span&gt;'
473req.sanitize('username').trim(); // returns 'a user'
474
475console.log(req.body.comment); // 'a &lt;span&gt;comment&lt;/span&gt;'
476console.log(req.body.username); // 'a user'
477
478```
479
480Sanitizes the specified parameter (using 'dot-notation' or array), the parameter will be updated to the sanitized result. Cannot be chained, and will return the result. See [chriso/validator.js](https://github.com/chriso/validator.js) for available sanitizers, or [add your own](#customsanitizers).
481
482If a sanitizer takes in params, you would call it like `req.sanitize('reqParam').whitelist(['a', 'b', 'c']);`.
483
484If the parameter is present in multiple places with the same name e.g. `req.params.comment` & `req.query.comment`, they will all be sanitized.
485
486#### req.filter();
487Alias for [req.sanitize()](#reqsanitize).
488
489#### req.sanitizeBody();
490Same as [req.sanitize()](#reqsanitize), but only looks in `req.body`.
491
492#### req.sanitizeQuery();
493Same as [req.sanitize()](#reqsanitize), but only looks in `req.query`.
494
495#### req.sanitizeParams();
496Same as [req.sanitize()](#reqsanitize), but only looks in `req.params`.
497
498#### req.sanitizeHeaders();
499Only sanitizes `req.headers`. This method is not covered by the general `req.sanitize()`.
500
501#### req.sanitizeCookies();
502Only sanitizes `req.cookies`. This method is not covered by the general `req.sanitize()`.
503
504## Regex routes
505
506Express allows you to define regex routes like:
507
508```javascript
509app.get(/\/test(\d+)/, function() {});
510```
511
512You can validate the extracted matches like this:
513
514```javascript
515req.assert(0, 'Not a three-digit integer.').len(3, 3).isInt();
516```
517
518## TypeScript
519If you have been using this library with [TypeScript](http://www.typescriptlang.org/),
520you must have been using the type definitions from [DefinitelyTyped](https://github.com/DefinitelyTyped/DefinitelyTyped/blob/e2af6d0/express-validator/express-validator.d.ts).
521
522However, as of v3.1.0, the type definitions are shipped with the library.
523So please uninstall the typings from DT. Otherwise they may cause conflicts
524
525
526## Changelog
527
528Check the [GitHub Releases page](https://github.com/ctavan/express-validator/releases).
529
530## License
531
532Copyright (c) 2010 Chris O'Hara <cohara87@gmail.com>, MIT License