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
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.
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
}
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 using express-oas-validator with express.js, the routes that end with a trailing slash are not being validated correctly against the OpenAPI definitions. This leads to the validator not recognizing valid endpoints if they are defined without a trailing slash in the OpenAPI documentation but are called with one (e.g., calling /api/forbidden-words/
when the OpenAPI defines /api/forbidden-words
).
/api/forbidden-words
)./api/forbidden-words/
).The validator should either recognize that /api/forbidden-words/
and /api/forbidden-words
are the same endpoint, or there should be an option to normalize the URL before validation to ensure consistency.
The validator returns an error: Method: "get" not found in the OpenAPI definition for "/api/forbidden-words/" endpoint
.
As a temporary workaround, routes can be normalized by stripping trailing slashes before validation. However, it would be preferable to have this handled within the library either by default or via a configuration option.
Please let me know if there are any more details I can provide or if a fix or workaround is already available. Thank you for your assistance!
/**
* @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.
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:
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,
};
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));
}
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.