Skip to content

Commit

Permalink
Fix authentication bug
Browse files Browse the repository at this point in the history
Closes #291.
  • Loading branch information
sferik committed Jul 19, 2012
1 parent 900d664 commit b1fc6ea
Show file tree
Hide file tree
Showing 3 changed files with 38 additions and 26 deletions.
16 changes: 8 additions & 8 deletions lib/twitter/client.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2856,19 +2856,13 @@ def connection
end

# Perform an HTTP request
def request(method, path, params, options)
def request(method, path, params={}, options={})
uri = options[:endpoint] || @endpoint
uri = URI(uri) unless uri.respond_to?(:host)
uri += path
request_headers = {}
if self.credentials?
# When posting a file, don't sign any params
signature_params = if [:post, :put].include?(method.to_sym) && params.values.any?{|value| value.is_a?(File) || (value.is_a?(Hash) && (value[:io].is_a?(IO) || value[:io].is_a?(StringIO)))}
{}
else
params
end
authorization = SimpleOAuth::Header.new(method, uri, signature_params, credentials)
authorization = auth_header(method, uri, params)
request_headers[:authorization] = authorization.to_s
end
connection.url_prefix = options[:endpoint] || @endpoint
Expand All @@ -2889,5 +2883,11 @@ def request(method, path, params, options)
raise Twitter::Error::ClientError
end

def auth_header(method, uri, params={})
# When posting a file, don't sign any params
signature_params = [:post, :put].include?(method.to_sym) && params.values.any?{|value| value.is_a?(File) || (value.is_a?(Hash) && (value[:io].is_a?(IO) || value[:io].is_a?(StringIO)))} ? {} : params
SimpleOAuth::Header.new(method, uri, signature_params, credentials)
end

end
end
12 changes: 9 additions & 3 deletions lib/twitter/configurable.rb
Original file line number Diff line number Diff line change
Expand Up @@ -58,10 +58,16 @@ def reset!
private

# @return [Hash]
# @note After Ruby 1.8 is deprecated, can be rewritten as:
# options.select{|key| AUTH_KEYS.include?(key)}
# @todo In version 4, rename to oauth_token to token and oauth_token_secret
# to token_secret and rewrite as:
# options.select{|key| AUTH_KEYS.include?(key)}
def credentials
Hash[options.select{|key, value| AUTH_KEYS.include?(key)}]
{
:consumer_key => @consumer_key,
:consumer_secret => @consumer_secret,
:token => @oauth_token,
:token_secret => @oauth_token_secret,
}
end

# @return [Hash]
Expand Down
36 changes: 21 additions & 15 deletions spec/twitter/client_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
describe Twitter::Client do

subject do
client = Twitter::Client.new
client = Twitter::Client.new(:consumer_key => "CK", :consumer_secret => "CS", :oauth_token => "OT", :oauth_token_secret => "OS")
client.class_eval{public *Twitter::Client.private_instance_methods}
client
end
Expand Down Expand Up @@ -92,30 +92,26 @@
end

describe "#rate_limited?" do
before do
@client = Twitter::Client.new
end
it "returns true for rate limited methods" do
@client.rate_limited?(:user).should be_true
subject.rate_limited?(:user).should be_true
end
it "returns false for rate limited methods" do
@client.rate_limited?(:rate_limit_status).should be_false
subject.rate_limited?(:rate_limit_status).should be_false
end
it "raises an ArgumentError for non-existant methods" do
lambda do
@client.rate_limited?(:foo)
subject.rate_limited?(:foo)
end.should raise_error(ArgumentError, "no method `foo' for Twitter::Client")
end
end

describe "#put" do
before do
@client = Twitter::Client.new
stub_put("/custom/put").
with(:body => {:updated => "object"})
end
it "allows custom put requests" do
@client.put("/custom/put", {:updated => "object"})
subject.put("/custom/put", {:updated => "object"})
a_put("/custom/put").
with(:body => {:updated => "object"}).
should have_been_made
Expand Down Expand Up @@ -144,31 +140,41 @@
end

describe "#request" do
before do
@client = Twitter::Client.new({:consumer_key => "CK", :consumer_secret => "CS", :oauth_token => "OT", :oauth_token_secret => "OS"})
end
it "encodes the entire body when no uploaded media is present" do
stub_post("/1/statuses/update.json").
with(:body => {:status => "Update"}).
to_return(:body => fixture("status.json"), :headers => {:content_type => "application/json; charset=utf-8"})
@client.update("Update")
subject.update("Update")
a_post("/1/statuses/update.json").
with(:body => {:status => "Update"}).
should have_been_made
end
it "encodes none of the body when uploaded media is present" do
stub_post("/1/statuses/update_with_media.json", "https://upload.twitter.com").
to_return(:body => fixture("status_with_media.json"), :headers => {:content_type => "application/json; charset=utf-8"})
@client.update_with_media("Update", fixture("pbjt.gif"))
subject.update_with_media("Update", fixture("pbjt.gif"))
a_post("/1/statuses/update_with_media.json", "https://upload.twitter.com").
should have_been_made
end
it "catches Faraday errors" do
subject.stub!(:connection).and_raise(Faraday::Error::ClientError.new("Oups"))
lambda do
subject.request(:get, "/path", {}, {})
subject.request(:get, "/path")
end.should raise_error(Twitter::Error::ClientError, "Oups")
end
end

describe "#auth_header" do
it "creates the correct auth headers" do
uri = URI("https://api.twitter.com/1/direct_messages.json")
authorization = subject.auth_header(:get, uri)
authorization.options[:signature_method].should == "HMAC-SHA1"
authorization.options[:version].should == "1.0"
authorization.options[:consumer_key].should == "CK"
authorization.options[:consumer_secret].should == "CS"
authorization.options[:token].should == "OT"
authorization.options[:token_secret].should == "OS"
end
end

end

0 comments on commit b1fc6ea

Please sign in to comment.