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

Add option to permit validation when schema and data are empty #417

Merged
merged 4 commits into from
May 13, 2024

Conversation

chibicco
Copy link
Contributor

@chibicco chibicco commented Mar 15, 2024

Background

In our project, there are scenarios where the API returns an empty response body with status code 200.
However, the current OpenAPI 2 schema validation does not allow an empty schema for the response body, causing validation errors in these cases.

Specifically, in cases such as the schema and controller example below, I expect the Committee::Middleware::ResponseValidation check to pass successfully.

"/pets/cat": {
  "get": {
    "description": "Returns pets which are cats",
    "operationId": "find pets which are cats",
    "responses": {
      "200": {
        "description": "empty schema"
      }
    }
  }
}
class CatController
    # pets/cat
    get "/" do
        status 200
        present nil
    end
end

Changes

To address this issue, I have added an option to allow an empty schema for the response body in OpenAPI 2.
This change enables the validation to pass when both the schema and response body are nil, accommodating the specific use case in our project.

  1. If allow_blank_structures is set to true, the validation will pass if the schema is empty and the data is nil.
  2. I have also modified the error message for the case where data is present and the schema does not exist.

@chibicco chibicco force-pushed the open_api_2_link_targaet_schema branch 2 times, most recently from 3d68f0d to 90fb86f Compare March 15, 2024 12:51
raise InvalidResponse, "Invalid response.\n\n#{errors}"
end
rescue => e
raise InvalidResponse, "Invalid response.\n\nschema is undefined" if /undefined method .all_of. for nil/ =~ e.message
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ruby 3.2.2

NoMethodError: undefined method `all_of' for nil:NilClass

ruby 3.3.0

NoMethodError: undefined method `all_of' for nil

ruby head

NoMethodError: undefined method 'all_of' for nil

@chibicco
Copy link
Contributor Author

@brandur @ota42y

If you have a moment, I would appreciate it if you could review it.
I apologize for my poor English skills, so please bear with me.

@brandur
Copy link
Member

brandur commented May 4, 2024

@chibicco Sorry for the delay. Do you still need this?

@chibicco chibicco force-pushed the open_api_2_link_targaet_schema branch from 90fb86f to d1488a8 Compare May 9, 2024 00:47
@chibicco
Copy link
Contributor Author

chibicco commented May 9, 2024

@brandur
Thank you for response :)

Yes, I need this pull requests.
I have rebased on the latest master, If possible, please review.

@chibicco
Copy link
Contributor Author

Greetings.

I have just noticed the following correction.
#420

If my PR is not appropriate, I would appreciate it if you could close it.

@brandur
Copy link
Member

brandur commented May 10, 2024

@chibicco Let's hold on that a bit longer. We have someone offering to help with maintenance so we may yet be able to rescue the project.

Copy link
Member

@ydah ydah left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@chibicco I left a few comments. Could you check?

@@ -46,6 +47,7 @@ def initialize(options, schema, schema_type)
@optimistic_json = options.fetch(:optimistic_json, false)
@parse_response_by_content_type = options.fetch(:parse_response_by_content_type, true)
@parameter_overwite_by_rails_rule = options.fetch(:parameter_overwite_by_rails_rule, true)
@permit_blank_structures = options.fetch(:permit_blank_structures, false)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nits) As for the name of the parameter, how about allow_blank_structures to match the name of the other parameter if you want to allow it?

@allow_form_params = options.fetch(:allow_form_params, true)
@allow_query_params = options.fetch(:allow_query_params, true)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you.
I have renamed permit_blank_structures to allow_blank_structures.

ref: 6de7583

@@ -46,6 +47,7 @@ def initialize(options, schema, schema_type)
@optimistic_json = options.fetch(:optimistic_json, false)
@parse_response_by_content_type = options.fetch(:parse_response_by_content_type, true)
@parameter_overwite_by_rails_rule = options.fetch(:parameter_overwite_by_rails_rule, true)
@permit_blank_structures = options.fetch(:permit_blank_structures, false)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you add a description of this parameter to the README?

https://github.com/interagent/committee?tab=readme-ov-file#configuration-options

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have added a note to the README : )

[memo]

In OpenAPI 3, the following becomes nil, so the validation of empty response succeeds.
Therefore, this option is expected to be valid only for Hyper-schema and OpenAPI 2.

Comment on lines +192 to +194
"responses": {
"200": {
"description": "empty schema"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

imo) 204 No Content I think the response body is empty as a specification. So why not make the test data follow the common use case?

Suggested change
"responses": {
"200": {
"description": "empty schema"
"responses": {
"204": {
"description": "The resource was deleted successfully."

Refs: https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/204#compatibility_notes

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In my recent experiences, I've noticed the following scenarios:

  1. status_code=200 && empty response
    => This PR addresses this case. While it's technically correct to use status_code=204, there are instances where APIs are operated with 200, and ideally, I'd like to accommodate this case as well.

  2. status_code=204 && empty response
    => While it's being skipped here for 204, it seemed like a better approach to modify it to skip within Committee::SchemaValidator::HyperSchema::ResponseValidator. If it's not an inconvenience, I'm considering addressing this in a separate PR. Could you please share your thoughts on this?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you for your detailed explanation!
I understood the intent and thought it make sense. So I agree with your opinion.

@ydah
Copy link
Member

ydah commented May 10, 2024

memo) I noticed in writing the following comment that 204 responses and so on expect to describe a response without a body. In other words, I think the next major update will change this parameters default value.

#417 (comment)

@chibicco
Copy link
Contributor Author

@ydah

Thank you for your review!
I have added the necessary commits for the corrections and replied to the comments.
I kindly ask for your confirmation.

Copy link
Member

@ydah ydah left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@chibicco Thank you for your response! I think it looks good 😀
Finally, could you add a description of this change in CHANGELOG.md?

@chibicco
Copy link
Contributor Author

@ydah I have updated the CHANGELOG.md :)
We appreciate your kind support.

@chibicco chibicco requested a review from ydah May 11, 2024 17:44
Copy link
Member

@ydah ydah left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good! Thank you for your work.

cc/ @brandur

@ydah ydah merged commit 79bad85 into interagent:master May 13, 2024
6 checks passed
@chibicco
Copy link
Contributor Author

@brandur
Thank you for merging the PR.
Could you kindly release the latest master at a time that is convenient for you?

@brandur
Copy link
Member

brandur commented May 15, 2024

@chibicco Yes! I believe @ydah is waiting for one more change on review feedback over on #396, after which he'll cut a release and get this shipped.

@chibicco
Copy link
Contributor Author

I see, I understand !

@ydah
Copy link
Member

ydah commented May 17, 2024

@chibicco Thank you for waiting. Since v5.3.0 has been released, so your patch has been released! Thank you for your great work!
https://rubygems.org/gems/committee/versions/5.3.0

@chibicco
Copy link
Contributor Author

@ydah

I have confirmed the v5.3.0 release : )
Thank you!

@chibicco chibicco deleted the open_api_2_link_targaet_schema branch June 6, 2024 19:28
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants