pelle-oauth 0.3.1 → 0.3.5

Sign up to get free protection for your applications and to get access to all the features.
Files changed (54) hide show
  1. data/History.txt +66 -17
  2. data/Manifest.txt +14 -1
  3. data/README.rdoc +7 -9
  4. data/Rakefile +7 -5
  5. data/TODO +17 -0
  6. data/bin/oauth +2 -2
  7. data/examples/yql.rb +44 -0
  8. data/lib/oauth.rb +1 -0
  9. data/lib/oauth/cli.rb +279 -31
  10. data/lib/oauth/client/action_controller_request.rb +14 -12
  11. data/lib/oauth/client/helper.rb +22 -14
  12. data/lib/oauth/client/net_http.rb +53 -22
  13. data/lib/oauth/consumer.rb +217 -111
  14. data/lib/oauth/errors.rb +3 -0
  15. data/lib/oauth/errors/error.rb +4 -0
  16. data/lib/oauth/errors/problem.rb +14 -0
  17. data/lib/oauth/errors/unauthorized.rb +12 -0
  18. data/lib/oauth/helper.rb +67 -6
  19. data/lib/oauth/oauth.rb +11 -0
  20. data/lib/oauth/oauth_test_helper.rb +12 -13
  21. data/lib/oauth/request_proxy/action_controller_request.rb +8 -8
  22. data/lib/oauth/request_proxy/base.rb +102 -44
  23. data/lib/oauth/request_proxy/jabber_request.rb +1 -2
  24. data/lib/oauth/request_proxy/mock_request.rb +8 -0
  25. data/lib/oauth/request_proxy/net_http.rb +2 -2
  26. data/lib/oauth/request_proxy/rack_request.rb +7 -7
  27. data/lib/oauth/server.rb +31 -33
  28. data/lib/oauth/signature.rb +9 -0
  29. data/lib/oauth/signature/base.rb +23 -21
  30. data/lib/oauth/signature/hmac/base.rb +1 -1
  31. data/lib/oauth/signature/hmac/sha1.rb +0 -1
  32. data/lib/oauth/signature/plaintext.rb +2 -2
  33. data/lib/oauth/signature/rsa/sha1.rb +5 -4
  34. data/lib/oauth/token.rb +6 -136
  35. data/lib/oauth/tokens/access_token.rb +68 -0
  36. data/lib/oauth/tokens/consumer_token.rb +33 -0
  37. data/lib/oauth/tokens/request_token.rb +32 -0
  38. data/lib/oauth/tokens/server_token.rb +9 -0
  39. data/lib/oauth/tokens/token.rb +17 -0
  40. data/lib/oauth/version.rb +1 -1
  41. data/oauth.gemspec +13 -7
  42. data/test/cases/spec/1_0-final/test_construct_request_url.rb +1 -1
  43. data/test/test_access_token.rb +28 -0
  44. data/test/test_action_controller_request_proxy.rb +105 -6
  45. data/test/test_consumer.rb +41 -5
  46. data/test/test_helper.rb +0 -5
  47. data/test/test_net_http_client.rb +38 -20
  48. data/test/test_net_http_request_proxy.rb +43 -8
  49. data/test/test_oauth_helper.rb +50 -0
  50. data/test/test_request_token.rb +53 -0
  51. data/test/test_server.rb +1 -1
  52. data/test/test_signature.rb +19 -11
  53. data/website/index.html +2 -2
  54. metadata +46 -6
@@ -4,9 +4,9 @@ require 'action_controller/test_process'
4
4
 
5
5
  module ActionController
6
6
  class Base
7
- def process_with_oauth(request,response=nil)
7
+ def process_with_oauth(request, response=nil)
8
8
  request.apply_oauth!
9
- process_without_oauth(request,response)
9
+ process_without_oauth(request, response)
10
10
  end
11
11
 
12
12
  alias_method_chain :process, :oauth
@@ -18,21 +18,23 @@ module ActionController
18
18
  end
19
19
 
20
20
  def self.use_oauth?
21
- @use_oauth
21
+ @use_oauth
22
22
  end
23
23
 
24
24
  def configure_oauth(consumer = nil, token = nil, options = {})
25
- @oauth_options = { :consumer => consumer,
26
- :token => token,
27
- :scheme => 'header',
28
- :signature_method => nil,
29
- :nonce => nil,
30
- :timestamp => nil }.merge(options)
25
+ @oauth_options = { :consumer => consumer,
26
+ :token => token,
27
+ :scheme => 'header',
28
+ :signature_method => nil,
29
+ :nonce => nil,
30
+ :timestamp => nil }.merge(options)
31
31
  end
32
32
 
33
33
  def apply_oauth!
34
34
  return unless ActionController::TestRequest.use_oauth? && @oauth_options
35
- @oauth_helper = OAuth::Client::Helper.new(self, @oauth_options.merge( { :request_uri => request_uri } ))
35
+
36
+ @oauth_helper = OAuth::Client::Helper.new(self, @oauth_options.merge(:request_uri => request_uri))
37
+ @oauth_helper.amend_user_agent_header(env)
36
38
 
37
39
  self.send("set_oauth_#{@oauth_options[:scheme]}")
38
40
  end
@@ -43,9 +45,9 @@ module ActionController
43
45
 
44
46
  def set_oauth_parameters
45
47
  @query_parameters = @oauth_helper.parameters_with_oauth
46
- @query_parameters.merge!( { :oauth_signature => @oauth_helper.signature } )
48
+ @query_parameters.merge!(:oauth_signature => @oauth_helper.signature)
47
49
  end
48
-
50
+
49
51
  def set_oauth_query_string
50
52
  end
51
53
  end
@@ -2,12 +2,13 @@ require 'oauth/client'
2
2
  require 'oauth/consumer'
3
3
  require 'oauth/helper'
4
4
  require 'oauth/token'
5
+ require 'oauth/version'
5
6
  require 'oauth/signature/hmac/sha1'
6
7
 
7
8
  module OAuth::Client
8
9
  class Helper
9
10
  include OAuth::Helper
10
-
11
+
11
12
  def initialize(request, options = {})
12
13
  @request = request
13
14
  @options = options
@@ -26,37 +27,44 @@ module OAuth::Client
26
27
  options[:timestamp] ||= generate_timestamp
27
28
  end
28
29
 
29
- def generate_timestamp
30
- Time.now.to_i.to_s
31
- end
32
-
33
30
  def oauth_parameters
34
31
  {
32
+ 'oauth_callback' => options[:oauth_callback],
35
33
  'oauth_consumer_key' => options[:consumer].key,
36
34
  'oauth_token' => options[:token] ? options[:token].token : '',
37
35
  'oauth_signature_method' => options[:signature_method],
38
36
  'oauth_timestamp' => timestamp,
39
37
  'oauth_nonce' => nonce,
38
+ 'oauth_verifier' => options[:oauth_verifier],
40
39
  'oauth_version' => '1.0'
41
- }.reject { |k,v| v == "" }
40
+ }.reject { |k,v| v.to_s == "" }
42
41
  end
43
42
 
44
43
  def signature(extra_options = {})
45
44
  OAuth::Signature.sign(@request, { :uri => options[:request_uri],
46
- :consumer => options[:consumer],
47
- :token => options[:token] }.merge(extra_options) )
45
+ :consumer => options[:consumer],
46
+ :token => options[:token] }.merge(extra_options) )
48
47
  end
49
48
 
50
49
  def signature_base_string(extra_options = {})
51
- OAuth::Signature.signature_base_string(@request, { :uri => options[:request_uri],
52
- :consumer => options[:consumer],
53
- :token => options[:token],
54
- :parameters => oauth_parameters}.merge(extra_options) )
50
+ OAuth::Signature.signature_base_string(@request, { :uri => options[:request_uri],
51
+ :consumer => options[:consumer],
52
+ :token => options[:token],
53
+ :parameters => oauth_parameters}.merge(extra_options) )
54
+ end
55
+
56
+ def amend_user_agent_header(headers)
57
+ @oauth_ua_string ||= "OAuth gem v#{OAuth::VERSION}"
58
+ if headers['User-Agent']
59
+ headers['User-Agent'] += " (#{@oauth_ua_string})"
60
+ else
61
+ headers['User-Agent'] = @oauth_ua_string
62
+ end
55
63
  end
56
64
 
57
65
  def header
58
66
  parameters = oauth_parameters
59
- parameters.merge!( { 'oauth_signature' => signature( options.merge({ :parameters => parameters }) ) } )
67
+ parameters.merge!('oauth_signature' => signature(options.merge(:parameters => parameters)))
60
68
 
61
69
  header_params_str = parameters.map { |k,v| "#{k}=\"#{escape(v)}\"" }.join(', ')
62
70
 
@@ -69,7 +77,7 @@ module OAuth::Client
69
77
  end
70
78
 
71
79
  def parameters_with_oauth
72
- oauth_parameters.merge( parameters )
80
+ oauth_parameters.merge(parameters)
73
81
  end
74
82
  end
75
83
  end
@@ -5,43 +5,74 @@ require 'oauth/request_proxy/net_http'
5
5
  class Net::HTTPRequest
6
6
  include OAuth::Helper
7
7
 
8
+ attr_reader :oauth_helper
9
+
10
+ # Add the OAuth information to an HTTP request. Depending on the <tt>options[:scheme]</tt> setting
11
+ # this may add a header, additional query string parameters, or additional POST body parameters.
12
+ # The default scheme is +header+, in which the OAuth parameters as put into the +Authorization+
13
+ # header.
14
+ #
15
+ # * http - Configured Net::HTTP instance
16
+ # * consumer - OAuth::Consumer instance
17
+ # * token - OAuth::Token instance
18
+ # * options - Request-specific options (e.g. +request_uri+, +consumer+, +token+, +scheme+,
19
+ # +signature_method+, +nonce+, +timestamp+)
20
+ #
21
+ # This method also modifies the <tt>User-Agent</tt> header to add the OAuth gem version.
22
+ #
23
+ # See Also: {OAuth core spec version 1.0, section 5.4.1}[http://oauth.net/core/1.0#rfc.section.5.4.1]
8
24
  def oauth!(http, consumer = nil, token = nil, options = {})
9
- options = { :request_uri => oauth_full_request_uri(http),
10
- :consumer => consumer,
11
- :token => token,
12
- :scheme => 'header',
25
+ options = { :request_uri => oauth_full_request_uri(http),
26
+ :consumer => consumer,
27
+ :token => token,
28
+ :scheme => 'header',
13
29
  :signature_method => nil,
14
- :nonce => nil,
15
- :timestamp => nil }.merge(options)
30
+ :nonce => nil,
31
+ :timestamp => nil }.merge(options)
16
32
 
17
33
  @oauth_helper = OAuth::Client::Helper.new(self, options)
34
+ @oauth_helper.amend_user_agent_header(self)
18
35
  self.send("set_oauth_#{options[:scheme]}")
19
36
  end
20
37
 
38
+ # Create a string suitable for signing for an HTTP request. This process involves parameter
39
+ # normalization as specified in the OAuth specification. The exact normalization also depends
40
+ # on the <tt>options[:scheme]</tt> being used so this must match what will be used for the request
41
+ # itself. The default scheme is +header+, in which the OAuth parameters as put into the +Authorization+
42
+ # header.
43
+ #
44
+ # * http - Configured Net::HTTP instance
45
+ # * consumer - OAuth::Consumer instance
46
+ # * token - OAuth::Token instance
47
+ # * options - Request-specific options (e.g. +request_uri+, +consumer+, +token+, +scheme+,
48
+ # +signature_method+, +nonce+, +timestamp+)
49
+ #
50
+ # See Also: {OAuth core spec version 1.0, section 9.1.1}[http://oauth.net/core/1.0#rfc.section.9.1.1]
21
51
  def signature_base_string(http, consumer = nil, token = nil, options = {})
22
- options = { :request_uri => oauth_full_request_uri(http),
23
- :consumer => consumer,
24
- :token => token,
25
- :scheme => 'header',
52
+ options = { :request_uri => oauth_full_request_uri(http),
53
+ :consumer => consumer,
54
+ :token => token,
55
+ :scheme => 'header',
26
56
  :signature_method => nil,
27
- :nonce => nil,
28
- :timestamp => nil }.merge(options)
57
+ :nonce => nil,
58
+ :timestamp => nil }.merge(options)
29
59
 
30
60
  OAuth::Client::Helper.new(self, options).signature_base_string
31
61
  end
32
-
33
- def oauth_helper
34
- @oauth_helper
35
- end
36
- private
62
+
63
+ private
37
64
 
38
65
  def oauth_full_request_uri(http)
39
66
  uri = URI.parse(self.path)
40
67
  uri.host = http.address
41
68
  uri.port = http.port
42
- if http.respond_to?(:use_ssl?)
43
- uri.scheme = http.use_ssl? ? 'https' : 'http'
69
+
70
+ if http.respond_to?(:use_ssl?) && http.use_ssl?
71
+ uri.scheme = "https"
72
+ else
73
+ uri.scheme = "http"
44
74
  end
75
+
45
76
  uri.to_s
46
77
  end
47
78
 
@@ -59,10 +90,10 @@ class Net::HTTPRequest
59
90
  end
60
91
 
61
92
  def set_oauth_query_string
62
- oauth_params_str = @oauth_helper.oauth_parameters.map { |k,v| "#{k}=#{v}" }.join("&")
93
+ oauth_params_str = @oauth_helper.oauth_parameters.map { |k,v| [escape(k), escape(v)] * "=" }.join("&")
63
94
 
64
95
  uri = URI.parse(path)
65
- if !uri.query || uri.query == ''
96
+ if uri.query.to_s == ""
66
97
  uri.query = oauth_params_str
67
98
  else
68
99
  uri.query = uri.query + "&" + oauth_params_str
@@ -70,6 +101,6 @@ class Net::HTTPRequest
70
101
 
71
102
  @path = uri.to_s
72
103
 
73
- @path << "&oauth_signature=#{escape(@oauth_helper.signature)}"
104
+ @path << "&oauth_signature=#{escape(oauth_helper.signature)}"
74
105
  end
75
106
  end
@@ -1,19 +1,32 @@
1
1
  require 'net/http'
2
2
  require 'net/https'
3
+ require 'oauth/oauth'
3
4
  require 'oauth/client/net_http'
5
+ require 'oauth/errors'
6
+
4
7
  module OAuth
5
8
  class Consumer
6
-
7
- @@default_options={
9
+ # determine the certificate authority path to verify SSL certs
10
+ CA_FILES = %w(/etc/ssl/certs/ca-certificates.crt /usr/share/curl/curl-ca-bundle.crt)
11
+ CA_FILES.each do |ca_file|
12
+ if File.exists?(ca_file)
13
+ CA_FILE = ca_file
14
+ break
15
+ end
16
+ end
17
+ CA_FILE = nil unless defined?(CA_FILE)
18
+
19
+ @@default_options = {
8
20
  # Signature method used by server. Defaults to HMAC-SHA1
9
- :signature_method => 'HMAC-SHA1',
10
-
21
+ :signature_method => 'HMAC-SHA1',
22
+
11
23
  # default paths on site. These are the same as the defaults set up by the generators
12
- :request_token_path=>'/oauth/request_token',
13
- :authorize_path=>'/oauth/authorize',
14
- :access_token_path=>'/oauth/access_token',
15
-
16
- # How do we send the oauth values to the server see
24
+ :request_token_path => '/oauth/request_token',
25
+ :authorize_path => '/oauth/authorize',
26
+ :access_token_path => '/oauth/access_token',
27
+
28
+ :proxy => nil,
29
+ # How do we send the oauth values to the server see
17
30
  # http://oauth.net/core/1.0/#consumer_req_param for more info
18
31
  #
19
32
  # Possible values:
@@ -21,123 +34,179 @@ module OAuth
21
34
  # :header - via the Authorize header (Default) ( option 1. in spec)
22
35
  # :body - url form encoded in body of POST request ( option 2. in spec)
23
36
  # :query_string - via the query part of the url ( option 3. in spec)
24
- :scheme=>:header,
25
-
37
+ :scheme => :header,
38
+
26
39
  # Default http method used for OAuth Token Requests (defaults to :post)
27
- :http_method=>:post,
28
-
29
- :oauth_version=>"1.0"
40
+ :http_method => :post,
41
+
42
+ :oauth_version => "1.0"
30
43
  }
31
-
32
- attr_accessor :site,:options, :key, :secret,:http
33
-
34
-
44
+
45
+ attr_accessor :options, :key, :secret
46
+ attr_writer :site, :http
47
+
35
48
  # Create a new consumer instance by passing it a configuration hash:
36
49
  #
37
- # @consumer=OAuth::Consumer.new( key,secret,{
38
- # :site=>"http://term.ie",
39
- # :scheme=>:header,
40
- # :http_method=>:post,
41
- # :request_token_path=>"/oauth/example/request_token.php",
42
- # :access_token_path=>"/oauth/example/access_token.php",
43
- # :authorize_path=>"/oauth/example/authorize.php"
50
+ # @consumer = OAuth::Consumer.new(key, secret, {
51
+ # :site => "http://term.ie",
52
+ # :scheme => :header,
53
+ # :http_method => :post,
54
+ # :request_token_path => "/oauth/example/request_token.php",
55
+ # :access_token_path => "/oauth/example/access_token.php",
56
+ # :authorize_path => "/oauth/example/authorize.php"
44
57
  # })
45
58
  #
46
59
  # Start the process by requesting a token
47
60
  #
48
- # @request_token=@consumer.get_request_token
49
- # session[:request_token]=@request_token
61
+ # @request_token = @consumer.get_request_token
62
+ # session[:request_token] = @request_token
50
63
  # redirect_to @request_token.authorize_url
51
64
  #
52
65
  # When user returns create an access_token
53
66
  #
54
- # @access_token=@request_token.get_access_token
67
+ # @access_token = @request_token.get_access_token
55
68
  # @photos=@access_token.get('/photos.xml')
56
69
  #
57
- #
58
-
59
- def initialize(consumer_key,consumer_secret,options={})
70
+ def initialize(consumer_key, consumer_secret, options = {})
71
+ @key = consumer_key
72
+ @secret = consumer_secret
73
+
60
74
  # ensure that keys are symbols
61
- @options=@@default_options.merge( options.inject({}) do |options, (key, value)|
75
+ @options = @@default_options.merge(options.inject({}) { |options, (key, value)|
62
76
  options[key.to_sym] = value
63
77
  options
64
- end)
65
- @key = consumer_key
66
- @secret = consumer_secret
78
+ })
67
79
  end
68
-
80
+
69
81
  # The default http method
70
82
  def http_method
71
- @http_method||=@options[:http_method]||:post
83
+ @http_method ||= @options[:http_method] || :post
72
84
  end
73
-
85
+
74
86
  # The HTTP object for the site. The HTTP Object is what you get when you do Net::HTTP.new
75
87
  def http
76
88
  @http ||= create_http
77
89
  end
78
-
90
+
79
91
  # Contains the root URI for this site
80
- def uri(custom_uri=nil)
92
+ def uri(custom_uri = nil)
81
93
  if custom_uri
82
- @uri = custom_uri
94
+ @uri = custom_uri
83
95
  @http = create_http # yike, oh well. less intrusive this way
84
96
  else # if no custom passed, we use existing, which, if unset, is set to site uri
85
97
  @uri ||= URI.parse(site)
86
98
  end
87
99
  end
88
-
100
+
101
+ def get_access_token(request_token, request_options = {}, *arguments)
102
+ response = token_request(http_method, (access_token_url? ? access_token_url : access_token_path), request_token, request_options, *arguments)
103
+ OAuth::AccessToken.from_hash(self, response)
104
+ end
105
+
89
106
  # Makes a request to the service for a new OAuth::RequestToken
90
- #
91
- # @request_token=@consumer.get_request_token
92
107
  #
93
- def get_request_token(request_options={}, *arguments)
94
- response=token_request(http_method,(request_token_url? ? request_token_url : request_token_path), nil, request_options, *arguments)
95
- OAuth::RequestToken.new(self,response[:oauth_token],response[:oauth_token_secret])
108
+ # @request_token = @consumer.get_request_token
109
+ #
110
+ # To include OAuth parameters:
111
+ #
112
+ # @request_token = @consumer.get_request_token \
113
+ # :oauth_callback => "http://example.com/cb"
114
+ #
115
+ # To include application-specific parameters:
116
+ #
117
+ # @request_token = @consumer.get_request_token({}, :foo => "bar")
118
+ #
119
+ # TODO oauth_callback should be a mandatory parameter
120
+ def get_request_token(request_options = {}, *arguments)
121
+ # if oauth_callback wasn't provided, it is assumed that oauth_verifiers
122
+ # will be exchanged out of band
123
+ request_options[:oauth_callback] ||= OAuth::OUT_OF_BAND
124
+
125
+ response = token_request(http_method, (request_token_url? ? request_token_url : request_token_path), nil, request_options, *arguments)
126
+ OAuth::RequestToken.from_hash(self, response)
96
127
  end
97
-
128
+
98
129
  # Creates, signs and performs an http request.
99
130
  # It's recommended to use the OAuth::Token classes to set this up correctly.
100
- # The arguments parameters are a hash or string encoded set of parameters if it's a post request as well as optional http headers.
101
- #
102
- # @consumer.request(:get,'/people',@token,{:scheme=>:query_string})
103
- # @consumer.request(:post,'/people',@token,{},@person.to_xml,{ 'Content-Type' => 'application/xml' })
131
+ # request_options take precedence over consumer-wide options when signing
132
+ # a request.
133
+ # arguments are POST and PUT bodies (a Hash, string-encoded parameters, or
134
+ # absent), followed by additional HTTP headers.
104
135
  #
105
- def request(http_method,path, token=nil,request_options={},*arguments)
106
- if path=~/^\//
107
- _http=http
108
- else
109
- _http=create_http(path)
110
- _uri=URI.parse(path)
111
- path="#{_uri.path}#{_uri.query ? "?#{_uri.query}" : ""}"
136
+ # @consumer.request(:get, '/people', @token, { :scheme => :query_string })
137
+ # @consumer.request(:post, '/people', @token, {}, @person.to_xml, { 'Content-Type' => 'application/xml' })
138
+ #
139
+ def request(http_method, path, token = nil, request_options = {}, *arguments)
140
+ if path !~ /^\//
141
+ @http = create_http(path)
142
+ _uri = URI.parse(path)
143
+ path = "#{_uri.path}#{_uri.query ? "?#{_uri.query}" : ""}"
112
144
  end
113
- _http.request(create_signed_request(http_method,path,token,request_options,*arguments))
145
+
146
+ rsp = http.request(create_signed_request(http_method, path, token, request_options, *arguments))
147
+
148
+ # check for an error reported by the Problem Reporting extension
149
+ # (http://wiki.oauth.net/ProblemReporting)
150
+ # note: a 200 may actually be an error; check for an oauth_problem key to be sure
151
+ if !(headers = rsp.to_hash["www-authenticate"]).nil? &&
152
+ (h = headers.select { |h| h =~ /^OAuth / }).any? &&
153
+ h.first =~ /oauth_problem/
154
+
155
+ # puts "Header: #{h.first}"
156
+
157
+ # TODO doesn't handle broken responses from api.login.yahoo.com
158
+ # remove debug code when done
159
+ params = OAuth::Helper.parse_header(h.first)
160
+
161
+ # puts "Params: #{params.inspect}"
162
+ # puts "Body: #{rsp.body}"
163
+
164
+ raise OAuth::Problem.new(params.delete("oauth_problem"), rsp, params)
165
+ end
166
+
167
+ rsp
114
168
  end
115
-
169
+
116
170
  # Creates and signs an http request.
117
171
  # It's recommended to use the Token classes to set this up correctly
118
- def create_signed_request(http_method,path, token=nil,request_options={},*arguments)
119
- request=create_http_request(http_method,path,*arguments)
120
- sign!(request,token,request_options)
172
+ def create_signed_request(http_method, path, token = nil, request_options = {}, *arguments)
173
+ request = create_http_request(http_method, path, *arguments)
174
+ sign!(request, token, request_options)
121
175
  request
122
176
  end
123
-
177
+
124
178
  # Creates a request and parses the result as url_encoded. This is used internally for the RequestToken and AccessToken requests.
125
- def token_request(http_method,path,token=nil,request_options={},*arguments)
126
- response=request(http_method,path,token,request_options,*arguments)
127
- if response.code=="200"
128
- CGI.parse(response.body).inject({}){|h,(k,v)| h[k.to_sym]=v.first;h}
129
- else
130
- response.error!
179
+ def token_request(http_method, path, token = nil, request_options = {}, *arguments)
180
+ response = request(http_method, path, token, request_options, *arguments)
181
+
182
+ case response.code.to_i
183
+
184
+ when (200..299)
185
+ # symbolize keys
186
+ # TODO this could be considered unexpected behavior; symbols or not?
187
+ # TODO this also drops subsequent values from multi-valued keys
188
+ CGI.parse(response.body).inject({}) do |h,(k,v)|
189
+ h[k.to_sym] = v.first
190
+ h[k] = v.first
191
+ h
192
+ end
193
+ when (300..399)
194
+ # this is a redirect
195
+ response.error!
196
+ when (400..499)
197
+ raise OAuth::Unauthorized, response
198
+ else
199
+ response.error!
131
200
  end
132
201
  end
133
202
 
134
203
  # Sign the Request object. Use this if you have an externally generated http request object you want to sign.
135
- def sign!(request,token=nil, request_options = {})
204
+ def sign!(request, token = nil, request_options = {})
136
205
  request.oauth!(http, self, token, options.merge(request_options))
137
206
  end
138
-
207
+
139
208
  # Return the signature_base_string
140
- def signature_base_string(request,token=nil, request_options = {})
209
+ def signature_base_string(request, token = nil, request_options = {})
141
210
  request.signature_base_string(http, self, token, options.merge(request_options))
142
211
  end
143
212
 
@@ -148,90 +217,127 @@ module OAuth
148
217
  def scheme
149
218
  @options[:scheme]
150
219
  end
151
-
220
+
152
221
  def request_token_path
153
222
  @options[:request_token_path]
154
223
  end
155
-
224
+
156
225
  def authorize_path
157
226
  @options[:authorize_path]
158
227
  end
159
-
228
+
160
229
  def access_token_path
161
230
  @options[:access_token_path]
162
231
  end
163
-
232
+
164
233
  # TODO this is ugly, rewrite
165
234
  def request_token_url
166
- @options[:request_token_url]||site+request_token_path
235
+ @options[:request_token_url] || site + request_token_path
167
236
  end
168
237
 
169
238
  def request_token_url?
170
- @options[:request_token_url]!=nil
239
+ @options.has_key?(:request_token_url)
171
240
  end
172
-
241
+
173
242
  def authorize_url
174
- @options[:authorize_url]||site+authorize_path
243
+ @options[:authorize_url] || site + authorize_path
175
244
  end
176
-
245
+
177
246
  def authorize_url?
178
- @options[:authorize_url]!=nil
247
+ @options.has_key?(:authorize_url)
179
248
  end
180
249
 
181
250
  def access_token_url
182
- @options[:access_token_url]||site+access_token_path
251
+ @options[:access_token_url] || site + access_token_path
183
252
  end
184
253
 
185
254
  def access_token_url?
186
- @options[:access_token_url]!=nil
255
+ @options.has_key?(:access_token_url)
256
+ end
257
+
258
+ def proxy
259
+ @options[:proxy]
187
260
  end
188
261
 
189
- protected
190
-
191
- #Instantiates the http object
192
- def create_http(_url=nil)
193
- if _url.nil?||_url[0]=~/^\//
194
- our_uri=URI.parse(site)
262
+ protected
263
+
264
+ # Instantiates the http object
265
+ def create_http(_url = nil)
266
+ if _url.nil? || _url[0] =~ /^\//
267
+ our_uri = URI.parse(site)
268
+ else
269
+ our_uri = URI.parse(_url)
270
+ end
271
+
272
+ if proxy.nil?
273
+ http_object = Net::HTTP.new(our_uri.host, our_uri.port)
274
+ else
275
+ proxy_uri = proxy.is_a?(URI) ? proxy : URI.parse(proxy)
276
+ http_object = Net::HTTP.new(our_uri.host, our_uri.port, proxy_uri.host, proxy_uri.port, proxy_uri.user, proxy_uri.password)
277
+ end
278
+
279
+ http_object.use_ssl = (our_uri.scheme == 'https')
280
+
281
+ if CA_FILE
282
+ http_object.ca_file = CA_FILE
283
+ http_object.verify_mode = OpenSSL::SSL::VERIFY_PEER
284
+ http_object.verify_depth = 5
195
285
  else
196
- our_uri=URI.parse(_url)
286
+ http_object.verify_mode = OpenSSL::SSL::VERIFY_NONE
197
287
  end
198
- http_object=Net::HTTP.new(our_uri.host, our_uri.port)
199
- http_object.use_ssl = true if our_uri.scheme=="https"
288
+
200
289
  http_object
201
290
  end
202
-
291
+
203
292
  # create the http request object for a given http_method and path
204
- def create_http_request(http_method,path,*arguments)
205
- http_method=http_method.to_sym
206
- if [:post,:put].include?(http_method)
207
- data=arguments.shift
293
+ def create_http_request(http_method, path, *arguments)
294
+ http_method = http_method.to_sym
295
+
296
+ if [:post, :put].include?(http_method)
297
+ data = arguments.shift
298
+ data.reject! { |k,v| v.nil? } if data.is_a?(Hash)
208
299
  end
209
- headers=(arguments.first.is_a?(Hash) ? arguments.shift : {})
300
+
301
+ headers = arguments.first.is_a?(Hash) ? arguments.shift : {}
302
+
210
303
  case http_method
211
304
  when :post
212
- request=Net::HTTP::Post.new(path,headers)
213
- request["Content-Length"]=0 # Default to 0
305
+ request = Net::HTTP::Post.new(path,headers)
306
+ request["Content-Length"] = 0 # Default to 0
214
307
  when :put
215
- request=Net::HTTP::Put.new(path,headers)
216
- request["Content-Length"]=0 # Default to 0
308
+ request = Net::HTTP::Put.new(path,headers)
309
+ request["Content-Length"] = 0 # Default to 0
217
310
  when :get
218
- request=Net::HTTP::Get.new(path,headers)
311
+ request = Net::HTTP::Get.new(path,headers)
219
312
  when :delete
220
- request=Net::HTTP::Delete.new(path,headers)
313
+ request = Net::HTTP::Delete.new(path,headers)
221
314
  when :head
222
- request=Net::HTTP::Head.new(path,headers)
315
+ request = Net::HTTP::Head.new(path,headers)
223
316
  else
224
317
  raise ArgumentError, "Don't know how to handle http_method: :#{http_method.to_s}"
225
318
  end
319
+
226
320
  if data.is_a?(Hash)
227
321
  request.set_form_data(data)
228
322
  elsif data
229
- request.body=data.to_s
230
- request["Content-Length"]=request.body.length
323
+ if data.respond_to?(:read)
324
+ request.body_stream = data
325
+ if data.respond_to?(:length)
326
+ request["Content-Length"] = data.length
327
+ elsif data.respond_to?(:stat) && data.stat.respond_to?(:size)
328
+ request["Content-Length"] = data.stat.size
329
+ else
330
+ raise ArgumentError, "Don't know how to send a body_stream that doesn't respond to .length or .stat.size"
331
+ end
332
+ else
333
+ request.body = data.to_s
334
+ request["Content-Length"] = request.body.length
335
+ end
231
336
  end
337
+
232
338
  request
233
339
  end
234
-
340
+
235
341
  # Unset cached http instance because it cannot be marshalled when
236
342
  # it has already been used and use_ssl is set to true
237
343
  def marshal_dump(*args)