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

assert_response_schema_confirm : impossible to validate integers in Headers #345

Open
garz75 opened this issue Dec 22, 2021 · 3 comments
Open

Comments

@garz75
Copy link

garz75 commented Dec 22, 2021

Hello,

I am using committee-rails and committee to add schema validation tests for the responses of our APIs. We also use Pagy response pagination gem that adds headers to the request (total number of result pages, current pages, etc.) , so our OpenAPI definition specifies these headers as integers:

          headers:
            Current-Page:
              schema:
                type: integer
              description: |
                [RFC288 Pagination header](https://tools.ietf.org/html/rfc8288): Current page number
              example: 2

However, when using `assert_response_schema_confirm(200) to check the JSON schema for the response, we get the error:

Invalid response for OpenAPI schema /Users/fgarzon/Dev/fft_api_doc/fft_server/openapi.yaml
- Headers: {"Content-Type"=>"application/json; charset=utf-8", "Link"=>"<http://www.example.com/api/v2/parcels?reference=162&page=1>; rel=\"first\", <http://www.example.com/api/v2/parcels?reference=162&page=1>; rel=\"last\"", "Current-Page"=>"1", "Page-Items"=>"5", "Total-Pages"=>"1", "Total-Count"=>"1", "ETag"=>"W/\"9edc3cf0bb6c09890b9df541eb9fe866\"", "Cache-Control"=>"max-age=0, private, must-revalidate", "X-Request-Id"=>"e9f565bc-f208-4c57-930e-5aa30c16b477", "X-Runtime"=>"0.003913", "Content-Length"=>"193"}
- Body: [{"id":6043,"reference":"162","type":"internal","status":"waiting","cancellable":true,"item_count":1,"description":"return 142","allow_bulk_handing":true,"to_hand_to":"Transporteur (Interne)"}]
Request:
- Path: /api/v2/parcels?reference=162
- Method: GET
- Body:
ERROR["test_0001_returns the expected parcel", #<Minitest::Reporters::Suite:0x00007fed4c77f010 @name="with reference filter">, 11.45178499999929]
 test_0001_returns the expected parcel#with reference filter (11.45s)
Minitest::UnexpectedError:         Committee::InvalidResponse: #/paths/~1parcels/get/responses/200/headers/Current-Page/schema expected integer, but received String: "1"
            test/support/assertions.rb:22:in `assert_response_v2_api'
            test/integration/parcels/index_test.rb:141:in `block (2 levels) in <class:ParcelsIndexTest>'

You can see in the verbose output above, the ActionDispatch::Response::Header object that stores the response headers stores the "integer values" as strings. But when sent on the wire, they are in integer format:

$ curl -v -u runner:<a password> -H "Accept: application/json"  http://localhost:3000/api/v2/parcels
*   Trying ::1:3000...
* Connected to localhost (::1) port 3000 (#0)
* Server auth using Basic with user 'runner'
> GET /api/v2/parcels HTTP/1.1
> Host: localhost:3000
> Authorization: Basic <some b64 string>
> User-Agent: curl/7.77.0
> Accept: application/json
>
* Mark bundle as not supporting multiuse
< HTTP/1.1 200 OK
< Content-Type: application/json; charset=utf-8
< Link: <http://localhost:3000/api/v2/parcels?page=1>; rel="first", <http://localhost:3000/api/v2/parcels?page=1>; rel="last"
< Current-Page: 1
< Page-Items: 5
< Total-Pages: 1
< Total-Count: 1
< ETag: W/"b26995e4184fe0b06e6811d07105e9ea"
< Cache-Control: max-age=0, private, must-revalidate
< X-Request-Id: ec7cb80a-35cc-425c-9aa1-d202b3b8e09b
< X-Runtime: 0.887195
< Transfer-Encoding: chunked
<
* Connection #0 to host localhost left intact

My question is: why does the committee validation for this header fail ? Am I missing something here ? Thank you in advance

  def assert_response_v2_api(code)
    assert_response(code)
    return unless ENV["V2_API_OPENAPI_SCHEMA_FILE"]

    begin
      assert_response_schema_confirm(code)
    rescue Committee::InvalidResponse => exception
      puts <<~INFO

        Invalid response for OpenAPI schema #{ENV['V2_API_OPENAPI_SCHEMA_FILE']}
        - Headers: #{response.headers}
        - Body: #{response.body}
        Request:
        - Path: #{request.fullpath}
        - Method: #{request.method}
        - Body: #{request.body&.string}
      INFO
      raise exception
    end
  end
@ota42y
Copy link
Member

ota42y commented Dec 28, 2021

Your OpenAPI Specification defile Current-Page as integer but rails set string (which we can convert integer) so committee raising error is correct works.

But we can't use integer in header because many library expect HTTP header as string.
So committee response validation can effectively only support strings.

It's not good feature, so we need to add coerce_header option to response validation.
I'm sorry, but until then, please use the string

@garz75
Copy link
Author

garz75 commented Dec 28, 2021

Thank you for your answer. I will have a look to the source code and see if I have what it takes to add this option.

@ahx
Copy link

ahx commented Apr 3, 2023

This is something where openapi_parameters could help. Here's a test that describes the behavior: https://github.com/ahx/openapi_parameters/blob/main/spec/openapi_parameters/header_spec.rb#L16-L19

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

No branches or pull requests

3 participants