mgomes / api_auth

HMAC authentication for Rails and HTTP Clients
MIT License
480 stars 147 forks source link

Can I use HTTParty with api_auth #69

Closed moustafasallam closed 9 years ago

moustafasallam commented 9 years ago

I was wondering if I can use httparty as http client.

kjg commented 9 years ago

There is no request driver currently for HTTParty, but I'd be willing to accept a new driver if someone makes it work. Unfortunately I don't have the bandwidth right now to tackle it. From what I can tell HTTParty is just using net/http under the hood, so hopefully that means a HTTParty request driver would mostly just be passing along work to the Net::HTTP driver.

davetapley commented 8 years ago

For anyone who finds it useful, here's the approach I took to patch ApiAuth.sign! in to HTTParty:

Firstly I defined a NetHTTPRequestSigner module to patch the Net::HTTP#request method. It's job is to sign the request right before it's executed:

module NetHTTPRequestSigner
  def request(unsigned_request, body = nil)
    ApiAuth.sign! unsigned_request, 'my_access_id', 'my_secret_key'
    super
  end
end

Then I created a new subclass of HTTParty::ConnectionAdapter per the docs. Its job is to patch Net::HTTP returned by HTTParty::ConnectionAdapter, and it uses the singleton_class.prepend trick to ensure we don't pollute the Net::HTTP in general:

class RequestSigningConnectionAdapter < HTTParty::ConnectionAdapter
  def connection
    super.tap do |http|
      http.singleton_class.prepend NetHTTPRequestSigner
    end
  end
end

Now we can specify this adapter whenever we need signing, per the docs:

class MyClient
  include HTTParty
  connection_adapter RequestSigningConnectionAdapter
end
cworsley4 commented 8 years ago

@dukedave thank you for that comment! One alteration is that you need to pass the signed request to your super call.

cworsley4 commented 8 years ago

Do you have any suggestions for passing the API authentication parameters to the RequestSigner module?

TomK32 commented 8 years ago

@cworsley4 you mean like super(unsigned_request, body) ?

cworsley4 commented 8 years ago

Not quite @TomK32. You take the unsigned request and sign it with this library, then pass the returned, signed, response on to super

super(ApiAuth.sign!(unsigned_request, key, secret))