naz / swagger-express-validator

Lightweight requrest/response validation middleware based on swagger/OpenAPI schema
MIT License
56 stars 24 forks source link

Support for endpoint-level validation #18

Open kibertoad opened 5 years ago

kibertoad commented 5 years ago

Judging by documentation, it is currently only possible to use the validator application-wide, immediately affecting all of the endpoints. It would be helpful to be able to attach middleware to specific endpoints with predefined swagger path already filled during instantiation.

This is useful for two scenarios: 1) Google Cloud Functions: while they seem to use Express under the hood and in general support swagger-style middleware, you can't attach middleware on app or router level and you don't have access to routing params, making usage of swagger-express-validator impossible; 2) Incremental introduction of validation into the project.

kibertoad commented 5 years ago

@gargol Please let me know if this change makes sense and if I could contribute to implementing it.

naz commented 5 years ago

:wave: @kibertoad . Thanks for the input! Can you please provide some code on how you see it being used. My understanding is something like this?

const validator = require('swagger-express-validator');

server.use('/status', validator(opts), (req, res) => {
  res.json({
    status: 'OK',
  })
});
kibertoad commented 5 years ago

That's the thing, Google Cloud Functions have no concept of server or router, so minimal Cloud Function code looks like this:

exports.helloHttp = (req, res) => {
  res.send(`Hello ${req.body.name || 'World'}!`);
};

End result of this is that when you call HOST_NAME/helloHttp, this function will be invoked. Recommended pattern for middleware looks like this:

exports.helloHttp = (req, res) => {
 cors(req, res, () => {
res.send(`Hello ${req.body.name || 'World'}!`);
});
});

Obviously you can structure code in a somewhat smarter fashion and implement express-like chains, but the main point here is that you can't rely on any existing context for resolving triggered path.

Ideally validation middleware API would be something like this:

const validationMiddleware = validator.get('helloHttp')

exports.helloHttp = (req, res) => {
 validationMiddleware (req, res, (err) => {
res.send(`Hello ${req.body.name || 'World'}!`);
});
});
kibertoad commented 5 years ago

(sorry, my original example was wrong, updated it now)

naz commented 5 years ago

My understanding is that it would require to extract resolveRequestModelSchema and resolveResponseModelSchema out of validateRequest and validateResponse methods into some more generic way or matching a schema to the endpoint that needs validation. Makes sense to me :+1: I'm not actively using the library any more but would gladly collaborate on such feature :smiley:

kibertoad commented 5 years ago

Thank you for the reply! Will try to cook up something for this :)

kibertoad commented 5 years ago

(switched companies since and feature become less relevant for me, but I still intend to implement it. Sorry for delay!)

naz commented 5 years ago

@kibertoad no worries, know the pain. I'm having troubles giving this project time as well :smiley: