snok/drf-openapi-tester

Custom URI validation

Closed this issue · 4 comments

Hi, thanks for this great library since it helps us to validate our spec against our API!

We have an API that passes google cloud store links around as part of the request / responses.

In our (YAML, openapi) spec, we document those e.g. as

      documentUri:                                                                                                                                                                        
        type: string                                                                                                                                                                         
        format: uri                                                                                                                                                                          
        description: remote reference to get the file                                                                                                                                    
        example: 'gs://bucket/obj.pdf'  

However, the built-in validation seems to rely on django's URL validators:

"uri": create_validator(URLValidator()),
"url": create_validator(URLValidator()),

which in turn only support more commonly known URL schemes: https://docs.djangoproject.com/en/3.2/ref/validators/

I've also looked into adding a custom validator with the validators kwarg, but it looks like custom validators are run in addition to the base set of validators, not in place of.

What would be the best way to add such custom URI scheme? Would be happy to drop a PR once it's clear what to do.

Hmm. Its a use case we did not anticipate. If you have time to add a PR, I guess you could add a more sophisticated URL validator that wraps and extends the django buildin.

If not - you could locally subclass the validator and override the validation logic locally. Then use your version of the library.

I guess you could add a more sophisticated URL validator that wraps and extends the django buildin.

From what I read here

combined_validators = cast(
List[Callable],
[
validate_type,
validate_format,
validate_pattern,
validate_multiple_of,
validate_minimum,
validate_maximum,
validate_unique_items,
validate_min_length,
validate_max_length,
validate_min_items,
validate_max_items,
validate_max_properties,
validate_min_properties,
validate_enum,
*self.validators,
*(validators or []),
],
)

it seems like you can only add validators instead of overriding them.

I could indeed just change the validator definition

 "uri": create_validator(URLValidator(schemes=['http', 'https', 'ftp', 'ftps', 'gs'])), 

but I'm not sure that's what you'd want.

Perhaps a simpler option would be:

  • define a custom gsuri format in our openapi spec
  • define a custom validator for that one?

that would work. An alternative within the scope of the library - modify the test_schema_section to call a function or use a @Property called "get_validators" - which will return all the list of builtin validators. You can then override it externally.

Couldn't get it to work with a custom validator yet; looks like the validator is only run once.

Will probably check after the weekend.

Thx already for the quick reply! Worst-case, I'll just stick to a custom format in our openapi spec (without any validation)