oauth 0.1.1 → 0.2.0
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.
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
|
+
|