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 `strip' for an instance of Hash #301

Open
swombat opened this issue Sep 4, 2024 · 4 comments
Open

undefined method `strip' for an instance of Hash #301

swombat opened this issue Sep 4, 2024 · 4 comments

Comments

@swombat
Copy link

swombat commented Sep 4, 2024

After much, much, much debugging, while getting the mysterious error undefined method strip' for an instance of Hash` (btw, whoever decided to catch that error and print it out and carry on without providing the stack trace... I hope you take a good long look at yourself in the mirror some day)...

I ended up diagnosing it as an issue with a parameter has being passed into net/http.

The full stack trace:

undefined method `strip' for an instance of Hash
======== /Users/danieltenner/.rvm/rubies/ruby-3.3.1/lib/ruby/3.3.0/net/http/header.rb:194:in `block in initialize_http_header'
/Users/danieltenner/.rvm/rubies/ruby-3.3.1/lib/ruby/3.3.0/net/http/header.rb:189:in `each'
/Users/danieltenner/.rvm/rubies/ruby-3.3.1/lib/ruby/3.3.0/net/http/header.rb:189:in `initialize_http_header'
/Users/danieltenner/.rvm/rubies/ruby-3.3.1/lib/ruby/3.3.0/net/http/generic_request.rb:51:in `initialize'
/Users/danieltenner/.rvm/gems/ruby-3.3.1/gems/faraday-net_http-3.1.1/lib/faraday/adapter/net_http.rb:79:in `new'
/Users/danieltenner/.rvm/gems/ruby-3.3.1/gems/faraday-net_http-3.1.1/lib/faraday/adapter/net_http.rb:79:in `create_request'
/Users/danieltenner/.rvm/gems/ruby-3.3.1/gems/faraday-net_http-3.1.1/lib/faraday/adapter/net_http.rb:112:in `block in request_with_wrapped_block'
/Users/danieltenner/.rvm/rubies/ruby-3.3.1/lib/ruby/3.3.0/net/http.rb:1570:in `start'
/Users/danieltenner/.rvm/gems/ruby-3.3.1/gems/faraday-net_http-3.1.1/lib/faraday/adapter/net_http.rb:111:in `request_with_wrapped_block'
/Users/danieltenner/.rvm/gems/ruby-3.3.1/gems/faraday-net_http-3.1.1/lib/faraday/adapter/net_http.rb:101:in `perform_request'
/Users/danieltenner/.rvm/gems/ruby-3.3.1/gems/faraday-net_http-3.1.1/lib/faraday/adapter/net_http.rb:65:in `block in call'
/Users/danieltenner/.rvm/gems/ruby-3.3.1/gems/faraday-2.10.1/lib/faraday/adapter.rb:45:in `connection'
/Users/danieltenner/.rvm/gems/ruby-3.3.1/gems/faraday-net_http-3.1.1/lib/faraday/adapter/net_http.rb:64:in `call'
/Users/danieltenner/.rvm/gems/ruby-3.3.1/gems/faraday-2.10.1/lib/faraday/middleware.rb:56:in `call'
/Users/danieltenner/.rvm/gems/ruby-3.3.1/gems/faraday-2.10.1/lib/faraday/rack_builder.rb:152:in `build_response'
/Users/danieltenner/.rvm/gems/ruby-3.3.1/gems/faraday-2.10.1/lib/faraday/connection.rb:444:in `run_request'
/Users/danieltenner/.rvm/gems/ruby-3.3.1/gems/faraday-2.10.1/lib/faraday/connection.rb:200:in `get'
/Users/danieltenner/.rvm/gems/ruby-3.3.1/gems/xero-ruby-9.2.0/lib/xero-ruby/api_client.rb:319:in `public_send'
/Users/danieltenner/.rvm/gems/ruby-3.3.1/gems/xero-ruby-9.2.0/lib/xero-ruby/api_client.rb:319:in `call_api'
/Users/danieltenner/.rvm/gems/ruby-3.3.1/gems/xero-ruby-9.2.0/lib/xero-ruby/api/accounting_api.rb:6339:in `get_accounts_with_http_info'
/Users/danieltenner/.rvm/gems/ruby-3.3.1/gems/xero-ruby-9.2.0/lib/xero-ruby/api/accounting_api.rb:6275:in `get_accounts'
/Users/danieltenner/dev/[...]/app/apis/xero_api.rb:60:in `get_accounts'

This is happening because the initheader parameter passed to net/http/header.rb's initialize_http_header method is:

{"Content-Type"=>"application/json", "User-Agent"=>"xero-ruby-9.2.0", 
"Accept"=>"application/json", "Xero-tenant-id"=>{"id"=>"[snip]", "authEventId"=>"[snip]", 
"tenantId"=>"[snip]", "tenantType"=>"ORGANISATION", "tenantName"=>"[snip]", 
"createdDateUtc"=>"2024-09-04T15:17:17.9469550", "updatedDateUtc"=>"2024-09-04T15:17:17.9483740"}, "Authorization"=>"Bearer [snip]", 
"accept-encoding"=>"gzip;q=1.0,deflate;q=0.6,identity;q=0.3"}

Notice Xero-tenant-id is a hash.

initialize_http_header then dutifully chokes on it because it expects string parameters:

  def initialize_http_header(initheader) #:nodoc:
    @header = {}
    return unless initheader
    initheader.each do |key, value|
      warn "net/http: duplicated HTTP header: #{key}", uplevel: 3 if key?(key) and $VERBOSE
      if value.nil?
        warn "net/http: nil HTTP header: #{key}", uplevel: 3 if $VERBOSE
      else
        value = value.strip # raise error for invalid byte sequences
        if key.to_s.bytesize > MAX_KEY_LENGTH
          raise ArgumentError, "too long (#{key.bytesize} bytes) header: #{key[0, 30].inspect}..."
        end
        if value.to_s.bytesize > MAX_FIELD_LENGTH
          raise ArgumentError, "header #{key} has too long field value: #{value.bytesize}"
        end
        if value.count("\r\n") > 0
          raise ArgumentError, "header #{key} has field value #{value.inspect}, this cannot include CR/LF"
        end
        @header[key.downcase.to_s] = [value]
      end
    end
  end

Haven't got a solution or workaround yet, but thought i'd put this here in case it helps someone. Will report back once I do have a solution, whatever it is.

Copy link

github-actions bot commented Sep 4, 2024

PETOSS-568

Copy link

github-actions bot commented Sep 4, 2024

Thanks for raising an issue, a ticket has been created to track your request

@swombat
Copy link
Author

swombat commented Sep 4, 2024

I believe I have figured this out! Documenting here as it may help others.

The README suggests that xero_client.last_connection "returns the xero-tenant-id of the most recently connected Xero org".

But that's not true. It returns a hash. And inside that is ["id"] - which is the thing you need to pass to, e.g., get_accounts.

So this bug is fixed by changing:

@api_client.accounting_api.get_accounts(@api_client.last_connection)

To

@api_client.accounting_api.get_accounts(@api_client.last_connection["id"])

Easy fix but fiendishly hard to debug. Hope this helps someone!

@swombat swombat closed this as completed Sep 4, 2024
@swombat
Copy link
Author

swombat commented Sep 5, 2024

Actually perhaps worth reopening as this is an easy documentation fix.

@swombat swombat reopened this Sep 5, 2024
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

1 participant