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

undefined method body and code for nil #21

Open
chaadow opened this issue Feb 24, 2023 · 6 comments
Open

undefined method body and code for nil #21

chaadow opened this issue Feb 24, 2023 · 6 comments

Comments

@chaadow
Copy link

chaadow commented Feb 24, 2023

I believe since the response is nil.. then open-uri tries to call resp.code which does not work

image

IoMonitor.configure do |config|
  config.publish = :logs
  config.warn_threshold = 0.8 
  config.adapters = [:active_record, :net_http, :redis] 
end
@chaadow
Copy link
Author

chaadow commented Feb 24, 2023

For the response body, here is an example of a unit test doing a GET request ( as you can see, this is from the main branch, not 0.2.0 which is outdated:
image

(the error comes from line 40 in io_controller in the gem)

@DmitryTsepelev
Copy link
Owner

Hey @chaadow! I'm trying to reproduce it, but I cannot recreate a case when response is nil: even if I do render text: '' or head :ok I do have payload[:response] filled. Could you please tell me how you do it in the controller?

@wrmk
Copy link

wrmk commented Jun 13, 2023

Hi, faced the same problem undefined method 'body' for nil:NilClass in tests when verifying that controller will raise an error

test:

    assert_raises ActiveRecord::RecordNotFound do
      get new_public_object_path(attr: "test")
    end

controller:

attr = Attr.find_by!(attr: params[:attr]]

Or when the user wants access to a page without authorization, we redirect him to the auth page. Authorization via Devise gem.

@greenfork
Copy link

When using Devise for authorization and accessing a not authorized page, the payload[:response] equals to nil.

Here is a request to a page that is not available to not signed in users:

    29: def append_info_to_payload(payload)
    30:   super
    31:
    32:   return unless monitors_action?(action_name)
    33:
    34:   data = payload[IoMonitor::NAMESPACE] = {}
    35:
    36:   aggregator.sources.each do |source|
    37:     data[source] = aggregator.get(source)
    38:   end
    39:
    40:   binding.pry
 => 41:   data[:response] = payload[:response].body.bytesize
    42: end

[1] pry(#<Hub::TasksController>)> payload
=> {:controller=>"Hub::TasksController",
 :action=>"index",
 :request=>#<ActionDispatch::Request GET "http://localhost:3000/hub/tasks" for ::1>,
 :params=>{"controller"=>"hub/tasks", "action"=>"index"},
 :headers=>
  #<ActionDispatch::Http::Headers:0x00007fba2960d1b0
   @req=#<ActionDispatch::Request GET "http://localhost:3000/hub/tasks" for ::1>>,
 :format=>:html,
 :method=>"GET",
 :path=>"/hub/tasks",
 :view_runtime=>nil,
 :db_runtime=>1.9763230085372925,
 :io_monitor=>{:active_record=>489}}

Here is also the response variable:

[1] pry(#<Hub::TasksController>)> response
=> #<ActionDispatch::Response:0x00007fb9beb601f0
 @cache_control={},
 @committed=false,
 @cv=
  #<MonitorMixin::ConditionVariable:0x00007fba2987ed68
   @cond=#<Thread::ConditionVariable:0x00007fba2987ed40>,
   @monitor=#<Monitor:0x00007fba2987ede0>>,
 @header=
  {"X-Frame-Options"=>"SAMEORIGIN",
   "X-XSS-Protection"=>"0",
   "X-Content-Type-Options"=>"nosniff",
   "X-Download-Options"=>"noopen",
   "X-Permitted-Cross-Domain-Policies"=>"none",
   "Referrer-Policy"=>"strict-origin-when-cross-origin"},
 @mon_data=#<Monitor:0x00007fba2987ede0>,
 @mon_data_owner_object_id=222560,
 @request=#<ActionDispatch::Request GET "http://localhost:3000/hub/tasks" for ::1>,
 @sending=false,
 @sent=false,
 @status=200,
 @stream=
  #<ActionDispatch::Response::Buffer:0x00007fb9be755fb0
   @buf=[],
   @closed=false,
   @response=#<ActionDispatch::Response:0x00007fb9beb601f0 ...>,
   @str_body=nil>>

If we stub this payload[:response]:

[2] pry(#<Hub::TasksController>)> payload[:response]={"body" => {"bytesize"=>1}}
=> {"body"=>{"bytesize"=>1}}
[3] pry(#<Hub::TasksController>)>

Completed 401 Unauthorized in 231635ms (ActiveRecord: 2.0ms | ActiveRecord Payload: 489 Bytes | Response Payload: 1 Byte | Allocations: 1444774)


Started GET "/users/sign_in" for ::1 at 2023-06-26 17:47:24 +0600
Processing by UsersDevise::SessionsController#new as HTML
  Rendering layout layouts/public/application.html.slim
  Rendering devise/sessions/new.html.slim within layouts/public/application
  Rendered shared/_notification.html.slim (Duration: 0.4ms | Allocations: 165)
  Rendered devise/sessions/new.html.slim within layouts/public/application (Duration: 3.4ms | Allocations: 1877)
  Rendered public/application/_favicon.html.slim (Duration: 0.2ms | Allocations: 16)
  Rendered layouts/public/_navbar.html.slim (Duration: 1.6ms | Allocations: 1332)
  Rendered shared/_footer_social_links.html.slim (Duration: 0.2ms | Allocations: 263)
  Rendered layouts/public/_footer.html.slim (Duration: 0.9ms | Allocations: 802)
  Rendered layout layouts/public/application.html.slim (Duration: 11.7ms | Allocations: 7974)

From: /home/grfork/playground/ruby/io_monitor/lib/io_monitor/controller.rb:41 IoMonitor::Controller#append_info_to_payload:

    29: def append_info_to_payload(payload)
    30:   super
    31:
    32:   return unless monitors_action?(action_name)
    33:
    34:   data = payload[IoMonitor::NAMESPACE] = {}
    35:
    36:   aggregator.sources.each do |source|
    37:     data[source] = aggregator.get(source)
    38:   end
    39:
    40:   binding.pry
 => 41:   data[:response] = payload[:response].body.bytesize
    42: end

[1] pry(#<UsersDevise::SessionsController>)> payload[:response].body.bytesize
=> 9139

then it returns 401 and initiates the next response that has payload[:response] present.

@Galathius
Copy link

Galathius commented Jul 20, 2023

Reproduced this issue with this code:

class GraphqlController < ApplicationController
  def execute
    raise StandardError
  end
end

After CURLing GQL endpoint got this:

2023-07-20 11:38:55.074216 F Rails -- Exception: NoMethodError: undefined method `body' for nil:NilClass
/Users/ikamenko/.rvm/gems/ruby-3.0.3@topteam/gems/io_monitor-1.0.0/lib/io_monitor/controller.rb:40:in `append_info_to_payload'
/Users/ikamenko/.rvm/gems/ruby-3.0.3@topteam/gems/actionpack-7.0.5/lib/action_controller/metal/instrumentation.rb:75:in `ensure in block in process_action'
/Users/ikamenko/.rvm/gems/ruby-3.0.3@topteam/gems/actionpack-7.0.5/lib/action_controller/metal/instrumentation.rb:75:in `block in process_action'
/Users/ikamenko/.rvm/gems/ruby-3.0.3@topteam/gems/activesupport-7.0.5/lib/active_support/notifications.rb:206:in `block in instrument'
/Users/ikamenko/.rvm/gems/ruby-3.0.3@topteam/gems/activesupport-7.0.5/lib/active_support/notifications/instrumenter.rb:24:in `instrument'
/Users/ikamenko/.rvm/gems/ruby-3.0.3@topteam/gems/activesupport-7.0.5/lib/active_support/notifications.rb:206:in `instrument'

This is how looks payload hash:

{:controller=>"GraphqlController",
 :action=>"execute",
 :request=>#<ActionDispatch::Request POST "http://localhost:5000/graphql?..." for 127.0.0.1>,
 :params=>
  {"operationName"=>"...",
   "variables"=>{},
   "query"=>
    "...",
   "..."=>nil,
   "controller"=>"graphql",
   "action"=>"execute",
   "graphql"=>
    {"operationName"=>"...",
     "variables"=>{},
     "query"=>
      "..."}},
 :headers=>#<ActionDispatch::Http::Headers:0x00007fc876464420 @req=#<ActionDispatch::Request POST "http://localhost:5000/graphql?..." for 127.0.0.1>>,
 :format=>:json,
 :method=>"POST",
 :path=>"/graphql?...",
 :status=>500,
 :view_runtime=>nil,
 :db_runtime=>0,
 :io_monitor=>{:active_record=>0}}

@Pagehey
Copy link

Pagehey commented Jan 11, 2024

Hi ! What's the status of this issue ?
I saw that the error was not occuring in previous version 0.2.0 thanks to simple safe navigation operators. Was there something wrong with this solution ? Couldn't it be fixed by using the same code?
Thanks !
Quite useful gem BTW ! ;-)

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

6 participants