Using Validator without express #11

Closed
mangvlad opened this Issue Apr 2, 2013 · 4 comments

Projects

None yet

2 participants

mangvlad commented Apr 2, 2013

I have a use-case for validator that maybe a good new feature...

The operation I am exposing has two parts: validate input and if valid, delegate the call to a data service. This is exactly how this library is designed to operate...

Another use-case is an operation that gets the input, validates and needs two call one or more operations from the same API. As it stands now, the only way to do it is to make HTTP calls (to take advantage of the Validator).

So, if validator code was split to allow for it to be invoked as a part of HTTP as well as "on demand", it will significantly increase the use-cases for it...

(I hope this will make sense to anyone but me.. If not, let me know: maybe I can try to come up with a better explanation...)

Thanks.

Contributor
feugy commented Apr 2, 2013

Hi Mangvlad.

Using the validator without express is perhaps possible but really tricky: you'll have to provide a "fake" Request object with its hearders, its query parameter, a path, and (most complicated) a parsed or readable body.

Take a look at the validate function, you'll immediately understand what I mean. IMHO, swagger-jack's validator just adds this Express-related stuff to json-gate.

So if you don't need Express routes, I think you should consider just using json-gate and js-yaml to store your descriptors.

Nevertheless, I'd like to explore this track a little bit. Could you please give some examples of use cases ? I didn't got the two-call stuff.

mangvlad commented Apr 2, 2013

Damien,

More details about the use case:

  1. I have 2 "backend" services: one to GET resource A {"p": "test"} and one to get resource B {"t":"bla"}. Both operations have input parameters (query strings, headers, path parameters..) so to make sure only valid requests will be forwarded to my backend service I use Validator middleware. Also, to hide some complexitiy of calling my backend services, I have two functions getA(params) and getB(params) that I use from my controllers.
  2. I need to expose a new service that gets resource C {"p": "test", "t":"bla"} and to get it this service needs to get resource A, resource B and do some logic for getting resource C. For now I will call getA(params) and getB(params) directly from this new controller, but this will bypass Validations.
  3. What I am looking for, is a way to call validate for a giving operation that can take query params array, path params array, headers array, JSON object that represents data (if update or insert) and based on the spec can tell me if this operation is allowed.

I see that there is a private function there already called validate:

validate = function(req, path, specs, next)

I would like there to be a function that will be request/response independent (dealing with arrays and data only and returning status and errors) and available to be called from outside of express...

(the same function can be reused by the current validate)

Thanks.

mangvlad commented Apr 7, 2013

Damien,

Looking at the code, I was able to find an easy way (with some very, very minor modifications) to extract only what is needed to generate a set of JSON schemas for a single operaton (operation's parameters to be exact).

The function takes swagger operation and returns an array of schemas. This way it decouples it from express and even json-gate so any schema validator can be used by any part of the app...

Here is the function (sorry, I did it in JS, not coffee) (it is almost an exact copy of one of the sub loops from your analyzeRoutes function; it also uses your other functions: convertType, convertModel, cast and generate):

function operationToSchemas(operation, models){
var schemas = [];
_ref4 = operation.parameters;
for (_l = 0, _len3 = _ref4.length; _l < _len3; _l++) {
spec = _ref4[_l];
allowMultiple = spec.allowMultiple === true;
schema = {
type: convertType(spec.dataType, spec.name, allowMultiple, models),
required: spec.required === true
};
if (spec.name != null) {
schema.title = spec.name;
}
if (spec.description != null) {
schema.description = spec.description;
}
if (schema.type === 'object') {
_.extend(schema, convertModel(models, spec.properties ? spec : models[spec.dataType]));
}
if (((_ref5 = spec.allowableValues) != null ? _ref5.valueType : void 0) != null) {
switch (spec.allowableValues.valueType.toLowerCase()) {
case 'range':
schema.minimum = spec.min;
schema.maximum = spec.max;
break;
case 'list':
schema["enum"] = spec.values;
}
}
if (allowMultiple) {
schema.items = _.clone(schema);
schema.items.type = convertType(spec.dataType, spec.name, false, models);
delete schema.items.title;
delete schema.items.description;
}
var jsonSchema = schema;
console.log(jsonSchema)
schemas.push({
kind: spec.paramType.toLowerCase(),
name: spec.name,
schema: jsonSchema
});
}
return schemas;
}

Not sure if you would like to refactor your code to expose it for use-cases like mine or if you would like me to do fork/pull... I think it will be a very easy/simple change...

Thanks.

@feugy feugy closed this in 5f4c907 May 13, 2013
Contributor
feugy commented May 13, 2013

Hi Mangvlad.

I've just pushed the 1.6.0 version (and not 1.5.0 as annonced in #11), which will allows you to use the validation method without Express request.

It's all explained inside the ReadMe.

Let me know if you encounter more problems.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment