savonrb / httpi

Common interface for Ruby's HTTP clients
http://httpirb.com
MIT License
300 stars 150 forks source link

Use Rack::Headers to avoid deprecation warning about Rack 3 #240

Closed 3UR closed 9 months ago

3UR commented 1 year ago

This resolves #239

olleolleolle commented 1 year ago

Thanks, @3UR for updating the code.

Background: The Rack::Headers class was introduced in Rack https://github.com/rack/rack/commit/79328deacf599b92c82b9e38aced48033f3f4d2f in 3.0.

Blocker: httpi's gemspec lists rack < 3, so this can not go in yet.

https://github.com/savonrb/httpi/blob/master/httpi.gemspec#L24

And, more context to that blocker: https://github.com/savonrb/savon/issues/992

pcai commented 1 year ago

Thanks @3UR and @olleolleolle - correct, this can't go in as-is. This is unlikely to go in at all, since this is a major breaking change that affects a public API method, and we're focused on maintenance only at the moment - see also https://github.com/savonrb/httpi/issues/238

dorianmarie commented 11 months ago

Couldn't we check the Rack version and use Rack::Utils::HeaderHash or Rack::Headers accordingly?

pcai commented 11 months ago

@dorianmarie we could, but I disagree with that design choice: A library’s public API should not depend on the version of a transitive dependency. A change in API should be a change in version.

gbs4ever commented 9 months ago

so how can we silence this Rack::Utils::HeaderHash is deprecated warning

pcai commented 9 months ago

@gbs4ever

presumably you could

# config/initializers/httpi.rb

# use rack 3.x interface to silence a warning
module HTTPI
  class Response
    def initialize(code, headers, body)
      self.code = code.to_i
      self.headers = Rack::Headers.new(headers)
      self.raw_body = body
    end
  end

  class Request
    def headers
      @headers ||= Rack::Headers.new
    end
  end
end
gbs4ever commented 9 months ago

Thank you @pcai upon testing Rack::Headers.new does not take arguments which is why this is my idea


Rails.logger.warn "Rewrote Httpi due to Rack::Utils::HeaderHash.new being deprecated https://github.com/rack/rack/blob/main/UPGRADE-GUIDE.md?plain=1 "
module HTTPI
  class Response
    def initialize(code, headers, body)
      self.code = code.to_i
      self.headers = !headers.is_a?(Hash) ? Rack::Headers.new.merge!(headers) : headers
      self.raw_body = body
    end
  end

  class Request
    def headers
      @headers ||= Rack::Headers.new
    end

    def headers=(headers)
      @headers = Rack::Headers.new.merge!(headers)
    end
  end
end`
Slotos commented 9 months ago

@dorianmarie we could, but I disagree with that design choice: A library’s public API should not depend on the version of a transitive dependency. A change in API should be a change in version.

The problem lies in #headers leaking implementation details. Would it return normalized library specific headers object, the library would be free to pick and choose whichever implementation fits the bill.

gbs4ever commented 9 months ago

It seems to be incorrect this version @3UR and @pcai as Rack::Headers.new does not accept a hash as an argument see below


 Rack::Headers.new(headers) => {} vs  Rack::Utils::HeaderHash.new(headers) =>  {
  "Content-Type" => "application/json",
  "Authorization" => "Bearer your_token_here",
}

  This would be more correct

   Rack::Headers.new.merge!(headers)
pcai commented 9 months ago

Thanks everyone for your contributions.

I took some time to investigate and this is now fixed in https://github.com/savonrb/httpi/commit/56cd67bf0da61c39552be1d9fc9bff6f33315284 which ended up being relatively minor overall.

I couldn't use this PR - as others have pointed out, the code isn't correct, and it doesnt account for tests and other dependencies that need updating (namely puma 6.x)

pcai commented 9 months ago

also @Slotos re:

The problem lies in #headers leaking implementation details. Would it return normalized library specific headers object, the library would be free to pick and choose whichever implementation fits the bill.

I agree that this is a mistake in the initial API design. But there is no turning back the clock on this one unfortunately.

pcai commented 8 months ago

Since it turns out that rack 3.x and 2.x have disjoint APIs and httpi 4.x is a public API change anyway, I actually went and implemented the suggestion by @Slotos by vendoring the class: https://github.com/savonrb/httpi/pull/245

I invite participants to review this change and release strategy.