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

Get access token only once and not before every request #441

Closed
thomasbaustert opened this Issue Aug 15, 2013 · 5 comments

Comments

Projects
None yet
4 participants
@thomasbaustert

thomasbaustert commented Aug 15, 2013

The code below raises a Twitter::Error::Forbidden: Unable to verify your credentials
after around 50 calls. (If only user_timeline or oembed is called it works.)

Note that this is not a problem of rate limits cause user_timeline allows 300 requests
for 15 minutes time window, oembed allows 180.

I guess the error is because the Twitter gem does a /oauth2/token request before every
user_timeline and oembed request, not just one at all. And twitter shuts up:

/oauth2/token
/statuses/user_timeline.json
/oauth2/token
/statuses/oembed.json
...

The same happens without the twitter gem (using Curb for example). Pseudo code:

60.times do |count|
  get_access_token
  user_timeline
  get_access_token
  oembed
end

Doing the calls with one call to /oauth2/token at the beginning works. Pseudo code:

get_access_token
60.times do |count|
  user_timeline
  oembed
end

See https://dev.twitter.com/discussions/20548 on not negotiate the token within a loop.

require "rubygems"
require "twitter" # 4.8.1

Twitter.configure do |config|
  config.consumer_key    = YOUR_COMSUMER_KEY
  config.consumer_secret = YOUR_COMSUMER_SECRET
end

60.times do |count|
  puts "request #{count+1}"

  # first get 10 tweets
  tweets = Twitter.user_timeline("torial", count: 10, exclude_replies: true)

  # second get oembed for first tweet
  Twitter.oembed(tweets.first.id, align: 'center')

  sleep 0.5
end
@paracycle

This comment has been minimized.

Collaborator

paracycle commented Aug 15, 2013

That's a good catch and a very useful error report.

I have verified the problem with the test case that you have supplied. The problem stems from the difference in behaviour of the Twitter module as opposed to Twitter::Client.

As a temporary workaround, you start creating Twitter::Client objects, and use those. For example, your test code would become:

require "rubygems"
require "twitter" # 4.8.1

twitter = Twitter::Client.new(consumer_key: YOUR_COMSUMER_KEY, consumer_secret: YOUR_COMSUMER_SECRET)

60.times do |count|
  puts "request #{count+1}"

  # first get 10 tweets
  tweets = twitter.user_timeline("torial", count: 10, exclude_replies: true)

  # second get oembed for first tweet
  twitter.oembed(tweets.first.id, align: 'center')

  sleep 0.5
end

I have narrowed the problem down to this line in twitter.rb:

      return @client if instance_variable_defined?(:@client) && @client.hash == options.hash

Since the @client variable has been modified (ie @bearer_token was set), the hash check fails and we end up returning a brand new Client object.

@sferik, I am not exactly sure how this should be mitigated? Could you point me in the right direction?

@sferik

This comment has been minimized.

Owner

sferik commented Aug 15, 2013

I’m in the process of re-thinking this interface for 5.0. For now, you can use the temporary workaround mentioned above.

@thomasbaustert

This comment has been minimized.

thomasbaustert commented Aug 15, 2013

Thanks for the quick response. I changed the code like recommended and it works now.

@halorgium

This comment has been minimized.

Collaborator

halorgium commented Aug 15, 2013

One thought would be to explicitly invalidate the default client when the configuration is modified, instead of relying on the hash check.

@sferik

This comment has been minimized.

Owner

sferik commented Aug 18, 2013

I’ve decided to remove global configuration from version 5 of the gem. This allows code simplification, removes possible confusion, and ensures that configuration is threadsafe.

@sferik sferik closed this Aug 18, 2013

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment