Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Non-blank strings emit schema that allows blanks #186

Closed
zefciu opened this issue Oct 31, 2020 · 5 comments
Closed

Non-blank strings emit schema that allows blanks #186

zefciu opened this issue Oct 31, 2020 · 5 comments
Labels
enhancement New feature or request fix confirmation pending issue has been fixed and confirmation from issue reporter is pending

Comments

@zefciu
Copy link

zefciu commented Oct 31, 2020

As stated in OpenAPI3 documentation: “ Note that an empty string "" is a valid string unless minLength or pattern is specified. ”
https://swagger.io/docs/specification/data-models/data-types/#string In drf, however "" is not a valid input for fields that have allow_blank set to False. drf-spectacular emits a field that allows blanks even if allow_blank is set to False.

To Reproduce
A simple way to show this error is to create any API that contains a non-blank character field and then run schemathesis against it. Output:

Received a response with a status code, which is not defined in the schema: 400

Declared status codes: 200                                                                                                                                                                      

Body            : {'email': '0@A.com', 'first_name': '', 'ip_address': '', 'last_name': ''}

Proposed fix
A simple idea to fix this would be to add minLength: 1 to all the fields that aren’t marked with allow_blank.
Please confirm that this would be a good solution, so I can work on a patch.

@tfranzel
Copy link
Owner

tfranzel commented Nov 1, 2020

hi @zefciu, that is quite interesting and has been an oversight until now. minLength: 1 is not only simple but probably the only way to model this here. yes, i would consider this change viable.

@tfranzel
Copy link
Owner

revisited this. We now add minLength: 1 for allow_blank=False, however there are caveats which is why it needs to be explicitly enabled. there are 2 main reasons for this:

  1. The change has a wide reach and may break users, as their schemas may significantly change.
  2. It is not a perfect representation when COMPONENT_SPLIT_REQUEST is turned off, because DRF is asymmetric in it's handling of blank strings. Responses may contain empty string even though allow_blank=False. The minLength: 1 is only guaranteed to be accurate for requests. We account for this on readOnly but it's not perfect otherwise.

# Adds "minLength: 1" to fields that do not allow blank strings. Deactivated
# by default because serializers do not strictly enforce this on responses and
# so "minLength: 1" may not always accurately describe API behavior.
# Gets implicitly enabled by COMPONENT_SPLIT_REQUEST, because this can be
# accurately modeled when request and response components are separated.
'ENFORCE_NON_BLANK_FIELDS': False,

@tfranzel tfranzel added the fix confirmation pending issue has been fixed and confirmation from issue reporter is pending label Oct 15, 2021
@intgr
Copy link
Contributor

intgr commented Oct 18, 2021

serializers do not strictly enforce this on responses

This behavior is the rule, not the exception. Validation only occurs during input (from the request), validations are mostly ignored on output (response).

By that logic, for example you should not add minimum, maximum, pattern etc properties to schemas either.

@tfranzel
Copy link
Owner

This behavior is the rule, not the exception.

@intgr totally agree. I have always brushed over this aspect. However, I would assume that the majority do use their serializers in a predictable symmetric way. Also I consider the blank thing a DRF/Django quirk that is worth pointing out more prominently in the schema.

Theoretically we could remove all "restricting" keywords from readOnly fields and all responses with COMPONENT_SPLIT_REQUEST. The question is "is it worth it"? Besides not being enforced it also has informational value. And finally in case of unpatched ModelSerializers, it is indeed a restriction (enforced by the database not the serializer though).

Imho there will always be some gray area due to the way DRF works. Can we gain something here by being pedantic?

@tfranzel
Copy link
Owner

closing this issue for now. feel free to comment if anything is missing or not working and we will follow-up.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request fix confirmation pending issue has been fixed and confirmation from issue reporter is pending
Projects
None yet
Development

No branches or pull requests

3 participants