brikev / express-oas-validator Goto Github PK
View Code? Open in Web Editor NEWExpress OpenAPI Specification (OAS) middleware validator
License: MIT License
Express OpenAPI Specification (OAS) middleware validator
License: MIT License
The data type of path parameters doesn't seem to be validated properly. Whereas we get an error if the path parameter is required and we receive a value of undefined
in the URL, the validator doesn't seem to be throwing an exception if it receives a string instead of a number, for example. โ
This issue can be easily reproduced by introducing a new test in pathParam.test.js
. The first step would be to modify one of the endpoints in fake-server.js
to set one of the path params to be of type number
, for example:
/**
* GET /api/v1/albums/{id}
* @summary This is the summary or description of the endpoint
* @param {number} id.path.required
* @return {object} 200 - success response - application/json
*/
Then, we could just create a new test in pathParam.test.js
file to trigger the issue:
it('should throw error when param is of wrong type', () => (
request
.get('/api/v1/albums/string')
.expect(400);
));
In the example above, the expected behaviour would be to obtain a bad request error after the validation, because the value of the path parameter is not valid. Right now, however, we'll see that the new test has failed because the endpoint is returning a successful response even though the data type doesn't match.
The parameter id
should be a number, but the value string
we've passed in the URL cannot be transformed into a numeric value. This behaviour could cause issues in the applications using the library, as they may not be double checking the data type of the parameters assuming the validator already did.
This issue was identified while running some tests on version 1.0.3, but it seems to still be present in the latest release, 1.0.4.
This problem is related to: BRIKEV/express-jsdoc-swagger#167
This happens because init()
call do no job if validator instance already exists
When we pass only 1 item as to array param express parses it as plain type (not array). As result we get validation error.
Example:
/**
* GET /testArray
* @param {array<string>} testParam.query.required - test array param
* @returns {boolean} 200 - OK
* @returns {ErrorResponse} 400 - Bad Request
*/
router.get('/testArray', validateRequest()),
async (req, res, next) => {
console.log(Array.from(req.query.testParam));
}
/**
* @typedef {object} UserPhotoUploadRequest
* @property {string} field1 - some field 1
* @property {integer} field2 - some field 2
* @property {string} photo.required - Photo - binary
*/
/**
* POST /photo
* @summary Uploads use photo
* @param {UserPhotoUploadRequest} request.body.required - request body - multipart/form-data
* @returns {boolean} 200 - success
* @returns {string} 400 - error text
* @returns {string} 500 - error text
*/
router.post('/photo', validateRequest(), async (req, res) => {
try {
const form = new multiparty.Form();
form.parse(req, async (err, fields, files) => {
// here we get an error since req object is already read by the validateRequest()
// also we have no way to access parsed fields and files by the validateRequest() call
});
} catch (err) {
res.status(500).send(err.message);
}
}
This happens since multiparty reads the req object stream. A possible solution is to modify the request object inside the validateRequest() call by adding fields and files properties there.
When any parameter is passed to validateRequest() the result config does not apply DEFAULT_CONFIG values.
The problem is that ...
is missing in config.js:
return {
DEFAULT_CONFIG,
...config,
};
To fix use the following code:
return {
...DEFAULT_CONFIG,
...config,
};
Describe the bug
There seems to be a problem when using the enum
keyword on a nullable field. In those cases, it seems enum
takes precedence over the nullable condition, causing the validation to fail even if we've added null
to the list of supported types for the property.
To Reproduce
The problem can be triggered with a schema where we have a field that can either contain a subset of values (defined with the enum
annotation) or be null
.
/**
* @typedef {object} MySchema
* @property {string|null} value - Nullable field that can only contain certain values - enum:val1,val2
*/
Expected behavior
What I'd expect on this scenario is that validation succeeds if any of these conditions are met:
value
contains any of the supported values defined in the enum
annotationvalue
is null
Screenshots
Below there is a subset of the schema where the bug was detected:
/**
* @typedef {object} GeneratedTestData
* @property {number} id.required - Test id
* @property {string} title.required - Name of the test
* @property {string|null} format - Test format - enum:multiple-choice,reading,other
* @property {string} createdOn - Creation date
*/
The library returned the following error when validating the response for an endpoint returning the forementioned schema:
{
name: 'OpenAPIUtilsError',
type: 'OpenAPIUtilsError:response',
message: 'Error in response: Schema GeneratedTestData/properties/format must be equal to one of the allowed values: multiple-choice, reading, other. You provide "{"id":208,"title":"Toets 1","format":null,"createdOn":"2012-07-19T10:58:11.000Z","updatedOn":"2022-01-31T17:00:30.659Z"}"',
extra: [
{
instancePath: '/0/format',
schemaPath: 'defs.json#/definitions/components/schemas/GeneratedTestData/properties/format/enum',
keyword: 'enum',
params: [Object],
message: 'must be equal to one of the allowed values'
}
],
status: 500,
statusCode: 500
}
Describe the bug
When validating the body of a request or response, the library throws an error when it encounters a null
value, even when the property is not marked as required.
To Reproduce
This issue can be easily reproduced by using a test for the POST /api/v1/songs
endpoint in request.test.js
, by adding a null
value to the payload sent to the endpoint. An example is listed below:
it('should not throw error when request is valid, including a null value for non-required property', () => (
request
.post('/api/v1/songs')
.send({ title: 'valid title', artist: null })
.expect(200)
));
The song schema looks like this:
/**
* A song
* @typedef {object} Song
* @property {string} title.required - The title
* @property {string} artist - The artist
* @property {integer} year - The year
*/
Although the artist
property is not required, running this test triggers the following validation error:
{
"name": "OpenAPIUtilsError",
"type": "OpenAPIUtilsError:request",
"message": "Error in request: Schema Song/properties/artist should be string. You provide \"{\"title\":\"valid title\",\"artist\":null}\"",
"extra": [
{
"keyword": "type",
"dataPath": "/artist",
"schemaPath": "defs.json#/definitions/components/schemas/Song/properties/artist/type",
"params": {
"type": "string"
},
"message": "should be string"
}
],
"status": 400,
"statusCode": 400
}
Expected behavior
If a property is not marked as required
in the schema, both undefined
and null
values should be acceptable both in request body and response.
Screenshots
The following error is being received for the example described above:
It would be nice to get parsed parameters after the validation process.
Imagine you have a request:
/**
* GET /visit/list
* @summary get list of visits
* @param {string} some-header-param.header - some header string value
* @param {boolean} booleanParam.query - some boolean value
* @param {integer} intParam.query - some integer value
*/
router.get('/list', validateRequest(), async (req, res) => {
const someHeaderParam = req.headers[''];
const {booleanParam, intParam} = req.query;
// the problem:
// we need to gather params from header, query, body and path and to convert there values to previously described types
// here booleanParam and intParam are string and we need to explicitly convert them before use
});
The suggest is to either set some req property to parsed list of params or to introduce another method to simplify request object parsing.
When express routes are used like this:
// authorization routines
app.use('/auth', require("./routes/auth"));
// user profile routines
app.use('/user', require("./routes/user"));
The validator fails to find the correct path since it uses req.route.path
which returns only the the final path.
E.g. /auth/login
request will have /login
as req.route.path
.
The solution is either use req.baseUrl
together with req.route.path
or to give an options to pass the baseUrl to validation methods.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.