oauth 0.1.1 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of oauth might be problematic. Click here for more details.
- data/History.txt +9 -0
- data/License.txt +1 -1
- data/Manifest.txt +25 -7
- data/config/hoe.rb +1 -1
- data/lib/oauth.rb +1 -12
- data/lib/oauth/client.rb +4 -0
- data/lib/oauth/client/action_controller_request.rb +51 -0
- data/lib/oauth/client/helper.rb +74 -0
- data/lib/oauth/client/net_http.rb +72 -0
- data/lib/oauth/consumer.rb +112 -43
- data/lib/oauth/{key.rb → helper.rb} +6 -7
- data/lib/oauth/request_proxy.rb +24 -0
- data/lib/oauth/request_proxy/action_controller_request.rb +65 -0
- data/lib/oauth/request_proxy/base.rb +50 -0
- data/lib/oauth/request_proxy/net_http.rb +64 -0
- data/lib/oauth/server.rb +12 -9
- data/lib/oauth/signature.rb +15 -142
- data/lib/oauth/signature/base.rb +69 -0
- data/lib/oauth/signature/hmac/base.rb +12 -0
- data/lib/oauth/signature/hmac/md5.rb +9 -0
- data/lib/oauth/signature/hmac/rmd160.rb +9 -0
- data/lib/oauth/signature/hmac/sha1.rb +10 -0
- data/lib/oauth/signature/hmac/sha2.rb +9 -0
- data/lib/oauth/signature/md5.rb +13 -0
- data/lib/oauth/signature/plaintext.rb +19 -0
- data/lib/oauth/signature/rsa/sha1.rb +20 -0
- data/lib/oauth/signature/sha1.rb +13 -0
- data/lib/oauth/token.rb +54 -14
- data/lib/oauth/version.rb +2 -2
- data/test/test_action_controller_request_proxy.rb +10 -0
- data/test/test_consumer.rb +144 -57
- data/test/test_helper.rb +4 -0
- data/test/test_hmac_sha1.rb +21 -0
- data/test/test_net_http_client.rb +139 -0
- data/test/test_net_http_request_proxy.rb +38 -0
- data/test/test_server.rb +1 -8
- data/test/test_signature.rb +11 -113
- data/test/test_signature_base.rb +32 -0
- data/test/test_token.rb +14 -0
- data/website/index.html +9 -8
- data/website/index.txt +5 -6
- metadata +37 -13
- data/lib/oauth/consumer_credentials.rb +0 -12
- data/lib/oauth/oauth_test_helper.rb +0 -24
- data/lib/oauth/request.rb +0 -258
- data/test/test_oauth.rb +0 -11
- data/test/test_request.rb +0 -282
@@ -0,0 +1,19 @@
|
|
1
|
+
require 'oauth/signature/base'
|
2
|
+
|
3
|
+
module OAuth::Signature
|
4
|
+
class PLAINTEXT < Base
|
5
|
+
implements 'plaintext'
|
6
|
+
|
7
|
+
def signature
|
8
|
+
signature_base_string
|
9
|
+
end
|
10
|
+
|
11
|
+
def ==(cmp_signature)
|
12
|
+
signature == cmp_signature
|
13
|
+
end
|
14
|
+
|
15
|
+
def signature_base_string
|
16
|
+
secret
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
require 'oauth/signature/base'
|
2
|
+
require 'openssl'
|
3
|
+
|
4
|
+
module OAuth::Signature::RSA
|
5
|
+
class SHA1 < OAuth::Signature::Base
|
6
|
+
implements 'rsa-sha1'
|
7
|
+
|
8
|
+
def ==(cmp_signature)
|
9
|
+
public_key = OpenSSL::PKey::RSA.new(request.consumer.secret)
|
10
|
+
public_key.verify(OpenSSL::Digest::SHA1.new, cmp_signature, signature_base_string)
|
11
|
+
end
|
12
|
+
|
13
|
+
private
|
14
|
+
|
15
|
+
def digest
|
16
|
+
private_key = OpenSSL::PKey::RSA.new(request.consumer.secret)
|
17
|
+
private_key.sign(OpenSSL::Digest::SHA1.new, signature_base_string)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
data/lib/oauth/token.rb
CHANGED
@@ -1,9 +1,10 @@
|
|
1
|
+
require 'oauth/helper'
|
1
2
|
module OAuth
|
2
3
|
|
3
4
|
# Superclass for the various tokens used by OAuth
|
4
5
|
|
5
6
|
class Token
|
6
|
-
include OAuth::
|
7
|
+
include OAuth::Helper
|
7
8
|
|
8
9
|
attr_accessor :token, :secret
|
9
10
|
|
@@ -33,6 +34,21 @@ module OAuth
|
|
33
34
|
super token,secret
|
34
35
|
@consumer=consumer
|
35
36
|
end
|
37
|
+
|
38
|
+
# Make a signed request using given http_method to the path
|
39
|
+
#
|
40
|
+
# @token.request(:get,'/people')
|
41
|
+
# @token.request(:post,'/people',@person.to_xml,{ 'Content-Type' => 'application/xml' })
|
42
|
+
#
|
43
|
+
def request(http_method,path,*arguments)
|
44
|
+
response=consumer.request(http_method,path,self,{},*arguments)
|
45
|
+
end
|
46
|
+
|
47
|
+
# Sign a request generated elsewhere using Net:HTTP::Post.new or friends
|
48
|
+
def sign!(request,options = {})
|
49
|
+
consumer.sign!(request,self,options)
|
50
|
+
end
|
51
|
+
|
36
52
|
end
|
37
53
|
|
38
54
|
# The RequestToken is used for the initial Request.
|
@@ -45,9 +61,8 @@ module OAuth
|
|
45
61
|
end
|
46
62
|
|
47
63
|
# exchange for AccessToken on server
|
48
|
-
def get_access_token
|
49
|
-
|
50
|
-
response=request.perform_token_request(consumer.secret,self.secret)
|
64
|
+
def get_access_token(options={})
|
65
|
+
response=consumer.token_request(consumer.http_method,consumer.access_token_path,self,options)
|
51
66
|
OAuth::AccessToken.new(consumer,response[:oauth_token],response[:oauth_token_secret])
|
52
67
|
end
|
53
68
|
end
|
@@ -55,29 +70,54 @@ module OAuth
|
|
55
70
|
# The Access Token is used for the actual "real" web service calls thatyou perform against the server
|
56
71
|
class AccessToken<ConsumerToken
|
57
72
|
|
73
|
+
# Make a regular get request using AccessToken
|
74
|
+
#
|
75
|
+
# @response=@token.get('/people')
|
76
|
+
# @response=@token.get('/people',{'Accept'=>'application/xml'})
|
77
|
+
#
|
58
78
|
def get(path,headers={})
|
59
|
-
|
79
|
+
request(:get,path,headers)
|
60
80
|
end
|
61
81
|
|
82
|
+
# Make a regular head request using AccessToken
|
83
|
+
#
|
84
|
+
# @response=@token.head('/people')
|
85
|
+
#
|
62
86
|
def head(path,headers={})
|
63
|
-
|
87
|
+
request(:head,path,headers)
|
64
88
|
end
|
65
89
|
|
90
|
+
# Make a regular post request using AccessToken
|
91
|
+
#
|
92
|
+
# @response=@token.post('/people')
|
93
|
+
# @response=@token.post('/people',{:name=>'Bob',:email=>'bob@mailinator.com'})
|
94
|
+
# @response=@token.post('/people',{:name=>'Bob',:email=>'bob@mailinator.com'},{'Accept'=>'application/xml'})
|
95
|
+
# @response=@token.post('/people',nil,{'Accept'=>'application/xml'})
|
96
|
+
# @response=@token.post('/people',@person.to_xml,{'Accept'=>'application/xml','Content-Type' => 'application/xml'})
|
97
|
+
#
|
66
98
|
def post(path, body = '',headers={})
|
67
|
-
|
99
|
+
request(:post,path,body,headers)
|
68
100
|
end
|
69
101
|
|
102
|
+
# Make a regular put request using AccessToken
|
103
|
+
#
|
104
|
+
# @response=@token.put('/people/123')
|
105
|
+
# @response=@token.put('/people/123',{:name=>'Bob',:email=>'bob@mailinator.com'})
|
106
|
+
# @response=@token.put('/people/123',{:name=>'Bob',:email=>'bob@mailinator.com'},{'Accept'=>'application/xml'})
|
107
|
+
# @response=@token.put('/people/123',nil,{'Accept'=>'application/xml'})
|
108
|
+
# @response=@token.put('/people/123',@person.to_xml,{'Accept'=>'application/xml','Content-Type' => 'application/xml'})
|
109
|
+
#
|
70
110
|
def put(path, body = '', headers={})
|
71
|
-
|
111
|
+
request(:put,path,body,headers)
|
72
112
|
end
|
73
113
|
|
114
|
+
# Make a regular delete request using AccessToken
|
115
|
+
#
|
116
|
+
# @response=@token.delete('/people/123')
|
117
|
+
# @response=@token.delete('/people/123',{'Accept'=>'application/xml'})
|
118
|
+
#
|
74
119
|
def delete(path,headers={})
|
75
|
-
|
76
|
-
end
|
77
|
-
|
78
|
-
def perform(http_method,path,*arguments)
|
79
|
-
request=consumer.create_request(http_method,path,{:oauth_token=>self.token},*arguments)
|
80
|
-
response=request.perform(consumer.secret,self.secret)
|
120
|
+
request(:delete,path,headers)
|
81
121
|
end
|
82
122
|
end
|
83
123
|
end
|
data/lib/oauth/version.rb
CHANGED
data/test/test_consumer.rb
CHANGED
@@ -1,41 +1,49 @@
|
|
1
1
|
require 'test/unit'
|
2
|
-
require 'oauth'
|
2
|
+
require 'oauth/consumer'
|
3
3
|
|
4
4
|
# This performs testing against Andy Smith's test server http://term.ie/oauth/example/
|
5
5
|
# Thanks Andy.
|
6
6
|
# This also means you have to be online to be able to run these.
|
7
7
|
class ConsumerTest < Test::Unit::TestCase
|
8
8
|
def setup
|
9
|
-
@consumer=OAuth::Consumer.new(
|
10
|
-
|
11
|
-
|
12
|
-
:site=>"http://
|
9
|
+
@consumer=OAuth::Consumer.new(
|
10
|
+
'consumer_key_86cad9', '5888bf0345e5d237',
|
11
|
+
{
|
12
|
+
:site=>"http://blabla.bla",
|
13
13
|
:request_token_path=>"/oauth/example/request_token.php",
|
14
14
|
:access_token_path=>"/oauth/example/access_token.php",
|
15
15
|
:authorize_path=>"/oauth/example/authorize.php",
|
16
|
-
:
|
16
|
+
:scheme=>:header,
|
17
17
|
:http_method=>:get
|
18
18
|
})
|
19
|
+
@token = OAuth::ConsumerToken.new(@consumer,'token_411a7f', '3196ffd991c8ebdb')
|
20
|
+
@request_uri = URI.parse('http://example.com/test?key=value')
|
21
|
+
@request_parameters = { 'key' => 'value' }
|
22
|
+
@nonce = 225579211881198842005988698334675835446
|
23
|
+
@timestamp = "1199645624"
|
24
|
+
@consumer.http=Net::HTTP.new(@request_uri.host, @request_uri.port)
|
19
25
|
end
|
20
26
|
|
21
27
|
def test_initializer
|
22
|
-
assert_equal "
|
23
|
-
assert_equal "
|
24
|
-
assert_equal "http://
|
28
|
+
assert_equal "consumer_key_86cad9",@consumer.key
|
29
|
+
assert_equal "5888bf0345e5d237",@consumer.secret
|
30
|
+
assert_equal "http://blabla.bla",@consumer.site
|
25
31
|
assert_equal "/oauth/example/request_token.php",@consumer.request_token_path
|
26
32
|
assert_equal "/oauth/example/access_token.php",@consumer.access_token_path
|
27
|
-
assert_equal "http://
|
28
|
-
assert_equal "http://
|
29
|
-
assert_equal
|
33
|
+
assert_equal "http://blabla.bla/oauth/example/request_token.php",@consumer.request_token_url
|
34
|
+
assert_equal "http://blabla.bla/oauth/example/access_token.php",@consumer.access_token_url
|
35
|
+
assert_equal "http://blabla.bla/oauth/example/authorize.php",@consumer.authorize_url
|
36
|
+
assert_equal :header,@consumer.scheme
|
30
37
|
assert_equal :get,@consumer.http_method
|
31
38
|
end
|
32
39
|
|
33
40
|
def test_defaults
|
34
|
-
@consumer=OAuth::Consumer.new(
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
41
|
+
@consumer=OAuth::Consumer.new(
|
42
|
+
"key",
|
43
|
+
"secret",
|
44
|
+
{
|
45
|
+
:site=>"http://twitter.com"
|
46
|
+
})
|
39
47
|
assert_equal "key",@consumer.key
|
40
48
|
assert_equal "secret",@consumer.secret
|
41
49
|
assert_equal "http://twitter.com",@consumer.site
|
@@ -43,54 +51,126 @@ class ConsumerTest < Test::Unit::TestCase
|
|
43
51
|
assert_equal "/oauth/access_token",@consumer.access_token_path
|
44
52
|
assert_equal "http://twitter.com/oauth/request_token",@consumer.request_token_url
|
45
53
|
assert_equal "http://twitter.com/oauth/access_token",@consumer.access_token_url
|
46
|
-
assert_equal
|
54
|
+
assert_equal "http://twitter.com/oauth/authorize",@consumer.authorize_url
|
55
|
+
assert_equal :header,@consumer.scheme
|
47
56
|
assert_equal :post,@consumer.http_method
|
48
57
|
end
|
49
|
-
|
50
|
-
def
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
58
|
+
|
59
|
+
def test_override_paths
|
60
|
+
@consumer=OAuth::Consumer.new(
|
61
|
+
"key",
|
62
|
+
"secret",
|
63
|
+
{
|
64
|
+
:site=>"http://twitter.com",
|
65
|
+
:request_token_url=>"http://oauth.twitter.com/request_token",
|
66
|
+
:access_token_url=>"http://oauth.twitter.com/access_token",
|
67
|
+
:authorize_url=>"http://site.twitter.com/authorize"
|
68
|
+
})
|
69
|
+
assert_equal "key",@consumer.key
|
70
|
+
assert_equal "secret",@consumer.secret
|
71
|
+
assert_equal "http://twitter.com",@consumer.site
|
72
|
+
assert_equal "/oauth/request_token",@consumer.request_token_path
|
73
|
+
assert_equal "/oauth/access_token",@consumer.access_token_path
|
74
|
+
assert_equal "http://oauth.twitter.com/request_token",@consumer.request_token_url
|
75
|
+
assert_equal "http://oauth.twitter.com/access_token",@consumer.access_token_url
|
76
|
+
assert_equal "http://site.twitter.com/authorize",@consumer.authorize_url
|
77
|
+
assert_equal :header,@consumer.scheme
|
78
|
+
assert_equal :post,@consumer.http_method
|
55
79
|
end
|
56
|
-
|
57
|
-
def
|
58
|
-
request
|
59
|
-
|
60
|
-
|
80
|
+
|
81
|
+
def test_that_signing_auth_headers_on_get_requests_works
|
82
|
+
request = Net::HTTP::Get.new(@request_uri.path + "?" + request_parameters_to_s)
|
83
|
+
@token.sign!(request, {:nonce => @nonce, :timestamp => @timestamp})
|
84
|
+
|
85
|
+
assert_equal 'GET', request.method
|
86
|
+
assert_equal '/test?key=value', request.path
|
87
|
+
assert_equal "OAuth realm=\"\", oauth_nonce=\"225579211881198842005988698334675835446\", oauth_signature_method=\"HMAC-SHA1\", oauth_token=\"token_411a7f\", oauth_timestamp=\"1199645624\", oauth_consumer_key=\"consumer_key_86cad9\", oauth_signature=\"1oO2izFav1GP4kEH2EskwXkCRFg%3D\", oauth_version=\"1.0\"", request['authorization']
|
61
88
|
end
|
62
89
|
|
63
|
-
def
|
64
|
-
request
|
65
|
-
|
66
|
-
|
90
|
+
def test_that_signing_auth_headers_on_post_requests_works
|
91
|
+
request = Net::HTTP::Post.new(@request_uri.path)
|
92
|
+
request.set_form_data( @request_parameters )
|
93
|
+
@token.sign!(request, {:nonce => @nonce, :timestamp => @timestamp})
|
94
|
+
# assert_equal "",request.oauth_helper.signature_base_string
|
95
|
+
|
96
|
+
assert_equal 'POST', request.method
|
97
|
+
assert_equal '/test', request.path
|
98
|
+
assert_equal 'key=value', request.body
|
99
|
+
assert_equal "OAuth realm=\"\", oauth_nonce=\"225579211881198842005988698334675835446\", oauth_signature_method=\"HMAC-SHA1\", oauth_token=\"token_411a7f\", oauth_timestamp=\"1199645624\", oauth_consumer_key=\"consumer_key_86cad9\", oauth_signature=\"26g7wHTtNO6ZWJaLltcueppHYiI%3D\", oauth_version=\"1.0\"", request['authorization']
|
67
100
|
end
|
68
|
-
|
69
|
-
def
|
70
|
-
request
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
101
|
+
|
102
|
+
def test_that_signing_post_params_works
|
103
|
+
request = Net::HTTP::Post.new(@request_uri.path)
|
104
|
+
request.set_form_data( @request_parameters )
|
105
|
+
@token.sign!(request, {:scheme => 'body', :nonce => @nonce, :timestamp => @timestamp})
|
106
|
+
|
107
|
+
assert_equal 'POST', request.method
|
108
|
+
assert_equal '/test', request.path
|
109
|
+
assert_equal "key=value&oauth_consumer_key=consumer_key_86cad9&oauth_nonce=225579211881198842005988698334675835446&oauth_signature=iMZaUTbQof%2fHMFyIde%2bOIkhW5is%3d&oauth_signature_method=HMAC-SHA1&oauth_timestamp=1199645624&oauth_token=token_411a7f&oauth_version=1.0", request.body.split("&").sort.join("&")
|
110
|
+
assert_equal nil, request['authorization']
|
75
111
|
end
|
76
|
-
|
77
|
-
def
|
78
|
-
request=@consumer.
|
79
|
-
|
80
|
-
assert_equal
|
81
|
-
|
82
|
-
|
112
|
+
|
113
|
+
def test_that_using_auth_headers_on_get_on_create_signed_requests_works
|
114
|
+
request=@consumer.create_signed_request(:get,@request_uri.path+ "?" + request_parameters_to_s,@token,{:nonce => @nonce, :timestamp => @timestamp},@request_parameters)
|
115
|
+
|
116
|
+
assert_equal 'GET', request.method
|
117
|
+
assert_equal '/test?key=value', request.path
|
118
|
+
assert_equal "OAuth realm=\"\", oauth_nonce=\"225579211881198842005988698334675835446\", oauth_signature_method=\"HMAC-SHA1\", oauth_token=\"token_411a7f\", oauth_timestamp=\"1199645624\", oauth_consumer_key=\"consumer_key_86cad9\", oauth_signature=\"1oO2izFav1GP4kEH2EskwXkCRFg%3D\", oauth_version=\"1.0\"", request['authorization']
|
119
|
+
end
|
120
|
+
|
121
|
+
def test_that_using_auth_headers_on_post_on_create_signed_requests_works
|
122
|
+
request=@consumer.create_signed_request(:post,@request_uri.path,@token,{:nonce => @nonce, :timestamp => @timestamp},@request_parameters,{})
|
123
|
+
assert_equal 'POST', request.method
|
124
|
+
assert_equal '/test', request.path
|
125
|
+
assert_equal 'key=value', request.body
|
126
|
+
assert_equal "OAuth realm=\"\", oauth_nonce=\"225579211881198842005988698334675835446\", oauth_signature_method=\"HMAC-SHA1\", oauth_token=\"token_411a7f\", oauth_timestamp=\"1199645624\", oauth_consumer_key=\"consumer_key_86cad9\", oauth_signature=\"26g7wHTtNO6ZWJaLltcueppHYiI%3D\", oauth_version=\"1.0\"", request['authorization']
|
127
|
+
end
|
128
|
+
|
129
|
+
def test_that_signing_post_params_works
|
130
|
+
request=@consumer.create_signed_request(:post,@request_uri.path,@token,{:scheme => 'body', :nonce => @nonce, :timestamp => @timestamp},@request_parameters,{})
|
131
|
+
|
132
|
+
assert_equal 'POST', request.method
|
133
|
+
assert_equal '/test', request.path
|
134
|
+
assert_equal "key=value&oauth_consumer_key=consumer_key_86cad9&oauth_nonce=225579211881198842005988698334675835446&oauth_signature=26g7wHTtNO6ZWJaLltcueppHYiI%3d&oauth_signature_method=HMAC-SHA1&oauth_timestamp=1199645624&oauth_token=token_411a7f&oauth_version=1.0", request.body.split("&").sort.join("&")
|
135
|
+
assert_equal nil, request['authorization']
|
83
136
|
end
|
84
137
|
|
85
|
-
def
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
138
|
+
def test_step_by_step_token_request
|
139
|
+
@consumer=OAuth::Consumer.new(
|
140
|
+
"key",
|
141
|
+
"secret",
|
142
|
+
{
|
143
|
+
:site=>"http://term.ie",
|
144
|
+
:request_token_path=>"/oauth/example/request_token.php",
|
145
|
+
:access_token_path=>"/oauth/example/access_token.php",
|
146
|
+
:authorize_path=>"/oauth/example/authorize.php",
|
147
|
+
:scheme=>:header
|
148
|
+
})
|
149
|
+
options={:nonce=>'nonce',:timestamp=>Time.now.to_i.to_s}
|
150
|
+
|
151
|
+
request = Net::HTTP::Get.new("/oauth/example/request_token.php")
|
152
|
+
signature_base_string=@consumer.signature_base_string(request,nil,options)
|
153
|
+
assert_equal "GET&http%3A%2F%2Fterm.ie%2Foauth%2Fexample%2Frequest_token.php&oauth_consumer_key%3Dkey%26oauth_nonce%3D#{options[:nonce]}%26oauth_signature_method%3DHMAC-SHA1%26oauth_timestamp%3D#{options[:timestamp]}%26oauth_token%3D%26oauth_version%3D1.0",signature_base_string
|
154
|
+
@consumer.sign!(request, nil,options)
|
155
|
+
|
156
|
+
assert_equal 'GET', request.method
|
157
|
+
assert_equal nil, request.body
|
158
|
+
response=@consumer.http.request(request)
|
159
|
+
assert_equal "200",response.code
|
160
|
+
assert_equal "oauth_token=requestkey&oauth_token_secret=requestsecret",response.body
|
91
161
|
end
|
92
162
|
|
93
|
-
def test_get_token_sequence
|
163
|
+
def test_get_token_sequence
|
164
|
+
@consumer=OAuth::Consumer.new(
|
165
|
+
"key",
|
166
|
+
"secret",
|
167
|
+
{
|
168
|
+
:site=>"http://term.ie",
|
169
|
+
:request_token_path=>"/oauth/example/request_token.php",
|
170
|
+
:access_token_path=>"/oauth/example/access_token.php",
|
171
|
+
:authorize_path=>"/oauth/example/authorize.php"
|
172
|
+
})
|
173
|
+
|
94
174
|
@request_token=@consumer.get_request_token
|
95
175
|
assert_not_nil @request_token
|
96
176
|
assert_equal "requestkey",@request_token.token
|
@@ -107,10 +187,17 @@ class ConsumerTest < Test::Unit::TestCase
|
|
107
187
|
assert_equal "200",@response.code
|
108
188
|
assert_equal( "ok=hello&test=this",@response.body)
|
109
189
|
|
110
|
-
@response=@access_token.post("/oauth/example/echo_api.php",
|
190
|
+
@response=@access_token.post("/oauth/example/echo_api.php",{'ok'=>'hello','test'=>'this'})
|
111
191
|
assert_not_nil @response
|
112
192
|
assert_equal "200",@response.code
|
113
|
-
assert_equal( "ok=hello&test=this",@response.body)
|
114
|
-
|
193
|
+
assert_equal( "ok=hello&test=this",@response.body)
|
115
194
|
end
|
195
|
+
protected
|
196
|
+
|
197
|
+
def request_parameters_to_s
|
198
|
+
@request_parameters.map { |k,v| "#{k}=#{v}" }.join("&")
|
199
|
+
end
|
200
|
+
|
201
|
+
|
116
202
|
end
|
203
|
+
|