pelle-oauth 0.3.1 → 0.3.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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)