10

Is it possible to use OAuth with HTTParty? I'm trying to do this API call, but, contradictory to the documentation, it needs authentication.

Before you say "Use a Twitter-specific Gem", hear me out--I've tried. I've tried twitter, grackle, and countless others, but none support this specific API call. So, I've turned to HTTParty.

So, how could I use OAuth with HTTParty?

skaffman
  • 398,947
  • 96
  • 818
  • 769
Ethan Turkeltaub
  • 2,931
  • 8
  • 30
  • 45
  • You could fork the twitter gem & add the method you need (see: http://github.com/jnunemaker/twitter/blob/master/lib/twitter/base.rb). Either way, the Twitter gem may be a good place to see how this is done (as it uses both HTTParty & OAuth) – Brian Aug 09 '10 at 18:04
  • 1
    Actually, It looks like the Twitter gem does have the functionality you are looking for, see lines 33-35 in http://github.com/jnunemaker/twitter/blob/master/lib/twitter/base.rb – Brian Aug 09 '10 at 18:15
  • Thanks. Didn't notice that before >. – Ethan Turkeltaub Aug 11 '10 at 12:55
  • 2
    I'm still very much interested in this answer. – user94154 Jun 12 '11 at 04:26
  • I've been looking for one myself. From the example request in a page from Twitter Dev (https://dev.twitter.com/docs/api/1/get/oauth/authenticate) I feel like there should be a way. Here's the request: `https://api.twitter.com/oauth/authenticate?oauth_token=Z6eEdO8MOmk394WozF5oKyuAv855l4Mlqo7hhlSLik` – tvalent2 May 23 '12 at 14:41

3 Answers3

3

I've been using the vanilla OAuth gem to implement a few simple Twitter API calls. I didn't need a heavyweight gem to do everything, and I was already using OAuth, so a 'roll-your-own' approach seemed reasonable. I know that I haven't mentioned HTTParty, so please don't ding me for that. This may be useful to others for the essence of easy Twitter OAuth if you're already using the OAuth gem.

In case it is helpful, here is the pertinent code (sorry about mixing some constants and other variables / methods at the start - it was the easiest and most accurate way to extract this from my real code):

#Set up the constants, etc required for Twitter OAuth
OAUTH_SITE = "https://api.twitter.com"
TOKEN_REQUEST_METHOD = :post
AUTHORIZATION_SCHEME = :header 

  def app_request_token_path 
    "/oauth/request_token"  
  end    
  def app_authorize_path 
    "/oauth/authorize"  
  end      
  def app_access_token_path        
    "/oauth/access_token"        
  end
  def consumer_key
    "your twitter API key"
  end
  def consumer_secret
    "your twitter API secret"
  end

  # Define the OAuth consumer
  def consumer meth=:post
    @consumer ||= OAuth::Consumer.new(consumer_key,consumer_secret, {
      :site => "#{OAUTH_SITE}",
      :request_token_path=>app_request_token_path,
      :authorize_path=>app_authorize_path,
      :access_token_path=>app_access_token_path,
      :http_method=>:post,
      :scheme=> :header,
      :body_hash => ''
    })
  end            

  # Essential parts of a generic OAuth request method
  def make_request url, method=:get, headers={}, content=''                  
    if method==:get
      res = @access_token.get(url, headers)
    elsif method==:post
      res = @access_token.post(url, content, headers)
    end

    if res.code.to_s=='200'
      jres = ActiveSupport::JSON.decode(res.body)
      if jres.nil?
        @last_status_text = @prev_error = "Unexpected error making an OAuth API call - response body is #{res.body}"
      end      
      return jres
    else
      @last_status_text = @prev_error = res if res.code.to_s!='200'
      return nil      
    end
  end

# Demonstrate the daily trends API call
# Note the use of memcache to ensure we don't break the rate-limiter
  def daily_trends

     url = "http://api.twitter.com/1/trends/daily.json"     
     @last_status_code = -1
     @last_status_success = false
     res = Rails.cache.fetch(url, :expires_in=> 5.minutes) do
       res = make_request(url, :get)          
       unless res
         @last_status_code = @prev_error.code.to_i
       end
       res
     end                 
     if res
         @last_status_code = 200
         @last_status_success = true
         @last_status_text = ""
     end
     return res
  end  

I hope this, largely in context of broader use of the OAuth gem, might be useful to others.

BenMorganIO
  • 2,036
  • 17
  • 37
Phil
  • 2,797
  • 1
  • 24
  • 30
  • Thanks for the edit Ismael Abreu. Catching how poorly I extracted this from other code. – Phil Jul 18 '13 at 18:24
  • Hey, I know its been a year, but can you let me know where you specify `@access_token`? I'm loving your example and targets a problem I'm beating my head against right now. – BenMorganIO May 21 '14 at 06:38
  • I wish I could help you with that. My code has diverged so much from the original since I answered that its hard to divine what was going on. But it was the third step in the exchange between your app and Twitter, when you exchange the request token for the access token. Maybe these snippets help: `request_token = params[:oauth_token]; oauth_options = {:oauth_verifier => params[:oauth_verifier]}; OAuth::RequestToken.new(consumer, request_token, consumer_secret) ; @access_token = request_token.get_access_token({:http_method=>TOKEN_REQUEST_METHOD}, params)` – Phil May 28 '14 at 15:43
1

I don't think that HTTParty supports OAuth (though I am no expert on HTTParty, it's way too high-level and slow for my taste).

I would just call the Twitter request directly using OAuth gem. Twitter API documentation even has an example of usage: https://dev.twitter.com/docs/auth/oauth/single-user-with-examples#ruby

Lukas Stejskal
  • 2,542
  • 19
  • 30
0

I used a mix of the OAuth2 gem to get the authentication token and HTTParty to make the query

client = OAuth2::Client.new(apiKey, apiSecret, 
                            :site => "https://SiteForAuthentication.com")
oauthResponse = client.password.get_token(username, password)
token = oauthResponse.token

queryAnswer = HTTParty.get('https://api.website.com/query/location', 
                            :query => {"token" => token})

Not perfect by a long way but it seems to have done the trick so far