Skip to content

Commit

Permalink
Implemented support for overriding Ajv configuration (#25)
Browse files Browse the repository at this point in the history
  • Loading branch information
kibertoad authored and naz committed Apr 3, 2019
1 parent 643ddb0 commit c443d9a
Show file tree
Hide file tree
Showing 5 changed files with 120 additions and 17 deletions.
9 changes: 8 additions & 1 deletion .eslintrc
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,14 @@
"mocha": true
},
"rules": {
"no-param-reassign": 0
"no-param-reassign": 0,
"comma-dangle": ["error", {
"arrays": "ignore",
"objects": "ignore",
"imports": "never",
"exports": "never",
"functions": "never"
}]
},
"settings": {
"import/resolve": {
Expand Down
20 changes: 20 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,25 @@ return server.listen(3000);

```

## Ajv configuration

`swagger-express-validator` uses Ajv for schema validation under the hood. You can tweak many validation parameters by passing Ajv configuration overrides:

```javascript
server.use(validator({
schema,
validateRequest: true,
validateResponse: true,
ajvRequestOptions: {
coerceTypes: true,
},
ajvResponseOptions: {
coerceTypes: true,
},
}));
```

See Ajv documentation for supported values.
## Debugging
To see debug output use `DEBUG=swagger-express-validator` as an environmental variable when starting
your project, eg.: `DEBUG=swagger-express-validator node server.js`. To gain more insights
Expand All @@ -74,6 +93,7 @@ on how this works see documentation of [debug](https://github.com/visionmedia/de
- [Nazar Gargol](https://github.com/gargol)
- [Isaac Stefanek](https://github.com/iadknet)
- [James Gregory](https://github.com/jagregory)
- [Igor Savin](https://github.com/kibertoad)

## Licence
[MIT](https://github.com/gargol/swagger-express-validator/blob/master/LICENSE)
Expand Down
44 changes: 29 additions & 15 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ const valueValidator = require('validator');

let pathObjects = [];
let options = {};
let ajvRequestOptions;
let ajvResponseOptions;

const buildPathObjects = paths => _.map(paths, (pathDef, path) => ({
definition: _.get(options.schema, ['paths', path]),
Expand Down Expand Up @@ -110,14 +112,18 @@ const sendData = (res, data, encoding) => {
};

const validateResponse = (req, res, next) => {
const ajv = new Ajv({
allErrors: true,
formats: {
int32: valueValidator.isInt,
int64: valueValidator.isInt,
url: valueValidator.isURL,
const ajv = new Ajv(Object.assign(
{},
{
allErrors: true,
formats: {
int32: valueValidator.isInt,
int64: valueValidator.isInt,
url: valueValidator.isURL,
},
},
});
ajvResponseOptions
));

const origEnd = res.end;
const writtenData = [];
Expand Down Expand Up @@ -199,14 +205,17 @@ const validateResponse = (req, res, next) => {
};

const validateRequest = (req, res, next) => {
const ajv = new Ajv({
allErrors: true,
formats: {
int32: valueValidator.isInt,
int64: valueValidator.isInt,
url: valueValidator.isURL,
},
});
const ajv = new Ajv(Object.assign(
{},
{
allErrors: true,
formats: {
int32: valueValidator.isInt,
int64: valueValidator.isInt,
url: valueValidator.isURL,
},
}, ajvRequestOptions
));

const requestSchema = resolveRequestModelSchema(req);

Expand Down Expand Up @@ -266,6 +275,8 @@ const validate = (req, res, next) => {
* @param opts.allowNullable {boolean|true}
* @param opts.requestValidationFn {function}
* @param opts.responseValidationFn {function}
* @param [opts.ajvRequestOptions] {object}
* @param [opts.ajvResponseOptions] {object}
* @returns {function(*=, *=, *=)}
*/
const init = (opts = {}) => {
Expand All @@ -274,6 +285,8 @@ const init = (opts = {}) => {
validateRequest: true,
validateResponse: true,
allowNullable: true,
ajvRequestOptions: {},
ajvResponseOptions: {},
});

if (options.schema) {
Expand All @@ -282,6 +295,7 @@ const init = (opts = {}) => {
debug('Please provide schema option to properly initialize middleware');
pathObjects = [];
}
({ ajvRequestOptions, ajvResponseOptions } = opts);

return validate;
};
Expand Down
5 changes: 4 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,10 @@
},
"scripts": {
"test": "mocha ./test --ui bdd",
"lint": "eslint ./"
"lint": "eslint ./",
"lint-fix": "eslint ./ --fix",
"precommit": "npm run lint && npm test",
"prepush": "npm run lint && npm test"
},
"keywords": [
"validation",
Expand Down
59 changes: 59 additions & 0 deletions test/pet-store.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -310,4 +310,63 @@ describe('pet store', () => {
});
});
});

describe('supports overriding ajv settings', () => {
const serverOpts = {
schema,
validateRequest: true,
validateResponse: true,
ajvRequestOptions: {
coerceTypes: true,
},
ajvResponseOptions: {
coerceTypes: true,
},
};

it('request passes after type coercion is applied', (done) => {
const router = Router();
router.post('/pet', (req, res) => {
res.json({
status: 'OK',
});
});
const app = createServer(router, serverOpts);
request(app)
.post('/pet')
.send({
id: '1',
name: 'Petty the Pet',
photoUrls: ['https://catphoto.com/best-cat'],
})
.expect(200)
.end((err) => {
app.close();
if (err) throw err;
done();
});
});

it('response passes after coercion is applied', (done) => {
const router = Router();
router.get('/pet/:id', (req, res) => {
res.json({
id: '1',
age: 21,
name: 'Pet Name',
photoUrls: ['https://catphoto.com/best-cat'],
});
});
const app = createServer(router, serverOpts);

request(app)
.get('/pet/1')
.expect(200)
.end((err) => {
app.close();
if (err) throw err;
done();
});
});
});
});

0 comments on commit c443d9a

Please sign in to comment.