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

Error when executing POST json request #20

Closed
nicopaez opened this issue Feb 17, 2021 · 5 comments
Closed

Error when executing POST json request #20

nicopaez opened this issue Feb 17, 2021 · 5 comments

Comments

@nicopaez
Copy link

nicopaez commented Feb 17, 2021

I am trying to generate the spec for a POST request that sends json message in the body and I getting the error below.

 ActionDispatch::Http::Parameters::ParseError:
            no implicit conversion of nil into String
          # /usr/local/bundle/gems/actionpack-6.0.3.3/lib/action_dispatch/http/parameters.rb:114:in `rescue in parse_formatted_parameters'
          # /usr/local/bundle/gems/actionpack-6.0.3.3/lib/action_dispatch/http/parameters.rb:110:in `parse_formatted_parameters'
          # /usr/local/bundle/gems/actionpack-6.0.3.3/lib/action_dispatch/http/request.rb:389:in `block in POST'
          # /usr/local/bundle/gems/rack-2.2.3/lib/rack/request.rb:69:in `fetch'
          # /usr/local/bundle/gems/rack-2.2.3/lib/rack/request.rb:69:in `fetch_header'
          # /usr/local/bundle/gems/actionpack-6.0.3.3/lib/action_dispatch/http/request.rb:388:in `POST'
          # /usr/local/bundle/gems/rspec-openapi-0.3.13/lib/rspec/openapi/record_builder.rb:94:in `raw_request_params'
          # /usr/local/bundle/gems/rspec-openapi-0.3.13/lib/rspec/openapi/record_builder.rb:41:in `build'
          # /usr/local/bundle/gems/rspec-openapi-0.3.13/lib/rspec/openapi/hooks.rb:12:in `block in <top (required)>'
          # ------------------
          # --- Caused by: ---
          # TypeError:
          #   no implicit conversion of nil into String
          #   /usr/local/bundle/gems/activesupport-6.0.3.3/lib/active_support/json/decoding.rb:23:in `decode'

this is my rspec:


      it 'create a user' do
        header 'CONTENT_TYPE', 'application/json'
        json_data = { name: 'juan'}.to_json
        post '/users', json_data, { 'Content-Type' => 'application/json' }
        expect(last_response.status).to eq(201)
      end

I notice that if I remove the fist line (header 'CONTENT_TYPE', 'application/json') then the execution completes successfully but the result yaml spec is wrong, it specifies request.content type as application/x-www-form-urlencoded instead of application/json.

I am running ruby 2.5.7p206 and my application is padrino application (not rails).

If anyone can give some guidance I my try to submit a fix.

@k0kubun
Copy link
Collaborator

k0kubun commented Feb 18, 2021

Thanks for trying that out with Padrino. I tried to reproduce it with a request spec for Rails, but header was not defined.

May I ask you to create a small repository that reproduces your issue?

@nicopaez
Copy link
Author

nicopaez commented Feb 18, 2021

Sure. Here you have a sample webapi project I am working on.

To reproduce the issue you can:

  1. Clone this repository: git@gitlab.com:fiuba-memo2/ejemplos/webapi-example.git
  2. Switch to branch "openapi-generator"
  3. Run the ./start_dev_containers.sh script to have a docker dev environment ready to work
  4. Run the ./generate_apispec.sh script to reproduce the issue

Please tell me If there is any other thing I could help.

Nico

@k0kubun
Copy link
Collaborator

k0kubun commented Feb 19, 2021

OK, I kind of understood why it's happening. Usually, when you write a request spec with rack-test, last_request.env['rack.input'] is ready to be read:

From: /home/k0kubun/src/github.com/k0kubun/rspec-openapi/spec/requests/roda_spec.rb:24 :

    19:   describe '/roda' do
    20:     context 'when id is given' do
    21:       it 'returns 200' do
    22:         header 'CONTENT_TYPE', 'application/json'
    23:         post '/roda', { id: 1 }.to_json, { 'Content-Type' => 'application/json' }
 => 24:         require "pry";binding.pry
    25:         expect(last_response.status).to eq(200)
    26:       end
    27:     end
    28:   end
    29: end

[1] 3.0.0-p0 (#<RSpec::ExampleGroups::Roda::Roda::WhenIdIsGiven>)> last_request.env['rack.input'].read(128)
=> "{\"id\":1}"

but in this repository's environment, it's not readable unless you rewind it by yourself:

From: /app/spec/app/api_spec.rb:13 :

     8:   describe 'Users' do
     9:     it 'POST /users' do
    10:       header 'CONTENT_TYPE', 'application/json'
    11:       json_data = { name: 'juan'}.to_json
    12:       post '/users', json_data, { 'Content-Type' => 'application/json' }
 => 13:       require "pry";binding.pry
    14:       expect(last_response.status).to eq(201)
    15:     end
    16:
    17:     it 'GET /users' do
    18:       get '/users'

[1] pry(#<RSpec::ExampleGroups::API::Users>)> last_request.env['rack.input'].read(128)
=> nil
[2] pry(#<RSpec::ExampleGroups::API::Users>)> last_request.env['rack.input'].tap(&:rewind).read(128)
=> "{\"name\":\"juan\"}"

Do you have any idea why this happens? Obviously we can fix this by just calling rewind, so I'm okay with it, but I'm curious about what makes the difference.

@nicopaez
Copy link
Author

I think that is because of the way I am reading the json when the padrino application wants to access the posted data.

      def user_params
        @body ||= request.body.read
        JSON.parse(@body).symbolize_keys
      end

Up to what I know this is usual method when using padrino/sinatra.

@k0kubun
Copy link
Collaborator

k0kubun commented Feb 20, 2021

Fixed it in v0.3.14. Please try the version.

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

2 participants