Open API Validation

Not applicable

I found an useful article on validating the Open API specification against the API requests here : https://community.apigee.com/articles/42993/using-the-openapi-spec-to-validate-json-requests.html .However it seems to validate requests that only contain a payload in the JSON format.Is there any way to extend this to include validating query parameters and form parameters?

2 5 1,667
5 REPLIES 5

@Kurt Googler Kanaskie @Dino-at-Google I have the same exact question.


Thanks for your question, in fact I did extend that example to validate based on params for header, query and form data. Its pretty straight forward.

This is my latest ValidateRequestTV4.js example:

/* Here's how JSON validation via OAS works:
    Create a JSON object for the oas by copy/pasting the entire OAS into oas.js and assigning to a variable 'oas'
    Get the request schema from the OAS, using the current.flow.name === operationId.
    e.g. {"$ref": "/schema#/definitions/NodeCreateRequest" };
    Add the OAS to tv4
    Validate with request schema and evaluate the results
    Throw errors which can be caught in the ProxyFaultRules
*/
try {
    var verb = context.getVariable('request.verb');
    var pathsuffix = context.getVariable('proxy.pathsuffix');
    var flowname = context.getVariable('current.flow.name');
    var params = getMessageParams( flowname );
    // print( "flowname:" + flowname + " params:" + JSON.stringify(params) );


    if( params !== undefined ) {
        for ( var param in params ) {
            // print( "PARAM " + JSON.stringify(params[param]) );
            if( params[param].hasOwnProperty( 'in' )       && params[param].in === 'header' && 
                params[param].hasOwnProperty( 'required' ) && params[param].required === true &&
                params[param].hasOwnProperty( 'name' ) ) {
                    
                var nameValue = params[param].name;
                var paramValue = context.getVariable( 'request.header.' + nameValue);
       
                if( paramValue === undefined || paramValue === null || paramValue === "") {
                    throw "Missing or empty required header param: " + nameValue;
                }
            }
            else if( params[param].hasOwnProperty( 'in' )  && params[param].in === 'query' && 
                params[param].hasOwnProperty( 'required' ) && params[param].required === true &&
                params[param].hasOwnProperty( 'name' ) ) {
                    
                var nameValue = params[param].name;
                var paramValue = context.getVariable( 'request.queryparam.' + nameValue);
                
                if( paramValue === undefined || paramValue === null || paramValue === "") {
                    throw "Missing required query param: " + nameValue;
                }
            }
            else if( params[param].hasOwnProperty( 'in' )  && params[param].in === 'formData' && 
                params[param].hasOwnProperty( 'required' ) && params[param].required === true &&
                params[param].hasOwnProperty( 'name' ) ) {
                    
                var nameValue = params[param].name;
                var paramValue = context.getVariable( 'request.formparam.' + nameValue);
                
                if( paramValue === undefined || paramValue === null || paramValue === "") {
                    throw "Missing or empty required formData param: " + nameValue;
                }
            }
            else if( params[param].hasOwnProperty( 'in' ) && params[param].in === 'body' && 
                params[param].hasOwnProperty( 'schema' ) ) {
                    
                // print( "REQUEST SCHEMA: " + JSON.stringify(params[param].schema) );
                var schema = params[param].schema;
                var bodyContent = context.getVariable('request.content');
                var body = JSON.parse(bodyContent);
                // Add the OAS as a schema and validate the sub schema
                tv4.addSchema('/schema', oas);
                var result = tv4.validateMultiple(body, schema);


                // A missing schema validates to true, but we want that to be an error
                // Override missing entry with full schema value
                if( result.missing[0] ) {
                    result.errors[0] = {"schema":schema};
                    throw "Schema definition not found" + JSON.stringify(result.errors);
                }
                else if( result.valid === false ) {
                    throw "Validation failed for: " + verb + " " + pathsuffix + ": " + JSON.stringify(result.errors);
                }
            }
        }
    }
}
catch( err ) {
    // This raises fault named "ScriptExecutionFailed", 
    // with script name and line details, so set errorMessage instead
    context.setVariable('javascript.errorMessage', err);
    throw err;
}


function getMessageParams( flowname ) {
    // Find the operationId that matches the flowname
    // Return the schema from the parameter that is "in" "body".
    var paths = oas.paths;
    for ( var path in paths ) {
        var verbs = paths[path];
        for( var verb in verbs ) {
            if( verbs[verb].operationId === flowname ) {
                var params = verbs[verb].parameters;
                return params;
            }
        }
    }
    return undefined;
}

Hi @Kurt Googler Kanaskie, the current implementation works fine only for required parameters defined in schema ex:

definitions:

sms:

type: object

required:

- smsType

properties:

smsType:

type: string

title: smsType

My client wants me to implement schema validation, for the whole JSON schema. is it possible?.

Yes, for the JSON payload that's the section where it looks for the schema in the OAS associated with

params[param].in==='body'
...

       tv4.addSchema('/schema', oas);
       var result = tv4.validateMultiple(body, schema);
...

Hey @Kurt Googler Kanaskie,


{"id":0,

"name":"doggie",

"photoUrls":["string"],

"tags":[{"id":0,"name":"string"}]

}

The above payload is defined in the schema, where name & photoUrls are required.

{

"name":"doggie",

"photoUrls":["string"]

}

if i send a request using above payload, the validation is passing, even though i did not specify id, tags. I would like a solution/method where it validates the entire schema against the request .

Thanks.