Class: Appsignal::Rack::BodyWrapper Private
- Defined in:
- lib/appsignal/rack/body_wrapper.rb
This class is part of a private API. You should avoid using this class if possible, as it may be removed or be changed in the future.
Direct Known Subclasses
Constant Summary collapse
- IGNORED_ERRORS =
This constant is part of a private API. You should avoid using this constant if possible, as it may be removed or be changed in the future.
[Errno::EPIPE].freeze
Class Method Summary collapse
Instance Method Summary collapse
-
#close ⇒ Object
private
This must be present in all Rack bodies and will be called by the serving adapter.
-
#initialize(body, appsignal_transaction) ⇒ BodyWrapper
constructor
private
A new instance of BodyWrapper.
-
#method_missing(method_name, *args, &block) ⇒ Object
private
Delegate missing methods to the wrapped body.
-
#respond_to_missing?(method_name, include_all = false) ⇒ Boolean
private
Return whether the wrapped body responds to the method if this class does not.
Constructor Details
#initialize(body, appsignal_transaction) ⇒ BodyWrapper
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
Returns a new instance of BodyWrapper.
39 40 41 42 43 |
# File 'lib/appsignal/rack/body_wrapper.rb', line 39 def initialize(body, appsignal_transaction) @body_already_closed = false @body = body @transaction = appsignal_transaction end |
Dynamic Method Handling
This class handles dynamic methods through the method_missing method
#method_missing(method_name, *args, &block) ⇒ Object
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
Delegate missing methods to the wrapped body. Based on: github.com/rack/rack/blob/0ed580bbe3858ffe5d530adf1bdad9ef9c03407c/lib/rack/body_proxy.rb#L44-L61
71 72 73 |
# File 'lib/appsignal/rack/body_wrapper.rb', line 71 def method_missing(method_name, *args, &block) @body.__send__(method_name, *args, &block) end |
Class Method Details
.wrap(original_body, appsignal_transaction) ⇒ Object
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 |
# File 'lib/appsignal/rack/body_wrapper.rb', line 9 def self.wrap(original_body, appsignal_transaction) # The logic of how Rack treats a response body differs based on which methods # the body responds to. This means that to support the Rack 3.x spec in full # we need to return a wrapper which matches the API of the wrapped body as closely # as possible. Pick the wrapper from the most specific to the least specific. # See https://github.com/rack/rack/blob/main/SPEC.rdoc#the-body- # # What is important is that our Body wrapper responds to the same methods Rack # (or a webserver) would be checking and calling, and passes through that functionality # to the original body. # # This comment https://github.com/rails/rails/pull/49627#issuecomment-1769802573 # is of particular interest to understand why this has to be somewhat complicated. if original_body.respond_to?(:to_path) PathableBodyWrapper.new(original_body, appsignal_transaction) elsif original_body.respond_to?(:to_ary) ArrayableBodyWrapper.new(original_body, appsignal_transaction) elsif !original_body.respond_to?(:each) && original_body.respond_to?(:call) # This body only supports #call, so we must be running a Rack 3 application # It is possible that a body exposes both `each` and `call` in the hopes of # being backwards-compatible with both Rack 3.x and Rack 2.x, however # this is not going to work since the SPEC says that if both are available, # `each` should be used and `call` should be ignored. # So for that case we can drop to our default EnumerableBodyWrapper CallableBodyWrapper.new(original_body, appsignal_transaction) else EnumerableBodyWrapper.new(original_body, appsignal_transaction) end end |
Instance Method Details
#close ⇒ Object
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
This must be present in all Rack bodies and will be called by the serving adapter
46 47 48 49 50 51 52 53 54 55 56 57 58 59 |
# File 'lib/appsignal/rack/body_wrapper.rb', line 46 def close # The @body_already_closed check is needed so that if `to_ary` # of the body has already closed itself (as prescribed) we do not # attempt to close it twice if !@body_already_closed && @body.respond_to?(:close) Appsignal.instrument("close_response_body.rack") { @body.close } end @body_already_closed = true rescue *IGNORED_ERRORS # Do not report raise rescue Exception => error # rubocop:disable Lint/RescueException appsignal_report_error(error) raise error end |
#respond_to_missing?(method_name, include_all = false) ⇒ Boolean
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
Return whether the wrapped body responds to the method if this class does not. Based on: github.com/rack/rack/blob/0ed580bbe3858ffe5d530adf1bdad9ef9c03407c/lib/rack/body_proxy.rb#L16-L24
64 65 66 |
# File 'lib/appsignal/rack/body_wrapper.rb', line 64 def respond_to_missing?(method_name, include_all = false) super || @body.respond_to?(method_name, include_all) end |