rest-graph 0.8.1 → 0.9.0
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGES +7 -0
- data/README +19 -12
- data/TODO +2 -1
- data/lib/rest-graph/version.rb +1 -1
- data/lib/rest-graph.rb +67 -37
- data/test/test_rest-graph.rb +41 -12
- metadata +4 -4
data/CHANGES
CHANGED
@@ -1,5 +1,12 @@
|
|
1
1
|
= rest-graph changes history
|
2
2
|
|
3
|
+
== rest-graph 0.9.0 -- 2010-05-04
|
4
|
+
* renamed :server option to :graph_server
|
5
|
+
* added :fql_server option and fql support.
|
6
|
+
* cookies related parsing utility is now instance methods.
|
7
|
+
you'll need to pass app_id and secret when initializing
|
8
|
+
* if sig in cookies is bad, then it won't extract the access_token
|
9
|
+
|
3
10
|
== rest-graph 0.8.1 -- 2010-05-03
|
4
11
|
* added access_token parsing utility
|
5
12
|
|
data/README
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
= rest-graph 0.
|
1
|
+
= rest-graph 0.9.0
|
2
2
|
by Lin Jen-Shin (aka godfat-真常[http://godfat.org])
|
3
3
|
godfat (XD) godfat.org
|
4
4
|
|
@@ -15,30 +15,37 @@ by Lin Jen-Shin (aka godfat-真常[http://godfat.org])
|
|
15
15
|
== SYNOPSIS:
|
16
16
|
|
17
17
|
require 'rest-graph'
|
18
|
+
|
19
|
+
# every option is optional!!
|
18
20
|
rg = RestGraph.new(:access_token => '...',
|
19
|
-
:
|
21
|
+
:graph_server => 'https://graph.facebook.com/',
|
22
|
+
:fql_server => 'https://api.facebook.com/',
|
20
23
|
:accept => 'text/javascript',
|
21
24
|
:lang => 'en-us', # this affect search
|
22
|
-
:auto_decode => true
|
25
|
+
:auto_decode => true, # decode by json
|
26
|
+
:app_id => '123',
|
27
|
+
:secret => '1829')
|
23
28
|
rg.get('me')
|
24
29
|
rg.post('feed/me', :message => 'bread!')
|
25
30
|
|
26
31
|
# for rack
|
27
|
-
app_id = '\d+'
|
28
32
|
lambda{ |env|
|
29
|
-
rg = RestGraph.new(:
|
30
|
-
|
33
|
+
rg = RestGraph.new(:app_id => '123', :secret => '1829')
|
34
|
+
rg.parse_token_in_rack_env!(env) # auto save access_token if sig checked
|
35
|
+
rg.access_token # => ...
|
31
36
|
}
|
32
37
|
|
33
38
|
# for fully blown cookies hash
|
34
|
-
|
35
|
-
rg
|
36
|
-
|
39
|
+
rg = RestGraph.new(:app_id => '123', :secret => '1829')
|
40
|
+
rg.parse_token_in_cookies!(cookies) # auto save access_token if sig checked
|
41
|
+
rg.access_token # => ...
|
37
42
|
|
38
|
-
# for
|
43
|
+
# for fbs in cookies
|
39
44
|
app_id = '456'
|
40
|
-
rg = RestGraph.new(:
|
41
|
-
|
45
|
+
rg = RestGraph.new(:app_id => '123', :secret => '1829')
|
46
|
+
fbs = cookies["fbs_#{rg.app_id}"]
|
47
|
+
rg.parse_token_in_fbs!(fbs) # auto save access_token if sig checked
|
48
|
+
rg.access_token # => ...
|
42
49
|
|
43
50
|
== REQUIREMENTS:
|
44
51
|
|
data/TODO
CHANGED
data/lib/rest-graph/version.rb
CHANGED
data/lib/rest-graph.rb
CHANGED
@@ -3,63 +3,82 @@ require 'rest_client'
|
|
3
3
|
|
4
4
|
require 'cgi'
|
5
5
|
|
6
|
-
class RestGraph
|
7
|
-
|
8
|
-
def self.parse_token_in_rack_env env, app_id = '\d+'
|
9
|
-
env['HTTP_COOKIE'] =~ /fbs_#{app_id}="(.+?)"/ &&
|
10
|
-
Rack::Utils.parse_query($1)['access_token']
|
11
|
-
end
|
12
|
-
|
13
|
-
def self.parse_token_in_cookies cookies, app_id
|
14
|
-
parse_token_in_fb_cookie(cookies["fbs_#{app_id}"])
|
15
|
-
end
|
16
|
-
|
17
|
-
def self.parse_token_in_fb_cookie fb_cookie
|
18
|
-
fb_cookie && Rack::Utils.parse_query(fb_cookie[1..-2])['access_token']
|
19
|
-
end
|
20
|
-
|
21
|
-
attr_accessor :access_token, :server, :accept, :lang, :auto_decode
|
6
|
+
class RestGraph < Struct.new(:access_token, :graph_server, :fql_server,
|
7
|
+
:accept, :lang, :auto_decode, :app_id, :secret)
|
22
8
|
def initialize o = {}
|
23
9
|
self.access_token = o[:access_token]
|
24
|
-
self.
|
10
|
+
self.graph_server = o[:graph_server] || 'https://graph.facebook.com/'
|
11
|
+
self.fql_server = o[:fql_server] || 'https://api.facebook.com/'
|
25
12
|
self.accept = o[:accept] || 'text/javascript'
|
26
13
|
self.lang = o[:lang] || 'en-us'
|
27
14
|
self.auto_decode = o.key?(:auto_decode) ? o[:auto_decode] : true
|
15
|
+
self.app_id = o[:app_id]
|
16
|
+
self.secret = o[:secret]
|
28
17
|
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
18
|
+
check_arguments!
|
19
|
+
end
|
20
|
+
|
21
|
+
def get path, opts = {}
|
22
|
+
request(graph_server, path, opts, :get)
|
23
|
+
end
|
24
|
+
|
25
|
+
def delete path, opts = {}
|
26
|
+
request(graph_server, path, opts, :delete)
|
27
|
+
end
|
28
|
+
|
29
|
+
def post path, payload, opts = {}
|
30
|
+
request(graph_server, path, opts, :post, payload)
|
36
31
|
end
|
37
32
|
|
38
|
-
def
|
39
|
-
|
33
|
+
def put path, payload, opts = {}
|
34
|
+
request(graph_server, path, opts, :put, payload)
|
40
35
|
end
|
41
36
|
|
42
|
-
def
|
43
|
-
request(
|
37
|
+
def fql query, opts = {}
|
38
|
+
request(fql_server, 'method/fql.query',
|
39
|
+
{:query => query, :format => 'json'}.merge(opts), :get)
|
44
40
|
end
|
45
41
|
|
46
|
-
|
47
|
-
|
42
|
+
# cookies, app_id, secrect related below
|
43
|
+
|
44
|
+
def parse_token_in_rack_env! env
|
45
|
+
self.access_token = env['HTTP_COOKIE'] =~ /fbs_#{app_id}="(.+?)"/ &&
|
46
|
+
extract_token_if_sig_ok(Rack::Utils.parse_query($1))
|
48
47
|
end
|
49
48
|
|
50
|
-
def
|
51
|
-
|
49
|
+
def parse_token_in_cookies! cookies
|
50
|
+
self.access_token = parse_token_in_fbs!(cookies["fbs_#{app_id}"])
|
52
51
|
end
|
53
52
|
|
54
|
-
def
|
55
|
-
|
53
|
+
def parse_token_in_fbs! fbs
|
54
|
+
self.access_token = fbs &&
|
55
|
+
extract_token_if_sig_ok(Rack::Utils.parse_query(fbs[1..-2]))
|
56
56
|
end
|
57
57
|
|
58
58
|
private
|
59
|
-
def
|
59
|
+
def check_arguments!
|
60
|
+
if auto_decode
|
61
|
+
begin
|
62
|
+
require 'json'
|
63
|
+
rescue LoadError
|
64
|
+
require 'json_pure'
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
if app_id && secret # want to parse access_token in cookies
|
69
|
+
require 'digest/md5'
|
70
|
+
require 'rack'
|
71
|
+
elsif app_id || secret
|
72
|
+
raise ArgumentError.new("You may want pass both" \
|
73
|
+
" app_id(#{app_id.inspect}) and" \
|
74
|
+
" secret(#{secret.inspect})")
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
def request server, path, opts, method, payload = nil
|
60
79
|
post_request(
|
61
|
-
|
62
|
-
|
80
|
+
RestClient::Resource.new(server)[path + build_query_string(opts)].
|
81
|
+
send(method, *[payload, build_headers].compact))
|
63
82
|
rescue RestClient::InternalServerError => e
|
64
83
|
post_request(e.http_body)
|
65
84
|
end
|
@@ -80,4 +99,15 @@ class RestGraph
|
|
80
99
|
def post_request result
|
81
100
|
auto_decode ? JSON.parse(result) : result
|
82
101
|
end
|
102
|
+
|
103
|
+
def extract_token_if_sig_ok cookies
|
104
|
+
cookies['access_token'] if calculate_sig(cookies) == cookies['sig']
|
105
|
+
end
|
106
|
+
|
107
|
+
def calculate_sig cookies
|
108
|
+
payload = cookies.reject{ |(k, v)| k == 'sig' }.sort.
|
109
|
+
map{ |a| a.join('=') }.join
|
110
|
+
|
111
|
+
Digest::MD5.hexdigest(payload + secret)
|
112
|
+
end
|
83
113
|
end
|
data/test/test_rest-graph.rb
CHANGED
@@ -59,7 +59,7 @@ describe RestGraph do
|
|
59
59
|
{'User-Agent' => 'Ruby'})). # this is by ruby
|
60
60
|
to_return(:body => '{"data": []}')
|
61
61
|
|
62
|
-
RestGraph.new(:
|
62
|
+
RestGraph.new(:graph_server => 'http://nothing.godfat.org/',
|
63
63
|
:lang => 'zh-tw',
|
64
64
|
:accept => 'text/plain').get('me').should == {'data' => []}
|
65
65
|
end
|
@@ -104,22 +104,51 @@ describe RestGraph do
|
|
104
104
|
RestGraph.new.delete('123').should == []
|
105
105
|
end
|
106
106
|
|
107
|
-
it 'would extract correct access_token' do
|
107
|
+
it 'would extract correct access_token or fail checking sig' do
|
108
108
|
access_token = '1|2-5|f.'
|
109
109
|
app_id = '1829'
|
110
|
+
secret = app_id.reverse
|
111
|
+
sig = '398262caea8442bd8801e8fba7c55c8a'
|
110
112
|
fbs = "\"access_token=#{CGI.escape(access_token)}&expires=0&" \
|
111
|
-
"secret=abc&session_key=def-456&sig
|
112
|
-
|
113
|
-
|
114
|
-
|
113
|
+
"secret=abc&session_key=def-456&sig=#{sig}&uid=3\""
|
114
|
+
|
115
|
+
check = lambda{ |token|
|
116
|
+
http_cookie =
|
117
|
+
"__utma=123; __utmz=456.utmcsr=(d)|utmccn=(d)|utmcmd=(n); " \
|
118
|
+
"fbs_#{app_id}=#{fbs}"
|
119
|
+
|
120
|
+
rg = RestGraph.new(:app_id => app_id, :secret => secret)
|
121
|
+
rg.parse_token_in_rack_env!('HTTP_COOKIE' => http_cookie).
|
122
|
+
should == token
|
123
|
+
rg.access_token.should == token
|
124
|
+
|
125
|
+
rg.parse_token_in_cookies!({"fbs_#{app_id}" => fbs}).
|
126
|
+
should == token
|
127
|
+
rg.access_token.should == token
|
128
|
+
|
129
|
+
rg.parse_token_in_fbs!(fbs).
|
130
|
+
should == token
|
131
|
+
rg.access_token.should == token
|
132
|
+
}
|
133
|
+
check.call(access_token)
|
134
|
+
fbs.chop!
|
135
|
+
fbs += '&inject=evil"'
|
136
|
+
check.call(nil)
|
137
|
+
end
|
138
|
+
|
139
|
+
it 'would do fql query with/without access_token' do
|
140
|
+
fql = 'SELECT name FROM likes where id="123"'
|
141
|
+
query = "query=#{fql}&format=json"
|
142
|
+
stub_request(:get, "https://api.facebook.com/method/fql.query?#{query}").
|
143
|
+
to_return(:body => '[]')
|
115
144
|
|
116
|
-
RestGraph.
|
117
|
-
should == access_token
|
145
|
+
RestGraph.new.fql(fql).should == []
|
118
146
|
|
119
|
-
|
120
|
-
|
147
|
+
token = 'token'.reverse
|
148
|
+
stub_request(:get, "https://api.facebook.com/method/fql.query?#{query}" \
|
149
|
+
"&access_token=#{token}").
|
150
|
+
to_return(:body => '[]')
|
121
151
|
|
122
|
-
RestGraph.
|
123
|
-
should == access_token
|
152
|
+
RestGraph.new(:access_token => token).fql(fql).should == []
|
124
153
|
end
|
125
154
|
end
|
metadata
CHANGED
@@ -4,9 +4,9 @@ version: !ruby/object:Gem::Version
|
|
4
4
|
prerelease: false
|
5
5
|
segments:
|
6
6
|
- 0
|
7
|
-
-
|
8
|
-
-
|
9
|
-
version: 0.
|
7
|
+
- 9
|
8
|
+
- 0
|
9
|
+
version: 0.9.0
|
10
10
|
platform: ruby
|
11
11
|
authors:
|
12
12
|
- "Lin Jen-Shin (aka godfat \xE7\x9C\x9F\xE5\xB8\xB8)"
|
@@ -14,7 +14,7 @@ autorequire:
|
|
14
14
|
bindir: bin
|
15
15
|
cert_chain: []
|
16
16
|
|
17
|
-
date: 2010-05-
|
17
|
+
date: 2010-05-04 00:00:00 +08:00
|
18
18
|
default_executable:
|
19
19
|
dependencies:
|
20
20
|
- !ruby/object:Gem::Dependency
|