rest-graph 0.8.1 → 0.9.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.
- 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
|