oauth_simple 0.1.0.pre
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.
- data/.gemtest +0 -0
- data/README.rdoc +93 -0
- data/lib/oauth_simple.rb +9 -0
- data/lib/oauth_simple/helper_functions.rb +83 -0
- data/lib/oauth_simple/http.rb +267 -0
- data/lib/oauth_simple/request_helper.rb +98 -0
- data/lib/oauth_simple/request_helper_factory.rb +72 -0
- data/lib/oauth_simple/request_param_list.rb +144 -0
- data/rakefile.rb +13 -0
- data/test/helper_path_setting.rb +4 -0
- data/test/test_http.rb +43 -0
- data/test/test_main.rb +151 -0
- metadata +61 -0
data/.gemtest
ADDED
File without changes
|
data/README.rdoc
ADDED
@@ -0,0 +1,93 @@
|
|
1
|
+
= oauth_simple [RubyGem]
|
2
|
+
|
3
|
+
== Example
|
4
|
+
|
5
|
+
Following example shows you how to obtain a request token from Twitter server:
|
6
|
+
|
7
|
+
require "oauth_simple"
|
8
|
+
|
9
|
+
req_uri_str = 'https://api.twitter.com/oauth/request_token'
|
10
|
+
req_method = 'POST'
|
11
|
+
consumer_sec = 'your_consumer_secret'
|
12
|
+
|
13
|
+
req_helper = OAuthSimple::RequestHelper.new(
|
14
|
+
URI.parse( uri_str ),
|
15
|
+
req_method,
|
16
|
+
"#{OAuthSimple::HelperFunctions.enc_perenc(consumer_sec)}&",
|
17
|
+
OAuthSimple::RequestParamList.new( [
|
18
|
+
[ 'oauth_consumer_key', 'your_consumer_key' ],
|
19
|
+
[ 'oauth_signature_method', 'HMAC-SHA1' ],
|
20
|
+
[ 'oauth_timestamp', OAuthSimple::HelperFunctions.create_timestamp_str() ],
|
21
|
+
[ 'oauth_nonce', OAuthSimple::HelperFunctions.create_nonce_str() ],
|
22
|
+
[ 'oauth_version', '1.0' ],
|
23
|
+
] ),
|
24
|
+
)
|
25
|
+
|
26
|
+
require 'net/https'
|
27
|
+
http = Net::HTTP.new( req_helper.host, req_helper.port )
|
28
|
+
http.use_ssl = true # SSLを有効に
|
29
|
+
http.verify_mode = OpenSSL::SSL::VERIFY_PEER # 認証モードをセット
|
30
|
+
http.start do |http|
|
31
|
+
http.request_post( req_helper.qpath, req_helper.req_body,
|
32
|
+
{ 'Authorization' => req_helper.oauth_header_str } ) do |res|
|
33
|
+
if res.code == '200'
|
34
|
+
res.read_body do |str|
|
35
|
+
puts 'str: ', str
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
Alternatively, you can use OAuthSimple::HTTP, which is a subclass of Net::HTTP.
|
42
|
+
Following example shows you how to obtain a temporaty credentials (request token)
|
43
|
+
from Twitter server,
|
44
|
+
how to obtain a token credentials (access token), and how to issue a authenticated request:
|
45
|
+
|
46
|
+
require 'net/https' # if you use ssl
|
47
|
+
require 'oauth_simple'
|
48
|
+
#
|
49
|
+
# OAuthSimple::HTTP is a subclass of Net::HTTP
|
50
|
+
http = OAuthSimple::HTTP.new( 'api.twitter.com', 443 )
|
51
|
+
#
|
52
|
+
# SSL setting
|
53
|
+
http.use_ssl = true
|
54
|
+
http.verify_mode = OpenSSL::SSL::VERIFY_PEER # 認証モードをセット
|
55
|
+
#
|
56
|
+
# OAuth setting (this feature is provided by OAuthSimple::HTTP)
|
57
|
+
http.use_oauth = true
|
58
|
+
http.set_oauth_client_credentials( 'YOUR_CLIENT_CREDENTIALS', 'YOUR_CLIENT_SECRET' )
|
59
|
+
http.set_oauth_signature_method( 'HMAC-SHA1' ) # at this time, only 'HMAC-SHA1' is supported
|
60
|
+
#
|
61
|
+
# connection start
|
62
|
+
http.start() do |http|
|
63
|
+
# == Obtaining Temporary Credentials ==
|
64
|
+
token, secret = http.request_oauth_temp_credentials( '/oauth/request_token', 'oob' ) do |res_failed|
|
65
|
+
# when response code is not '200', this block is called
|
66
|
+
raise res_failed.body
|
67
|
+
end
|
68
|
+
# token and secret are set to OAuthSimple::HTTP object automatically in the request_oauth_temp_credentials method,
|
69
|
+
# so you need not set them explicitly as follows
|
70
|
+
# http.set_oauth_user_credentials( token, secret )
|
71
|
+
#
|
72
|
+
# == Resource Owner Authorization ==
|
73
|
+
puts "access to https://api.twitter.com/oauth/authorize?oauth_token=#{OAuthSimple::HelperFunctions.enc_perenc(token)} " +
|
74
|
+
'and input verifier'
|
75
|
+
$stdout << 'verifier : '
|
76
|
+
verifier = $stdin.gets.chomp
|
77
|
+
#
|
78
|
+
# == Obtaining Token Credentials ==
|
79
|
+
token, secret = http.request_oauth_token_credentials( '/oauth/access_token', verifier ) do |res_failed|
|
80
|
+
# when response code is not '200', this block is called
|
81
|
+
raise res_failed.body
|
82
|
+
end
|
83
|
+
# token and secret are set to OAuthSimple::HTTP object automatically in the request_oauth_token_credentials method,
|
84
|
+
# you need not set them explicitly as follows
|
85
|
+
# http.set_oauth_user_credentials( token, secret )
|
86
|
+
#
|
87
|
+
# == Authenticated Requests ==
|
88
|
+
http.set_oauth_user_credentials( token, secret )
|
89
|
+
http.request_get( '/1/statuses/home_timeline.json?include_entities=true' ) do |res|
|
90
|
+
p res.code
|
91
|
+
p res.body
|
92
|
+
end
|
93
|
+
end
|
data/lib/oauth_simple.rb
ADDED
@@ -0,0 +1,83 @@
|
|
1
|
+
# coding : utf-8
|
2
|
+
|
3
|
+
require 'openssl'
|
4
|
+
|
5
|
+
module OAuthSimple
|
6
|
+
module HelperFunctions
|
7
|
+
|
8
|
+
# ====================
|
9
|
+
# MODULE FUNCTIONS
|
10
|
+
# ====================
|
11
|
+
module_function
|
12
|
+
|
13
|
+
# nonce 用にランダムに文字列生成するメソッド
|
14
|
+
NONCE_STRING_SOURCE = ('a'..'z').to_a() + ('A'..'Z').to_a() + ('0'..'9').to_a()
|
15
|
+
def create_nonce_str( length = 16 )
|
16
|
+
Array.new( length ).map{ NONCE_STRING_SOURCE[rand(NONCE_STRING_SOURCE.size)] }.join('')
|
17
|
+
end
|
18
|
+
|
19
|
+
def create_timestamp_str( time = Time.now )
|
20
|
+
( time - Time.utc( 1970, 1, 1 ) ).to_i().to_s()
|
21
|
+
end
|
22
|
+
|
23
|
+
# HMAC-SHA1
|
24
|
+
# RSA-SHA1
|
25
|
+
def calc_signature( method, uri_str, param_list, secret_str )
|
26
|
+
params_str = param_list.get_normalized_params_str()
|
27
|
+
#sb_str = String.new()
|
28
|
+
#list.each do |item|
|
29
|
+
# if ( sb_str != "" ) then
|
30
|
+
# sb_str << "&"
|
31
|
+
# end
|
32
|
+
# sb_str << encode( item[0] ) << "=" << encode( item[1] )
|
33
|
+
#end
|
34
|
+
base_str = [ method, uri_str, params_str ].map{ |e| enc_perenc(e) }.join('&')
|
35
|
+
digest = OpenSSL::HMAC::digest( OpenSSL::Digest::SHA1.new(), secret_str, base_str )
|
36
|
+
return [digest].pack('m').gsub!( /\n/u, '' )
|
37
|
+
end
|
38
|
+
|
39
|
+
# param : String
|
40
|
+
# return : [ [ String, String or nil ], ... ]
|
41
|
+
def decode_from_percent_encoded_str( str )
|
42
|
+
str.split( '&', -1 ).map! do |s|
|
43
|
+
if s.empty?
|
44
|
+
[ '', nil ]
|
45
|
+
else
|
46
|
+
pair = s.split( '=', -1 ).map!{ |s| dec_perenc( s ) }
|
47
|
+
# TODO: pair の要素数は 1 以上 2 以下 ('=' がない場合など, 1 個だけの場合もある)
|
48
|
+
[ pair[0], pair[1] ]
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
# param : [ [ String, String or nil ], ... ]
|
54
|
+
# return : String
|
55
|
+
def encode_to_percent_encoded_str_pairs( str_pairs )
|
56
|
+
str_pairs.map do |pair|
|
57
|
+
pair[1].nil? ? enc_perenc( pair[0] )
|
58
|
+
: enc_perenc( pair[0] ) + '=' + enc_perenc( pair[1] )
|
59
|
+
end.join( '&' )
|
60
|
+
end
|
61
|
+
|
62
|
+
# TODO これで良いか?
|
63
|
+
# UTF-8 エンコードされたものをパーセントエンコードしているとみなしてデコードする
|
64
|
+
# パーセントエンコードする際には文字列を UTF-8 エンコードするのは OAuth 1.0 の仕様
|
65
|
+
# だが, デコード時はこれでよいか?
|
66
|
+
def dec_perenc( str )
|
67
|
+
str.gsub( /%[a-fA-F\d]{2}/u ){ |s| [s[1,2]].pack('H*') }.force_encoding( Encoding::UTF_8 )
|
68
|
+
end
|
69
|
+
|
70
|
+
def enc_perenc( str )
|
71
|
+
str.gsub( /[^a-zA-Z\d\-\._\~]/u ) do |s|
|
72
|
+
d_str = s.unpack("H*")[0].upcase()
|
73
|
+
e_str = String.new()
|
74
|
+
while ( d_str[0,2] != "" ) do
|
75
|
+
e_str << "%" << d_str[0,2]
|
76
|
+
d_str[0,2] = ""
|
77
|
+
end
|
78
|
+
e_str
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
end
|
83
|
+
end
|
@@ -0,0 +1,267 @@
|
|
1
|
+
# coding : utf-8
|
2
|
+
|
3
|
+
require 'net/http'
|
4
|
+
require 'oauth_simple/helper_functions'
|
5
|
+
require 'oauth_simple/request_param_list'
|
6
|
+
|
7
|
+
module OAuthSimple
|
8
|
+
|
9
|
+
###
|
10
|
+
# Subclass of Net::HTTP, which has feature of OAuth authentication
|
11
|
+
class HTTP < Net::HTTP
|
12
|
+
|
13
|
+
include HelperFunctions
|
14
|
+
|
15
|
+
module DefaultOAuthParamSettable
|
16
|
+
def set_default_oauth_client_credentials( key, secret )
|
17
|
+
@client_credentials = [ key, secret ]
|
18
|
+
end
|
19
|
+
|
20
|
+
def set_default_oauth_user_credentials( key, secret )
|
21
|
+
@user_credentials = [ key, secret ]
|
22
|
+
end
|
23
|
+
|
24
|
+
def set_default_oauth_signature_method( sig_met )
|
25
|
+
@signature_method = sig_met
|
26
|
+
end
|
27
|
+
|
28
|
+
def get_default_params
|
29
|
+
params = {}
|
30
|
+
params[:oauth_client_credentials] = @client_credentials if @client_credentials
|
31
|
+
params[:oauth_user_credentials ] = @user_credentials if @user_credentials
|
32
|
+
params[:signature_method ] = @signature_method if @signature_method
|
33
|
+
return params
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
# :stopdoc:
|
38
|
+
# 空のハッシュを表す定数
|
39
|
+
EMPTY_HASH = {}.freeze
|
40
|
+
# :startdoc:
|
41
|
+
|
42
|
+
def initialize( *args )
|
43
|
+
super
|
44
|
+
self.set_oauth_params_location( LOC_AUTHORIZATION_HEADER )
|
45
|
+
end
|
46
|
+
|
47
|
+
def self.create_subclass_with_default_oauth_params( oauth_params = EMPTY_HASH )
|
48
|
+
klass = Class.new( self ) do
|
49
|
+
def initialize( *args )
|
50
|
+
super
|
51
|
+
default_params = self.class.get_default_params
|
52
|
+
self.use_oauth = true
|
53
|
+
if default_params.has_key? :oauth_client_credentials
|
54
|
+
self.set_oauth_client_credentials( *default_params[:oauth_client_credentials] )
|
55
|
+
end
|
56
|
+
if default_params.has_key? :oauth_user_credentials
|
57
|
+
self.set_oauth_user_credentials( *default_params[:oauth_user_credentials] )
|
58
|
+
end
|
59
|
+
if default_params.has_key? :signature_method
|
60
|
+
# at this time, only 'HMAC-SHA1' is supported
|
61
|
+
self.set_oauth_signature_method( default_params[:signature_method] )
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
klass.extend DefaultOAuthParamSettable
|
66
|
+
# TODO oauth_params で渡されたパラメータをここでセット
|
67
|
+
#
|
68
|
+
return klass
|
69
|
+
end
|
70
|
+
|
71
|
+
# @consumer_key
|
72
|
+
# @token
|
73
|
+
# @signature_method
|
74
|
+
# (timestamp, nonce, version)
|
75
|
+
# -> signature
|
76
|
+
#
|
77
|
+
# @consumer_secret
|
78
|
+
# @token_secret
|
79
|
+
|
80
|
+
###
|
81
|
+
# Override: Net::HTTP#transport_request
|
82
|
+
def transport_request( req )
|
83
|
+
if use_oauth?
|
84
|
+
req_method = req.method.upcase
|
85
|
+
uri_str_scheme = use_ssl? ? 'https' : 'http'
|
86
|
+
uri_str_host = addr_port.downcase # デフォルトでない場合ポート番号含む
|
87
|
+
# TODO: path 中の '#' はどのように扱われるべき?
|
88
|
+
qpath, uri_str_fragment = req.path.split( '#', 2 )
|
89
|
+
uri_str_path, query_str = qpath.split( '?', 2 )
|
90
|
+
# OAuth Header (基本的には自分で用意)
|
91
|
+
#req.get_fields( 'Authorization' )
|
92
|
+
# ...
|
93
|
+
# body parameters (必要な場合だけ)
|
94
|
+
# Protocol parameters can be transmitted in the HTTP request entity-
|
95
|
+
# body, but only if the following REQUIRED conditions are met:
|
96
|
+
# o The entity-body is single-part.
|
97
|
+
# o The entity-body follows the encoding requirements of the
|
98
|
+
# "application/x-www-form-urlencoded" content-type as defined by
|
99
|
+
# [W3C.REC-html40-19980424].
|
100
|
+
# o The HTTP request entity-header includes the "Content-Type" header
|
101
|
+
# field set to "application/x-www-form-urlencoded".
|
102
|
+
body_str = nil
|
103
|
+
if req.request_body_permitted?
|
104
|
+
content_type = req.content_type || 'application/x-www-form-urlencoded'
|
105
|
+
if content_type == 'application/x-www-form-urlencoded'
|
106
|
+
body_str = req.body
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
secret_str = [ @oauth_consumer_secret, @oauth_token_secret ].
|
111
|
+
map {|e| e.nil? ? '' : enc_perenc( e ) }.
|
112
|
+
join( '&' )
|
113
|
+
|
114
|
+
# for debug
|
115
|
+
#puts "request method - #{req_method }"
|
116
|
+
#puts "http or https - #{uri_str_scheme}"
|
117
|
+
#puts "host[:port] - #{uri_str_host }"
|
118
|
+
#puts "path - #{uri_str_path }"
|
119
|
+
#puts "query str - #{query_str.nil? ? '<nil>' : query_str}"
|
120
|
+
#puts "body str - #{body_str.nil? ? '<nil>' : body_str }"
|
121
|
+
|
122
|
+
p_params = RequestParamList.new()
|
123
|
+
{
|
124
|
+
'oauth_consumer_key' => @oauth_consumer_key,
|
125
|
+
'oauth_token' => @oauth_token,
|
126
|
+
'oauth_signature_method' => @oauth_signature_method,
|
127
|
+
}.each_pair{|k,v| p_params.add( k, v ) if v }
|
128
|
+
p_params.add( 'oauth_timestamp' , create_timestamp_str() )
|
129
|
+
p_params.add( 'oauth_nonce' , create_nonce_str() )
|
130
|
+
p_params.add( 'oauth_version' , '1.0' )
|
131
|
+
if req.respond_to? :oauth_params
|
132
|
+
req.oauth_params.each_pair do |key,value|
|
133
|
+
p_params.add( key, value )
|
134
|
+
end
|
135
|
+
end
|
136
|
+
|
137
|
+
param_list = RequestParamList.new()
|
138
|
+
param_list.concat p_params
|
139
|
+
param_list.concat RequestParamList.from_percent_encoded_str query_str if query_str
|
140
|
+
param_list.concat RequestParamList.from_percent_encoded_str body_str if body_str
|
141
|
+
|
142
|
+
# signature の計算
|
143
|
+
uri_str = "#{uri_str_scheme}://#{uri_str_host}#{uri_str_path}"
|
144
|
+
signature = calc_signature( req_method, uri_str, param_list, secret_str )
|
145
|
+
|
146
|
+
case @oauth_params_loc
|
147
|
+
when LOC_AUTHORIZATION_HEADER
|
148
|
+
# Authorization Header
|
149
|
+
p_params.add( 'oauth_signature', signature )
|
150
|
+
req.add_field( 'Authorization', 'OAuth ' + p_params.to_header_string() )
|
151
|
+
when LOC_REQBODY_OR_REQQUERY
|
152
|
+
# req body or req query
|
153
|
+
raise 'not implemented yet'
|
154
|
+
when LOC_REQQUERY
|
155
|
+
# req query
|
156
|
+
raise 'not implemented yet'
|
157
|
+
else
|
158
|
+
# error
|
159
|
+
raise 'invalid location'
|
160
|
+
end
|
161
|
+
end
|
162
|
+
return super # 引数, block をそのまま継承先へ渡す
|
163
|
+
end
|
164
|
+
|
165
|
+
def use_oauth=( val )
|
166
|
+
@use_oauth = val
|
167
|
+
end
|
168
|
+
|
169
|
+
def use_oauth?
|
170
|
+
@use_oauth
|
171
|
+
end
|
172
|
+
|
173
|
+
def set_oauth_client_credentials( key, secret )
|
174
|
+
@oauth_consumer_key = key
|
175
|
+
@oauth_consumer_secret = secret
|
176
|
+
end
|
177
|
+
|
178
|
+
def set_oauth_user_credentials( token, secret )
|
179
|
+
@oauth_token = token
|
180
|
+
@oauth_token_secret = secret
|
181
|
+
end
|
182
|
+
|
183
|
+
def set_oauth_signature_method( sigmet )
|
184
|
+
if sigmet != 'HMAC-SHA1'
|
185
|
+
raise %q{at this time, only 'HMAC-SHA1' is supported}
|
186
|
+
end
|
187
|
+
@oauth_signature_method = sigmet
|
188
|
+
end
|
189
|
+
|
190
|
+
LOC_AUTHORIZATION_HEADER = :auth_header
|
191
|
+
LOC_REQBODY_OR_REQQUERY = :reqbody_or_reqquery
|
192
|
+
LOC_REQQUERY = :reqquery
|
193
|
+
def set_oauth_params_location( location )
|
194
|
+
@oauth_params_loc = location
|
195
|
+
end
|
196
|
+
|
197
|
+
# TODO: POST メソッド以外も使えるように
|
198
|
+
def request_oauth_temp_credentials( path, oauth_callback_uri, &block )
|
199
|
+
req = Post.new( path )
|
200
|
+
req.set_oauth_param( 'oauth_callback', oauth_callback_uri )
|
201
|
+
token = nil
|
202
|
+
secret = nil
|
203
|
+
request( req ) do |res|
|
204
|
+
if res.code == '200'
|
205
|
+
params = RequestParamList.from_percent_encoded_str res.body
|
206
|
+
token = params.get_values( 'oauth_token' )[0]
|
207
|
+
secret = params.get_values( 'oauth_token_secret' )[0]
|
208
|
+
else
|
209
|
+
if block
|
210
|
+
block.call res
|
211
|
+
else
|
212
|
+
raise 'error' # TODO
|
213
|
+
end
|
214
|
+
end
|
215
|
+
end
|
216
|
+
|
217
|
+
# Set credentials automatically
|
218
|
+
set_oauth_user_credentials( token, secret )
|
219
|
+
return token, secret
|
220
|
+
end
|
221
|
+
|
222
|
+
# TODO: POST メソッド以外も使えるように
|
223
|
+
def request_oauth_token_credentials( path, oauth_verifier, &block )
|
224
|
+
req = Post.new( path )
|
225
|
+
req.set_oauth_param( 'oauth_verifier', oauth_verifier )
|
226
|
+
token = nil
|
227
|
+
secret = nil
|
228
|
+
request( req ) do |res|
|
229
|
+
if res.code == '200'
|
230
|
+
params = RequestParamList.from_percent_encoded_str res.body
|
231
|
+
token = params.get_values( 'oauth_token' )[0]
|
232
|
+
secret = params.get_values( 'oauth_token_secret' )[0]
|
233
|
+
else
|
234
|
+
if block
|
235
|
+
block.call res
|
236
|
+
else
|
237
|
+
raise 'error'
|
238
|
+
end
|
239
|
+
end
|
240
|
+
end
|
241
|
+
set_oauth_user_credentials( token, secret )
|
242
|
+
return token, secret
|
243
|
+
end
|
244
|
+
|
245
|
+
module OAuthParamsHandler
|
246
|
+
def set_oauth_param( name, value )
|
247
|
+
# TODO: name must start with 'oauth_'
|
248
|
+
@oauth_params ||= {}
|
249
|
+
@oauth_params[ name ] = value
|
250
|
+
end
|
251
|
+
def get_oauth_param( name )
|
252
|
+
( @oauth_params || {} )[ name ]
|
253
|
+
end
|
254
|
+
def oauth_params
|
255
|
+
@oauth_params || {}
|
256
|
+
end
|
257
|
+
end
|
258
|
+
|
259
|
+
class Get < Net::HTTP::Get
|
260
|
+
include OAuthParamsHandler
|
261
|
+
end
|
262
|
+
class Post < Net::HTTP::Post
|
263
|
+
include OAuthParamsHandler
|
264
|
+
end
|
265
|
+
|
266
|
+
end
|
267
|
+
end
|
@@ -0,0 +1,98 @@
|
|
1
|
+
# coding : utf-8
|
2
|
+
|
3
|
+
require 'oauth_simple/helper_functions'
|
4
|
+
|
5
|
+
module OAuthSimple
|
6
|
+
class RequestHelper
|
7
|
+
|
8
|
+
include HelperFunctions
|
9
|
+
|
10
|
+
###
|
11
|
+
# req_uri : URI or String object
|
12
|
+
# req_method : String
|
13
|
+
def initialize( req_uri, req_method, oauth_secret, protocol_params, query_params = nil, body_params = nil )
|
14
|
+
# URI
|
15
|
+
@req_uri = req_uri # 後ろの処理で query は nil になる
|
16
|
+
# String or Symbol?
|
17
|
+
@req_method = req_method
|
18
|
+
# String or Symbol?
|
19
|
+
@sig_method = nil
|
20
|
+
# String
|
21
|
+
@secret_str = oauth_secret
|
22
|
+
# RequestParamList
|
23
|
+
@p_params = protocol_params
|
24
|
+
# RequestParamList or nil
|
25
|
+
q_params_list = []
|
26
|
+
if @req_uri.query
|
27
|
+
q_params_list << RequestParamList.from_percent_encoded_str( @req_uri.query )
|
28
|
+
@req_uri.query = nil
|
29
|
+
end
|
30
|
+
if query_params
|
31
|
+
q_params_list << query_params
|
32
|
+
end
|
33
|
+
@q_params = q_params_list.empty? ? nil : q_params_list.inject{|a,b| a.concat b}
|
34
|
+
# RequestParamList or nil
|
35
|
+
@b_params = body_params
|
36
|
+
|
37
|
+
params = RequestParamList.new()
|
38
|
+
params.concat @p_params
|
39
|
+
params.concat @q_params if @q_params
|
40
|
+
params.concat @b_params if @b_params
|
41
|
+
|
42
|
+
# URI の処理
|
43
|
+
# The scheme, authority, and path of the request resource URI [RFC3986]
|
44
|
+
# are included by constructing an "http" or "https" URI representing
|
45
|
+
# the request resource (without the query or fragment) as follows:
|
46
|
+
# 1. The scheme and host MUST be in lowercase.
|
47
|
+
uri_str = ''
|
48
|
+
# scheme
|
49
|
+
uri_str << @req_uri.scheme.downcase
|
50
|
+
uri_str << '://'
|
51
|
+
uri_str << @req_uri.host.downcase
|
52
|
+
# 3. The port MUST be included if it is not the default port for the
|
53
|
+
# scheme, and MUST be excluded if it is the default. Specifically,
|
54
|
+
# the port MUST be excluded when making an HTTP request [RFC2616]
|
55
|
+
# to port 80 or when making an HTTPS request [RFC2818] to port 443.
|
56
|
+
# All other non-default port numbers MUST be included.
|
57
|
+
if @req_uri.port != @req_uri.default_port
|
58
|
+
uri_str << ":#{@req_uri.port}"
|
59
|
+
end
|
60
|
+
uri_str << @req_uri.path
|
61
|
+
|
62
|
+
@p_params.add( 'oauth_signature', calc_signature( req_method, uri_str, params, @secret_str ) )
|
63
|
+
end
|
64
|
+
|
65
|
+
def host
|
66
|
+
@req_uri.host
|
67
|
+
end
|
68
|
+
|
69
|
+
def port
|
70
|
+
@req_uri.port
|
71
|
+
end
|
72
|
+
|
73
|
+
def request_method
|
74
|
+
@req_method
|
75
|
+
end
|
76
|
+
|
77
|
+
###
|
78
|
+
# path + '?' + query
|
79
|
+
def qpath
|
80
|
+
@req_uri.path
|
81
|
+
end
|
82
|
+
|
83
|
+
def qpath_with_oauth_params
|
84
|
+
|
85
|
+
end
|
86
|
+
|
87
|
+
def req_body
|
88
|
+
end
|
89
|
+
|
90
|
+
def req_body_with_oauth_params
|
91
|
+
end
|
92
|
+
|
93
|
+
def oauth_header_str( realm_str = nil )
|
94
|
+
'OAuth ' + @p_params.to_header_string()
|
95
|
+
end
|
96
|
+
|
97
|
+
end
|
98
|
+
end
|
@@ -0,0 +1,72 @@
|
|
1
|
+
# coding : utf-8
|
2
|
+
|
3
|
+
require 'oauth_simple/helper_functions'
|
4
|
+
|
5
|
+
module OAuthSimple
|
6
|
+
class RequestHelperFactory
|
7
|
+
|
8
|
+
include HelperFunctions
|
9
|
+
|
10
|
+
###
|
11
|
+
# consumer_secret
|
12
|
+
# token_secret
|
13
|
+
# consumer_key
|
14
|
+
# token
|
15
|
+
# clients MAY omit the parameter.
|
16
|
+
# signature_method
|
17
|
+
# timestamp
|
18
|
+
# MAY be omitted when using the "PLAINTEXT" signature method.
|
19
|
+
# nonce
|
20
|
+
# MAY be omitted when using the "PLAINTEXT" signature method.
|
21
|
+
# version
|
22
|
+
# OPTIONAL. If present, MUST be set to "1.0".
|
23
|
+
# :consumer_key, :consumer_secret, :token, :token_secret, :signature_method
|
24
|
+
# :use_default_timestamp, :use_default_nonce, :use_default_version
|
25
|
+
def initialize( args )
|
26
|
+
args = {
|
27
|
+
:use_default_timestamp => true,
|
28
|
+
:use_default_nonce => true,
|
29
|
+
:use_default_version => true,
|
30
|
+
}.merge args
|
31
|
+
# String object or nil
|
32
|
+
@consumer_key = args.delete( :consumer_key )
|
33
|
+
@consumer_secret = args.delete( :consumer_secret )
|
34
|
+
@token = args.delete( :token )
|
35
|
+
@token_secret = args.delete( :token_secret )
|
36
|
+
@signature_method = args.delete( :signature_method )
|
37
|
+
# boolean
|
38
|
+
@use_default_timestamp = args.delete( :use_default_timestamp )
|
39
|
+
@use_default_nonce = args.delete( :use_default_nonce )
|
40
|
+
@use_default_version = args.delete( :use_default_version )
|
41
|
+
# TODO: args に key が残っている場合, 警告を表示
|
42
|
+
end
|
43
|
+
|
44
|
+
###
|
45
|
+
# create RequestHelper object
|
46
|
+
def create( req_uri, req_method, option_params )
|
47
|
+
# secret_str 生成
|
48
|
+
cons_sec = option_params[:consumer_secret] || @consumer_secret
|
49
|
+
tokn_sec = option_params[:token_secret ] || @token_secret
|
50
|
+
secret_str = "#{cons_sec}&#{tokn_sec}"
|
51
|
+
|
52
|
+
# protocol params
|
53
|
+
p_params = RequestParamList.new()
|
54
|
+
p_params.add( 'oauth_consumer_key' , @consumer_key ) if @consumer_key
|
55
|
+
p_params.add( 'oauth_token' , @token ) if @token
|
56
|
+
p_params.add( 'oauth_signature_method', @signature_method ) if @signature_method
|
57
|
+
p_params.add( 'oauth_timestamp' , create_timestamp_str() ) if @use_default_timestamp
|
58
|
+
p_params.add( 'oauth_nonce' , create_nonce_str() ) if @use_default_nonce
|
59
|
+
p_params.add( 'oauth_version' , '1.0' ) if @use_default_version
|
60
|
+
p_params2 = option_params.delete( :protocol_params )
|
61
|
+
p_params.concat p_params2 if p_params2
|
62
|
+
|
63
|
+
# query_params and body_params
|
64
|
+
q_params = option_params.delete( :query_params )
|
65
|
+
b_params = option_params.delete( :body_params )
|
66
|
+
|
67
|
+
# RequestHelper object 生成
|
68
|
+
RequestHelper.new( req_uri, req_method, secret_str, p_params, q_params, b_params )
|
69
|
+
end
|
70
|
+
|
71
|
+
end
|
72
|
+
end
|
@@ -0,0 +1,144 @@
|
|
1
|
+
# coding : utf-8
|
2
|
+
|
3
|
+
require 'oauth_simple/helper_functions'
|
4
|
+
|
5
|
+
module OAuthSimple
|
6
|
+
class RequestParamList
|
7
|
+
|
8
|
+
include HelperFunctions
|
9
|
+
|
10
|
+
# instance variable
|
11
|
+
# @list : [ [ String obj, String obj or nil ], ... ]
|
12
|
+
|
13
|
+
def initialize( arg = Array.new() )
|
14
|
+
if ( arg.is_a? Array ) then
|
15
|
+
arg.each do |item|
|
16
|
+
if not item.is_a?( Array ) or item.length != 2 or not item[0].is_a?( String ) or not ( item[1].is_a?( String ) or item[1].nil? ) then
|
17
|
+
raise "引数として与えられた Array が正しい形式ではありません. " +
|
18
|
+
'引数として与えられた Array オブジェクトの各要素は, String オブジェクト ' +
|
19
|
+
'2 つ (または 2 つめは nil) からなる Array オブジェクトである必要があります'
|
20
|
+
end
|
21
|
+
end
|
22
|
+
@list = arg
|
23
|
+
elsif ( arg.is_a? Hash ) then
|
24
|
+
@list = Array.new()
|
25
|
+
arg.each do |key,val|
|
26
|
+
@list.push( [key, val] )
|
27
|
+
end
|
28
|
+
elsif ( arg.is_a? String ) then
|
29
|
+
@list = Array.new()
|
30
|
+
if ( /%(?![a-fA-F\d]{2})/u =~ arg ) then
|
31
|
+
# OAuth の仕様どおりではないが, URL エンコードの形式ならば受け付ける
|
32
|
+
raise "引数として与えられた String オブジェクトが正しく encode されたものではありません"
|
33
|
+
end
|
34
|
+
param_list = arg.split( /&/u )
|
35
|
+
param_list.each do |item|
|
36
|
+
if ( item.nil? || item == "" ) then
|
37
|
+
next
|
38
|
+
end
|
39
|
+
pair = item.split( /=/u )
|
40
|
+
@list.push( [decode( pair[0] ), decode( pair[1].to_s() )] )
|
41
|
+
end
|
42
|
+
else
|
43
|
+
raise "型エラー : ParameterList の初期化時に与えることができる引数の型は Array と String のみです"
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
def self.from_percent_encoded_str( str )
|
48
|
+
# HelperFunctions モジュールで定義されている... 関数呼び出しにはできない?
|
49
|
+
new HelperFunctions.decode_from_percent_encoded_str( str )
|
50
|
+
end
|
51
|
+
|
52
|
+
public
|
53
|
+
def +( other )
|
54
|
+
return ParameterList.new( self.get_list() + other.get_list() )
|
55
|
+
end
|
56
|
+
|
57
|
+
def concat( other )
|
58
|
+
@list.concat( other.get_list() )
|
59
|
+
return self
|
60
|
+
end
|
61
|
+
|
62
|
+
def add( name, value )
|
63
|
+
@list.push( [name, value] )
|
64
|
+
return nil
|
65
|
+
end
|
66
|
+
|
67
|
+
def get_values( name )
|
68
|
+
res_list = Array.new()
|
69
|
+
@list.each do |item|
|
70
|
+
if ( item[0] == name ) then
|
71
|
+
res_list.push( item[1] )
|
72
|
+
end
|
73
|
+
end
|
74
|
+
return res_list
|
75
|
+
end
|
76
|
+
|
77
|
+
alias :[] :get_values
|
78
|
+
|
79
|
+
def each()
|
80
|
+
@list.each do |item|
|
81
|
+
yield( item[0], item[1] )
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
def to_header_string()
|
86
|
+
#list = get_sorted_list()
|
87
|
+
sb_str = String.new()
|
88
|
+
@list.each do |item|
|
89
|
+
if ( sb_str != "" ) then
|
90
|
+
sb_str << ", "
|
91
|
+
end
|
92
|
+
sb_str << enc_perenc( item[0] ) << '="' << enc_perenc( item[1] ) << '"'
|
93
|
+
end
|
94
|
+
return sb_str
|
95
|
+
end
|
96
|
+
|
97
|
+
def to_query_string()
|
98
|
+
#list = get_sorted_list()
|
99
|
+
sb_str = String.new()
|
100
|
+
@list.map{ |e| enc_perenc( e[0] ) + ( e[1] ? "=#{enc_perenc( e[1] )}" : '' ) }.join( '&' )
|
101
|
+
end
|
102
|
+
|
103
|
+
=begin
|
104
|
+
def to_signature_string( method, url, key )
|
105
|
+
list = get_sorted_list()
|
106
|
+
sb_str = String.new()
|
107
|
+
list.each do |item|
|
108
|
+
if ( sb_str != "" ) then
|
109
|
+
sb_str << "&"
|
110
|
+
end
|
111
|
+
sb_str << encode( item[0] ) << "=" << encode( item[1] )
|
112
|
+
end
|
113
|
+
base_string = encode( method ) + "&" + encode( url ) + "&" + encode( sb_str )
|
114
|
+
digest = OpenSSL::HMAC::digest( OpenSSL::Digest::SHA1.new(), key, base_string )
|
115
|
+
sig = [digest].pack("m").gsub!( /\n/u, "" )
|
116
|
+
return sig
|
117
|
+
end
|
118
|
+
=end
|
119
|
+
|
120
|
+
protected
|
121
|
+
def get_list()
|
122
|
+
return @list
|
123
|
+
end
|
124
|
+
|
125
|
+
public
|
126
|
+
# http://tools.ietf.org/html/rfc5849#section-3.4.1.3.2
|
127
|
+
def get_normalized_params_str()
|
128
|
+
@list.
|
129
|
+
map do |e| # [ key, val ]
|
130
|
+
[ enc_perenc( e[0] ), e[1] ? enc_perenc( e[1] ) : '' ]
|
131
|
+
end.
|
132
|
+
sort do |a,b|
|
133
|
+
case a[0] <=> b[0]
|
134
|
+
when 1 then rel = 1
|
135
|
+
when -1 then rel = -1
|
136
|
+
when 0 then rel = a[1] <=> b[1]
|
137
|
+
end
|
138
|
+
end.
|
139
|
+
map{ |e| "#{e[0]}=#{e[1]}" }.
|
140
|
+
join( '&' )
|
141
|
+
end
|
142
|
+
|
143
|
+
end
|
144
|
+
end
|
data/rakefile.rb
ADDED
@@ -0,0 +1,13 @@
|
|
1
|
+
# coding: UTF-8
|
2
|
+
|
3
|
+
require 'rake/testtask'
|
4
|
+
|
5
|
+
task :default => [:test]
|
6
|
+
|
7
|
+
Rake::TestTask.new do |test|
|
8
|
+
# $LOAD_PATH に追加するパス (デフォルトで 'lib' は入っている)
|
9
|
+
test.libs << 'test'
|
10
|
+
# テスト対象ファイルの指定
|
11
|
+
test.test_files = Dir[ 'test/**/test_*.rb' ]
|
12
|
+
test.verbose = true
|
13
|
+
end
|
data/test/test_http.rb
ADDED
@@ -0,0 +1,43 @@
|
|
1
|
+
# coding: UTF-8
|
2
|
+
|
3
|
+
require File.expand_path File.join( File.dirname(__FILE__), 'helper_path_setting' )
|
4
|
+
|
5
|
+
require 'uri'
|
6
|
+
require 'minitest/unit'
|
7
|
+
require 'minitest/autorun'
|
8
|
+
|
9
|
+
require 'oauth_simple'
|
10
|
+
require 'oauth_simple/http'
|
11
|
+
|
12
|
+
class TestHttp < MiniTest::Unit::TestCase
|
13
|
+
|
14
|
+
# OAuthSimple::HTTP is a subclass of Net::HTTP
|
15
|
+
MyHTTP = OAuthSimple::HTTP.create_subclass_with_default_oauth_params()
|
16
|
+
MyHTTP.set_default_oauth_client_credentials( 'key', 'secret' )
|
17
|
+
#MyHTTP.set_default_oauth_user_credentials( key, secret )
|
18
|
+
MyHTTP.set_default_oauth_signature_method( 'HMAC-SHA1' )
|
19
|
+
|
20
|
+
###
|
21
|
+
# test by using OAuth Test Server : http://term.ie/oauth/example/
|
22
|
+
def test_getting_request_token
|
23
|
+
|
24
|
+
http = MyHTTP.new( 'term.ie' )
|
25
|
+
# connection start
|
26
|
+
http.start() do |http|
|
27
|
+
assert_equal( http.class, MyHTTP )
|
28
|
+
http.request_post( '/oauth/example/request_token.php', nil ) do |res|
|
29
|
+
assert_equal( '200', res.code )
|
30
|
+
assert_equal( 'oauth_token=requestkey&oauth_token_secret=requestsecret', res.body )
|
31
|
+
end
|
32
|
+
|
33
|
+
token, secret = http.request_oauth_temp_credentials( '/oauth/example/request_token.php', 'oob' )
|
34
|
+
assert_equal( 'requestkey' , token )
|
35
|
+
assert_equal( 'requestsecret', secret )
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
end
|
40
|
+
|
41
|
+
__END__
|
42
|
+
|
43
|
+
assert( .... )
|
data/test/test_main.rb
ADDED
@@ -0,0 +1,151 @@
|
|
1
|
+
# coding: UTF-8
|
2
|
+
|
3
|
+
require File.expand_path File.join( File.dirname(__FILE__), 'helper_path_setting' )
|
4
|
+
|
5
|
+
require 'uri'
|
6
|
+
require 'minitest/unit'
|
7
|
+
require 'minitest/autorun'
|
8
|
+
|
9
|
+
require 'oauth_simple'
|
10
|
+
require 'oauth_simple/http'
|
11
|
+
|
12
|
+
class TestMain < MiniTest::Unit::TestCase
|
13
|
+
|
14
|
+
def test_proxy
|
15
|
+
http = OAuthSimple::HTTP.Proxy( '96.32.133.3', '8085' ).new( 'api.twitter.com' )
|
16
|
+
assert( http.is_a? OAuthSimple::HTTP )
|
17
|
+
end
|
18
|
+
|
19
|
+
def test_sign_simple
|
20
|
+
base_str = 'GET&http%3A%2F%2Fphotos.example.net%2Fphotos&file%3Dvacation.jpg%26oauth_consumer_key%3Ddpf43f3p2l4k3l03%26oauth_nonce%3Dkllo9940pd9333jh%26oauth_signature_method%3DHMAC-SHA1%26oauth_timestamp%3D1191242096%26oauth_token%3Dnnch734d00sl2jdk%26oauth_version%3D1.0%26size%3Doriginal'
|
21
|
+
secret_str = 'kd94hf93k423kf44&pfkkdhi9sl3r4s00'
|
22
|
+
signature = 'tR3+Ty81lMeYAr/Fid0kMTYa/WM='
|
23
|
+
digest = OpenSSL::HMAC::digest( OpenSSL::Digest::SHA1.new(), secret_str, base_str )
|
24
|
+
assert_equal( signature, [digest].pack('m').gsub!( /\n/u, '' ) )
|
25
|
+
base_str = 'POST&http%3A%2F%2Fexample.com%2Frequest&a2%3Dr%2520b%26a3%3D2%2520q%26a3%3Da%26b5%3D%253D%25253D%26c%2540%3D%26c2%3D%26oauth_consumer_key%3D9djdj82h48djs9d2%26oauth_nonce%3D7d8f3e4a%26oauth_signature_method%3DHMAC-SHA1%26oauth_timestamp%3D137131201%26oauth_token%3Dkkk9d7dh3k39sjv7'
|
26
|
+
secret_str = 'j49sk3j29djd&dh893hdasih9'
|
27
|
+
signature = 'r6%2FTJjbCOr97%2F%2BUU0NsvSne7s5g%3D'
|
28
|
+
digest = OpenSSL::HMAC::digest( OpenSSL::Digest::SHA1.new(), secret_str, base_str )
|
29
|
+
assert_equal( signature, OAuthSimple::HelperFunctions.enc_perenc( [digest].pack('m').gsub!( /\n/u, '' ) ) )
|
30
|
+
end
|
31
|
+
|
32
|
+
def test_nonce_string_creation
|
33
|
+
# 引数を与えなければ, 16 文字の文字列
|
34
|
+
nonce_str = OAuthSimple::HelperFunctions.create_nonce_str()
|
35
|
+
assert_equal( nonce_str.class, String )
|
36
|
+
assert_equal( nonce_str.length, 16 )
|
37
|
+
# 0 以上の整数を引数として与えると, その長さの文字列
|
38
|
+
[ 20, 0, 300, 432, 125432 ].each do |len|
|
39
|
+
nonce_str = OAuthSimple::HelperFunctions.create_nonce_str( len )
|
40
|
+
assert_equal( nonce_str.class, String )
|
41
|
+
assert_equal( nonce_str.length, len )
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
def test_helper
|
46
|
+
req_helper = OAuthSimple::RequestHelper.new(
|
47
|
+
URI.parse( 'https://api.twitter.com/oauth/request_token' ),
|
48
|
+
'POST',
|
49
|
+
'CONS_SECRET_XXXX&',
|
50
|
+
OAuthSimple::RequestParamList.new( [
|
51
|
+
# TwitVC
|
52
|
+
[ 'oauth_consumer_key', 'CONS_KEY_XXXX' ],
|
53
|
+
[ 'oauth_signature_method', 'HMAC-SHA1' ],
|
54
|
+
[ 'oauth_timestamp', ( Time.now() - Time.utc( 1970, 1, 1 ) ).to_i().to_s() ],
|
55
|
+
[ 'oauth_nonce', 'dfaeaveafefea' ],
|
56
|
+
[ 'oauth_version', '1.0' ],
|
57
|
+
] ),
|
58
|
+
)
|
59
|
+
assert_equal( req_helper.host, 'api.twitter.com' )
|
60
|
+
assert_equal( req_helper.port, 443 )
|
61
|
+
end
|
62
|
+
|
63
|
+
# RFC5849 Sec. 3.1 の試験
|
64
|
+
# http://tools.ietf.org/html/rfc5849
|
65
|
+
#
|
66
|
+
# POST /request?b5=%3D%253D&a3=a&c%40=&a2=r%20b HTTP/1.1
|
67
|
+
# Host: example.com
|
68
|
+
# Content-Type: application/x-www-form-urlencoded
|
69
|
+
#
|
70
|
+
# c2&a3=2+q
|
71
|
+
#
|
72
|
+
# The client assigns values to the following protocol parameters using
|
73
|
+
# its client credentials, token credentials, the current timestamp, a
|
74
|
+
# uniquely generated nonce, and indicates that it will use the
|
75
|
+
# "HMAC-SHA1" signature method:
|
76
|
+
# oauth_consumer_key: 9djdj82h48djs9d2
|
77
|
+
# oauth_token: kkk9d7dh3k39sjv7
|
78
|
+
# oauth_signature_method: HMAC-SHA1
|
79
|
+
# oauth_timestamp: 137131201
|
80
|
+
# oauth_nonce: 7d8f3e4a
|
81
|
+
def test_sign
|
82
|
+
client_secret = 'j49sk3j29djd'
|
83
|
+
token_secret = 'dh893hdasih9'
|
84
|
+
req_helper = OAuthSimple::RequestHelper.new(
|
85
|
+
URI.parse( 'http://example.com/request?b5=%3D%253D&a3=a&c%40=&a2=r%20b' ),
|
86
|
+
'POST',
|
87
|
+
"#{client_secret}&#{token_secret}",
|
88
|
+
OAuthSimple::RequestParamList.new( [
|
89
|
+
[ 'oauth_consumer_key', '9djdj82h48djs9d2' ],
|
90
|
+
[ 'oauth_token', 'kkk9d7dh3k39sjv7' ],
|
91
|
+
[ 'oauth_signature_method', 'HMAC-SHA1' ],
|
92
|
+
[ 'oauth_timestamp', '137131201' ],
|
93
|
+
[ 'oauth_nonce', '7d8f3e4a' ],
|
94
|
+
] ),
|
95
|
+
nil,
|
96
|
+
OAuthSimple::RequestParamList.new( [
|
97
|
+
[ 'c2', nil ],
|
98
|
+
[ 'a3', '2 q' ],
|
99
|
+
] ),
|
100
|
+
)
|
101
|
+
#p req_helper.oauth_header_str
|
102
|
+
end
|
103
|
+
|
104
|
+
def test_factory
|
105
|
+
rhf = OAuthSimple::RequestHelperFactory.new(
|
106
|
+
:consumer_key => '9djdj82h48djs9d2',
|
107
|
+
:consumer_secret => 'j49sk3j29djd' ,
|
108
|
+
:token => 'kkk9d7dh3k39sjv7',
|
109
|
+
:token_secret => 'dh893hdasih9' ,
|
110
|
+
:signature_method => 'HMAC-SHA1' ,
|
111
|
+
)
|
112
|
+
req_helper = rhf.create(
|
113
|
+
URI.parse( 'http://example.com/request?b5=%3D%253D&a3=a&c%40=&a2=r%20b' ),
|
114
|
+
'POST',
|
115
|
+
:body_params => OAuthSimple::RequestParamList.new( [
|
116
|
+
[ 'c2', nil ],
|
117
|
+
[ 'a3', '2 q' ],
|
118
|
+
] )
|
119
|
+
)
|
120
|
+
assert_equal( req_helper.class, OAuthSimple::RequestHelper )
|
121
|
+
#p req_helper.oauth_header_str
|
122
|
+
end
|
123
|
+
|
124
|
+
###
|
125
|
+
# test by using OAuth Test Server : http://term.ie/oauth/example/
|
126
|
+
def test_getting_request_token
|
127
|
+
# OAuthSimple::HTTP is a subclass of Net::HTTP
|
128
|
+
http = OAuthSimple::HTTP.new( 'term.ie' )
|
129
|
+
|
130
|
+
# OAuth setting (this feature provided by OAuthSimple::HTTP)
|
131
|
+
http.use_oauth = true
|
132
|
+
http.set_oauth_client_credentials( 'key', 'secret' )
|
133
|
+
http.set_oauth_signature_method( 'HMAC-SHA1' ) # at this time, only 'HMAC-SHA1' is supported
|
134
|
+
|
135
|
+
# connection start
|
136
|
+
http.start() do |http|
|
137
|
+
assert_equal( http.class, OAuthSimple::HTTP )
|
138
|
+
http.request_post( '/oauth/example/request_token.php', nil ) do |res|
|
139
|
+
assert_equal( '200', res.code )
|
140
|
+
assert_equal( 'oauth_token=requestkey&oauth_token_secret=requestsecret', res.body )
|
141
|
+
end
|
142
|
+
|
143
|
+
token, secret = http.request_oauth_temp_credentials( '/oauth/example/request_token.php', 'oob' )
|
144
|
+
end
|
145
|
+
end
|
146
|
+
|
147
|
+
end
|
148
|
+
|
149
|
+
__END__
|
150
|
+
|
151
|
+
assert( .... )
|
metadata
ADDED
@@ -0,0 +1,61 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: oauth_simple
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0.pre
|
5
|
+
prerelease: 6
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- NOBUOKA Yu
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2012-05-11 00:00:00.000000000 Z
|
13
|
+
dependencies: []
|
14
|
+
description:
|
15
|
+
email: nobuoka@vividcode.info
|
16
|
+
executables: []
|
17
|
+
extensions: []
|
18
|
+
extra_rdoc_files:
|
19
|
+
- README.rdoc
|
20
|
+
files:
|
21
|
+
- README.rdoc
|
22
|
+
- rakefile.rb
|
23
|
+
- .gemtest
|
24
|
+
- lib/oauth_simple/request_param_list.rb
|
25
|
+
- lib/oauth_simple/helper_functions.rb
|
26
|
+
- lib/oauth_simple/request_helper_factory.rb
|
27
|
+
- lib/oauth_simple/request_helper.rb
|
28
|
+
- lib/oauth_simple/http.rb
|
29
|
+
- lib/oauth_simple.rb
|
30
|
+
- test/helper_path_setting.rb
|
31
|
+
- test/test_http.rb
|
32
|
+
- test/test_main.rb
|
33
|
+
homepage: https://github.com/nobuoka/ruby-OAuthSimple
|
34
|
+
licenses: []
|
35
|
+
post_install_message:
|
36
|
+
rdoc_options:
|
37
|
+
- --charset=UTF-8
|
38
|
+
- --main
|
39
|
+
- README.rdoc
|
40
|
+
require_paths:
|
41
|
+
- lib
|
42
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
43
|
+
none: false
|
44
|
+
requirements:
|
45
|
+
- - ! '>='
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0'
|
48
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
49
|
+
none: false
|
50
|
+
requirements:
|
51
|
+
- - ! '>'
|
52
|
+
- !ruby/object:Gem::Version
|
53
|
+
version: 1.3.1
|
54
|
+
requirements: []
|
55
|
+
rubyforge_project:
|
56
|
+
rubygems_version: 1.8.24
|
57
|
+
signing_key:
|
58
|
+
specification_version: 3
|
59
|
+
summary: Helper for OAuth 1.0
|
60
|
+
test_files:
|
61
|
+
- test/test_main.rb
|