koala 1.0.0.beta2.1 → 1.0.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/.gitignore +3 -0
- data/CHANGELOG +15 -12
- data/Gemfile +3 -0
- data/LICENSE +1 -1
- data/Rakefile +13 -14
- data/koala.gemspec +35 -20
- data/lib/koala/graph_api.rb +2 -2
- data/lib/koala/http_services.rb +32 -27
- data/lib/koala/test_users.rb +4 -4
- data/lib/koala/uploadable_io.rb +1 -1
- data/lib/koala.rb +29 -54
- data/readme.md +15 -8
- data/spec/cases/api_base_spec.rb +101 -0
- data/spec/cases/graph_and_rest_api_spec.rb +31 -0
- data/spec/cases/graph_api_spec.rb +25 -0
- data/spec/{koala/http_services/http_service_tests.rb → cases/http_services/http_service_spec.rb} +8 -5
- data/spec/cases/http_services/net_http_service_spec.rb +350 -0
- data/spec/cases/http_services/typhoeus_service_spec.rb +144 -0
- data/spec/cases/oauth_spec.rb +409 -0
- data/spec/cases/realtime_updates_spec.rb +184 -0
- data/spec/cases/rest_api_spec.rb +25 -0
- data/spec/{koala/test_users/test_users_tests.rb → cases/test_users_spec.rb} +34 -29
- data/spec/cases/uploadable_io_spec.rb +151 -0
- data/spec/{facebook_data.yml → fixtures/facebook_data.yml} +5 -5
- data/spec/{mock_facebook_responses.yml → fixtures/mock_facebook_responses.yml} +313 -311
- data/spec/spec_helper.rb +18 -0
- data/spec/support/graph_api_shared_examples.rb +424 -0
- data/spec/{koala → support}/live_testing_data_helper.rb +39 -42
- data/spec/{mock_http_service.rb → support/mock_http_service.rb} +94 -94
- data/spec/{koala/rest_api/rest_api_tests.rb → support/rest_api_shared_examples.rb} +43 -0
- data/spec/support/setup_mocks_or_live.rb +52 -0
- data/spec/support/uploadable_io_shared_examples.rb +76 -0
- metadata +106 -53
- data/init.rb +0 -2
- data/spec/koala/api_base_tests.rb +0 -102
- data/spec/koala/graph_and_rest_api/graph_and_rest_api_no_token_tests.rb +0 -14
- data/spec/koala/graph_and_rest_api/graph_and_rest_api_with_token_tests.rb +0 -16
- data/spec/koala/graph_api/graph_api_no_access_token_tests.rb +0 -65
- data/spec/koala/graph_api/graph_api_tests.rb +0 -85
- data/spec/koala/graph_api/graph_api_with_access_token_tests.rb +0 -194
- data/spec/koala/graph_api/graph_collection_tests.rb +0 -104
- data/spec/koala/http_services/net_http_service_tests.rb +0 -339
- data/spec/koala/http_services/typhoeus_service_tests.rb +0 -162
- data/spec/koala/oauth/oauth_tests.rb +0 -372
- data/spec/koala/realtime_updates/realtime_updates_tests.rb +0 -187
- data/spec/koala/rest_api/rest_api_no_access_token_tests.rb +0 -25
- data/spec/koala/rest_api/rest_api_with_access_token_tests.rb +0 -38
- data/spec/koala/uploadable_io/uploadable_io_tests.rb +0 -246
- data/spec/koala_spec.rb +0 -18
- data/spec/koala_spec_helper.rb +0 -74
- data/spec/koala_spec_without_mocks.rb +0 -19
- /data/spec/{koala/assets → fixtures}/beach.jpg +0 -0
data/.gitignore
ADDED
data/CHANGELOG
CHANGED
|
@@ -1,26 +1,29 @@
|
|
|
1
1
|
v1.0
|
|
2
2
|
New methods:
|
|
3
3
|
-- Photo and file upload now supported through #put_picture
|
|
4
|
-
--
|
|
5
|
-
|
|
6
|
-
-- Added
|
|
7
|
-
-- Beta 2: Added put_connection and delete_connection convenience methods
|
|
4
|
+
-- Added UploadableIO class to manage file uploads
|
|
5
|
+
-- Added a delete_like method (thanks to waseem)
|
|
6
|
+
-- Added put_connection and delete_connection convenience methods
|
|
8
7
|
Updated methods:
|
|
9
|
-
--
|
|
10
|
-
--
|
|
11
|
-
--
|
|
8
|
+
-- Search can now search places, checkins, etc. (thanks, rickyc!)
|
|
9
|
+
-- You can now pass :beta => true in the http options to use Facebook's beta tier.
|
|
10
|
+
-- TestUser#befriend now requires user info hashes (id and access token) due to Facebook API changes (thanks, pulsd and kbighorse!)
|
|
11
|
+
-- All methods now accept an http_options hash as their optional last parameter (thanks, spiegela!)
|
|
12
|
+
-- url_for_oauth_code can now take a :display option (thanks, netbe!)
|
|
13
|
+
-- Net::HTTP can now accept :timeout and :proxy options (thanks, gilles!)
|
|
14
|
+
-- Test users now supports using test accounts across multiple apps
|
|
12
15
|
Internal improvements:
|
|
13
16
|
-- For public requests, Koala now uses http by default (instead of https) to improve speed
|
|
14
17
|
-- This can be overridden through Koala.always_use_ssl= or by passing :use_ssl => true in the options hash for an api call
|
|
15
18
|
-- Read-only REST API requests now go through the faster api-read server
|
|
16
19
|
-- Replaced parse_signed_request with a version from Facebook that also supports the new signed params proposal
|
|
17
20
|
-- Note: invalid requests will now raise exceptions rather than return nil, in keeping with other SDKs
|
|
18
|
-
--
|
|
19
|
-
--
|
|
20
|
-
--
|
|
21
|
-
--
|
|
22
|
-
-- Beta 3: Updated parse_signed_request to match Facebook's current implementation (thanks, imajes!)
|
|
21
|
+
-- Delete methods will now raise an error if there's no access token (like put_object and delete_like)
|
|
22
|
+
-- Updated parse_signed_request to match Facebook's current implementation (thanks, imajes!)
|
|
23
|
+
-- APIError is now < StandardError, not Exception
|
|
24
|
+
-- Added KoalaError for non-API errors
|
|
23
25
|
Test improvements:
|
|
26
|
+
-- Incorporated joshk's awesome rewrite of the entire Koala test suite (thanks, joshk!)
|
|
24
27
|
-- Expanded HTTP service tests (added Typhoeus test suite and additional Net::HTTP test cases)
|
|
25
28
|
-- Live tests now verify that the access token has the necessary permissions before starting
|
|
26
29
|
-- Replaced the 50-person network test, which often took 15+ minutes to run live, with a 5-person test
|
data/Gemfile
ADDED
data/LICENSE
CHANGED
data/Rakefile
CHANGED
|
@@ -1,17 +1,16 @@
|
|
|
1
|
-
# Rakefile
|
|
2
|
-
require 'rubygems'
|
|
3
1
|
require 'rake'
|
|
4
|
-
require 'echoe'
|
|
5
2
|
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
3
|
+
begin
|
|
4
|
+
require 'bundler/setup'
|
|
5
|
+
Bundler::GemHelper.install_tasks
|
|
6
|
+
rescue LoadError
|
|
7
|
+
puts 'although not required, bundler is recommened for running the tests'
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
task :default => :spec
|
|
12
|
+
|
|
13
|
+
require 'rspec/core/rake_task'
|
|
14
|
+
RSpec::Core::RakeTask.new do |t|
|
|
15
|
+
t.rspec_opts = ["--color", '--format doc']
|
|
17
16
|
end
|
data/koala.gemspec
CHANGED
|
@@ -1,35 +1,50 @@
|
|
|
1
1
|
# -*- encoding: utf-8 -*-
|
|
2
2
|
|
|
3
3
|
Gem::Specification.new do |s|
|
|
4
|
-
s.name
|
|
5
|
-
s.version = "1.0.0
|
|
4
|
+
s.name = %q{koala}
|
|
5
|
+
s.version = "1.0.0"
|
|
6
|
+
s.date = %q{2011-05-01}
|
|
7
|
+
|
|
8
|
+
s.summary = %q{A lightweight, flexible library for Facebook with support for the Graph API, the REST API, realtime updates, and OAuth authentication.}
|
|
9
|
+
s.description = %q{Koala is a lightweight, flexible Ruby SDK for Facebook. It allows read/write access to the social graph via the Graph and REST APIs, as well as support for realtime updates and OAuth and Facebook Connect authentication. Koala is fully tested and supports Net::HTTP and Typhoeus connections out of the box and can accept custom modules for other services.}
|
|
10
|
+
s.homepage = %q{http://github.com/arsduo/koala}
|
|
6
11
|
|
|
7
|
-
s.required_rubygems_version = Gem::Requirement.new(">= 1.2") if s.respond_to? :required_rubygems_version=
|
|
8
12
|
s.authors = ["Alex Koppel, Chris Baclig, Rafi Jacoby, Context Optional"]
|
|
9
|
-
s.
|
|
10
|
-
|
|
11
|
-
s.
|
|
12
|
-
s.
|
|
13
|
-
|
|
14
|
-
s.
|
|
15
|
-
s.rdoc_options
|
|
16
|
-
|
|
17
|
-
s.
|
|
18
|
-
|
|
19
|
-
s.
|
|
13
|
+
s.email = %q{alex@alexkoppel.com}
|
|
14
|
+
|
|
15
|
+
s.files = `git ls-files`.split("\n")
|
|
16
|
+
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
|
17
|
+
|
|
18
|
+
s.extra_rdoc_files = ["readme.md", "CHANGELOG"]
|
|
19
|
+
s.rdoc_options = ["--line-numbers", "--inline-source", "--title", "Koala"]
|
|
20
|
+
|
|
21
|
+
s.require_paths = ["lib"]
|
|
22
|
+
|
|
23
|
+
s.rubygems_version = %q{1.4.2}
|
|
24
|
+
|
|
25
|
+
s.required_rubygems_version = Gem::Requirement.new(">= 1.2") if s.respond_to? :required_rubygems_version=
|
|
20
26
|
|
|
21
27
|
if s.respond_to? :specification_version then
|
|
22
28
|
s.specification_version = 3
|
|
23
29
|
|
|
24
30
|
if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
|
|
25
|
-
s.add_runtime_dependency(%q<json>,
|
|
26
|
-
s.add_runtime_dependency(%q<multipart-post>,
|
|
31
|
+
s.add_runtime_dependency(%q<json>, ["~> 1.0"])
|
|
32
|
+
s.add_runtime_dependency(%q<multipart-post>, ["~> 1.0"])
|
|
33
|
+
s.add_development_dependency(%q<rspec>, ["~> 2.5.0"])
|
|
34
|
+
s.add_development_dependency(%q<rake>, ["~> 0.8.7"])
|
|
35
|
+
s.add_development_dependency(%q<typhoeus>, ["~> 0.2.4"])
|
|
27
36
|
else
|
|
28
|
-
s.add_dependency(%q<json>,
|
|
29
|
-
s.add_dependency(%q<multipart-post>,
|
|
37
|
+
s.add_dependency(%q<json>, ["~> 1.0"])
|
|
38
|
+
s.add_dependency(%q<multipart-post>, ["~> 1.0"])
|
|
39
|
+
s.add_dependency(%q<rspec>, ["~> 2.5.0"])
|
|
40
|
+
s.add_dependency(%q<rake>, ["~> 0.8.7"])
|
|
41
|
+
s.add_dependency(%q<typhoeus>, ["~> 0.2.4"])
|
|
30
42
|
end
|
|
31
43
|
else
|
|
32
|
-
s.add_dependency(%q<json>,
|
|
33
|
-
s.add_dependency(%q<multipart-post>,
|
|
44
|
+
s.add_dependency(%q<json>, ["~> 1.0"])
|
|
45
|
+
s.add_dependency(%q<multipart-post>, ["~> 1.0"])
|
|
46
|
+
s.add_dependency(%q<rspec>, ["~> 2.5.0"])
|
|
47
|
+
s.add_dependency(%q<rake>, ["~> 0.8.7"])
|
|
48
|
+
s.add_dependency(%q<typhoeus>, ["~> 0.2.4"])
|
|
34
49
|
end
|
|
35
50
|
end
|
data/lib/koala/graph_api.rb
CHANGED
|
@@ -171,8 +171,8 @@ module Koala
|
|
|
171
171
|
# Search
|
|
172
172
|
|
|
173
173
|
def search(search_terms, args = {}, options = {})
|
|
174
|
-
|
|
175
|
-
result = graph_call("search", args
|
|
174
|
+
args.merge!({:q => search_terms}) unless search_terms.nil?
|
|
175
|
+
result = graph_call("search", args, "get", options)
|
|
176
176
|
result ? GraphCollection.new(result, self) : nil # when facebook is down nil can be returned
|
|
177
177
|
end
|
|
178
178
|
|
data/lib/koala/http_services.rb
CHANGED
|
@@ -54,7 +54,7 @@ module Koala
|
|
|
54
54
|
# if the verb isn't get or post, send it as a post argument
|
|
55
55
|
args.merge!({:method => verb}) && verb = "post" if verb != "get" && verb != "post"
|
|
56
56
|
|
|
57
|
-
http =
|
|
57
|
+
http = create_http(server(options), private_request, options)
|
|
58
58
|
http.use_ssl = true if private_request
|
|
59
59
|
|
|
60
60
|
result = http.start do |http|
|
|
@@ -87,6 +87,22 @@ module Koala
|
|
|
87
87
|
[key, value.kind_of?(Koala::UploadableIO) ? value.to_upload_io : value]
|
|
88
88
|
end.flatten]
|
|
89
89
|
end
|
|
90
|
+
|
|
91
|
+
def self.create_http(server, private_request, options)
|
|
92
|
+
if options[:proxy]
|
|
93
|
+
proxy = URI.parse(options[:proxy])
|
|
94
|
+
http = Net::HTTP.new(server, private_request ? 443 : nil,
|
|
95
|
+
proxy.host, proxy.port, proxy.user, proxy.password)
|
|
96
|
+
else
|
|
97
|
+
http = Net::HTTP.new(server, private_request ? 443 : nil)
|
|
98
|
+
end
|
|
99
|
+
if options[:timeout]
|
|
100
|
+
http.open_timeout = options[:timeout]
|
|
101
|
+
http.read_timeout = options[:timeout]
|
|
102
|
+
end
|
|
103
|
+
http
|
|
104
|
+
end
|
|
105
|
+
|
|
90
106
|
end
|
|
91
107
|
end
|
|
92
108
|
end
|
|
@@ -94,11 +110,6 @@ module Koala
|
|
|
94
110
|
module TyphoeusService
|
|
95
111
|
# this service uses Typhoeus to send requests to the graph
|
|
96
112
|
|
|
97
|
-
# used for multipart file uploads (see below)
|
|
98
|
-
class NetHTTPInterface
|
|
99
|
-
include NetHTTPService
|
|
100
|
-
end
|
|
101
|
-
|
|
102
113
|
def self.included(base)
|
|
103
114
|
base.class_eval do
|
|
104
115
|
require "typhoeus" unless defined?(Typhoeus)
|
|
@@ -107,34 +118,28 @@ module Koala
|
|
|
107
118
|
include Koala::HTTPService
|
|
108
119
|
|
|
109
120
|
def self.make_request(path, args, verb, options = {})
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
args.merge!({:method => verb}) && verb = "post" if verb != "get" && verb != "post"
|
|
121
|
+
# if the verb isn't get or post, send it as a post argument
|
|
122
|
+
args.merge!({:method => verb}) && verb = "post" if verb != "get" && verb != "post"
|
|
113
123
|
|
|
114
|
-
|
|
115
|
-
|
|
124
|
+
# switch any UploadableIOs to the files Typhoeus expects
|
|
125
|
+
args.each_pair {|key, value| args[key] = value.to_file if value.is_a?(UploadableIO)}
|
|
116
126
|
|
|
117
|
-
|
|
118
|
-
|
|
127
|
+
# you can pass arguments directly to Typhoeus using the :typhoeus_options key
|
|
128
|
+
typhoeus_options = {:params => args}.merge(options[:typhoeus_options] || {})
|
|
119
129
|
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
130
|
+
# by default, we use SSL only for private requests (e.g. with access token)
|
|
131
|
+
# this makes public requests faster
|
|
132
|
+
prefix = (args["access_token"] || @always_use_ssl || options[:use_ssl]) ? "https" : "http"
|
|
123
133
|
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
else
|
|
127
|
-
# we have to use NetHTTPService for multipart for file uploads
|
|
128
|
-
# until Typhoeus integrates support
|
|
129
|
-
Koala::TyphoeusService::NetHTTPInterface.make_request(path, args, verb, options)
|
|
130
|
-
end
|
|
134
|
+
response = self.send(verb, "#{prefix}://#{server(options)}#{path}", typhoeus_options)
|
|
135
|
+
Koala::Response.new(response.code, response.body, response.headers_hash)
|
|
131
136
|
end
|
|
132
137
|
|
|
133
138
|
private
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
139
|
+
|
|
140
|
+
def self.multipart_requires_content_type?
|
|
141
|
+
false # Typhoeus handles multipart file types, we don't have to require it
|
|
142
|
+
end
|
|
138
143
|
end # class_eval
|
|
139
144
|
end
|
|
140
145
|
end
|
data/lib/koala/test_users.rb
CHANGED
|
@@ -20,11 +20,11 @@ module Koala
|
|
|
20
20
|
@graph_api = GraphAPI.new(@app_access_token)
|
|
21
21
|
end
|
|
22
22
|
|
|
23
|
-
def create(installed, permissions = nil)
|
|
23
|
+
def create(installed, permissions = nil, args = {}, options = {})
|
|
24
24
|
# Creates and returns a test user
|
|
25
|
-
args
|
|
25
|
+
args['installed'] = installed
|
|
26
26
|
args['permissions'] = (permissions.is_a?(Array) ? permissions.join(",") : permissions) if installed
|
|
27
|
-
result = @graph_api.graph_call(accounts_path, args, "post")
|
|
27
|
+
result = @graph_api.graph_call(accounts_path, args, "post", options)
|
|
28
28
|
end
|
|
29
29
|
|
|
30
30
|
def list
|
|
@@ -49,7 +49,7 @@ module Koala
|
|
|
49
49
|
# we explicitly raise an error here to minimize the risk of confusing output
|
|
50
50
|
# if you pass in a string (as was previously supported) no local exception would be raised
|
|
51
51
|
# but the Facebook call would fail
|
|
52
|
-
raise ArgumentError, "TestUsers#befriend requires hash arguments with id and access_token"
|
|
52
|
+
raise ArgumentError, "TestUsers#befriend requires hash arguments for both users with id and access_token"
|
|
53
53
|
end
|
|
54
54
|
|
|
55
55
|
u1_graph_api = GraphAPI.new(user1_token)
|
data/lib/koala/uploadable_io.rb
CHANGED
|
@@ -42,7 +42,7 @@ module Koala
|
|
|
42
42
|
|
|
43
43
|
# Expects a parameter of type ActionDispatch::Http::UploadedFile
|
|
44
44
|
def parse_rails_3_param(uploaded_file)
|
|
45
|
-
if uploaded_file.respond_to?(:content_type) and uploaded_file.respond_to?(:tempfile) and uploaded_file.respond_to?(:path)
|
|
45
|
+
if uploaded_file.respond_to?(:content_type) and uploaded_file.respond_to?(:tempfile) and uploaded_file.tempfile.respond_to?(:path)
|
|
46
46
|
@io_or_path = uploaded_file.tempfile.path
|
|
47
47
|
@content_type = uploaded_file.content_type
|
|
48
48
|
end
|
data/lib/koala.rb
CHANGED
|
@@ -1,27 +1,17 @@
|
|
|
1
1
|
require 'cgi'
|
|
2
2
|
require 'digest/md5'
|
|
3
3
|
|
|
4
|
-
# rubygems is required to support json, how facebook returns data
|
|
5
|
-
require 'rubygems'
|
|
6
4
|
require 'json'
|
|
7
5
|
|
|
8
6
|
# OpenSSL and Base64 are required to support signed_request
|
|
9
7
|
require 'openssl'
|
|
10
8
|
require 'base64'
|
|
11
9
|
|
|
12
|
-
# include
|
|
10
|
+
# include koala modules
|
|
13
11
|
require 'koala/http_services'
|
|
14
|
-
|
|
15
|
-
# add Graph API methods
|
|
16
12
|
require 'koala/graph_api'
|
|
17
|
-
|
|
18
|
-
# add REST API methods
|
|
19
13
|
require 'koala/rest_api'
|
|
20
|
-
|
|
21
|
-
# add realtime update methods
|
|
22
14
|
require 'koala/realtime_updates'
|
|
23
|
-
|
|
24
|
-
# add test user methods
|
|
25
15
|
require 'koala/test_users'
|
|
26
16
|
|
|
27
17
|
# add KoalaIO class
|
|
@@ -31,28 +21,12 @@ module Koala
|
|
|
31
21
|
|
|
32
22
|
module Facebook
|
|
33
23
|
# Ruby client library for the Facebook Platform.
|
|
34
|
-
# Copyright 2010
|
|
35
|
-
#
|
|
36
|
-
#
|
|
37
|
-
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
|
38
|
-
# not use this file except in compliance with the License. You may obtain
|
|
39
|
-
# a copy of the License at
|
|
40
|
-
# http://www.apache.org/licenses/LICENSE-2.0
|
|
41
|
-
#
|
|
42
|
-
# Unless required by applicable law or agreed to in writing, software
|
|
43
|
-
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
|
44
|
-
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
|
45
|
-
# License for the specific language governing permissions and limitations
|
|
46
|
-
# under the License.
|
|
47
|
-
#
|
|
48
|
-
# This client library is designed to support the Graph API and the official
|
|
49
|
-
# Facebook JavaScript SDK, which is the canonical way to implement
|
|
50
|
-
# Facebook authentication. Read more about the Graph API at
|
|
51
|
-
# http://developers.facebook.com/docs/api. You can download the Facebook
|
|
52
|
-
# JavaScript SDK at http://github.com/facebook/connect-js/.
|
|
24
|
+
# Copyright 2010-2011 Alex Koppel
|
|
25
|
+
# Contributors: Alex Koppel, Chris Baclig, Rafi Jacoby, and the team at Context Optional
|
|
26
|
+
# http://github.com/arsduo/koala
|
|
53
27
|
|
|
54
28
|
class API
|
|
55
|
-
# initialize with an access token
|
|
29
|
+
# initialize with an access token
|
|
56
30
|
def initialize(access_token = nil)
|
|
57
31
|
@access_token = access_token
|
|
58
32
|
end
|
|
@@ -61,7 +35,7 @@ module Koala
|
|
|
61
35
|
def api(path, args = {}, verb = "get", options = {}, &error_checking_block)
|
|
62
36
|
# Fetches the given path in the Graph API.
|
|
63
37
|
args["access_token"] = @access_token || @app_access_token if @access_token || @app_access_token
|
|
64
|
-
|
|
38
|
+
|
|
65
39
|
# add a leading /
|
|
66
40
|
path = "/#{path}" unless path =~ /^\//
|
|
67
41
|
|
|
@@ -173,12 +147,13 @@ module Koala
|
|
|
173
147
|
# for permissions, see http://developers.facebook.com/docs/authentication/permissions
|
|
174
148
|
permissions = options[:permissions]
|
|
175
149
|
scope = permissions ? "&scope=#{permissions.is_a?(Array) ? permissions.join(",") : permissions}" : ""
|
|
176
|
-
|
|
150
|
+
display = options.has_key?(:display) ? "&display=#{options[:display]}" : ""
|
|
151
|
+
|
|
177
152
|
callback = options[:callback] || @oauth_callback_url
|
|
178
153
|
raise ArgumentError, "url_for_oauth_code must get a callback either from the OAuth object or in the options!" unless callback
|
|
179
154
|
|
|
180
155
|
# Creates the URL for oauth authorization for a given callback and optional set of permissions
|
|
181
|
-
"https://#{GRAPH_SERVER}/oauth/authorize?client_id=#{@app_id}&redirect_uri=#{callback}#{scope}"
|
|
156
|
+
"https://#{GRAPH_SERVER}/oauth/authorize?client_id=#{@app_id}&redirect_uri=#{callback}#{scope}#{display}"
|
|
182
157
|
end
|
|
183
158
|
|
|
184
159
|
def url_for_access_token(code, options = {})
|
|
@@ -188,26 +163,26 @@ module Koala
|
|
|
188
163
|
"https://#{GRAPH_SERVER}/oauth/access_token?client_id=#{@app_id}&redirect_uri=#{callback}&client_secret=#{@app_secret}&code=#{code}"
|
|
189
164
|
end
|
|
190
165
|
|
|
191
|
-
def get_access_token_info(code)
|
|
166
|
+
def get_access_token_info(code, options = {})
|
|
192
167
|
# convenience method to get a parsed token from Facebook for a given code
|
|
193
168
|
# should this require an OAuth callback URL?
|
|
194
|
-
get_token_from_server(:code => code, :redirect_uri => @oauth_callback_url)
|
|
169
|
+
get_token_from_server({:code => code, :redirect_uri => @oauth_callback_url}, false, options)
|
|
195
170
|
end
|
|
196
171
|
|
|
197
|
-
def get_access_token(code)
|
|
172
|
+
def get_access_token(code, options = {})
|
|
198
173
|
# upstream methods will throw errors if needed
|
|
199
|
-
if info = get_access_token_info(code)
|
|
174
|
+
if info = get_access_token_info(code, options)
|
|
200
175
|
string = info["access_token"]
|
|
201
176
|
end
|
|
202
177
|
end
|
|
203
178
|
|
|
204
|
-
def get_app_access_token_info
|
|
179
|
+
def get_app_access_token_info(options = {})
|
|
205
180
|
# convenience method to get a the application's sessionless access token
|
|
206
|
-
get_token_from_server({:type => 'client_cred'}, true)
|
|
181
|
+
get_token_from_server({:type => 'client_cred'}, true, options)
|
|
207
182
|
end
|
|
208
183
|
|
|
209
|
-
def get_app_access_token
|
|
210
|
-
if info = get_app_access_token_info
|
|
184
|
+
def get_app_access_token(options = {})
|
|
185
|
+
if info = get_app_access_token_info(options)
|
|
211
186
|
string = info["access_token"]
|
|
212
187
|
end
|
|
213
188
|
end
|
|
@@ -225,19 +200,19 @@ module Koala
|
|
|
225
200
|
raise "SignedRequest: Unsupported algorithm #{envelope['algorithm']}" if envelope['algorithm'] != 'HMAC-SHA256'
|
|
226
201
|
|
|
227
202
|
# now see if the signature is valid (digest, key, data)
|
|
228
|
-
hmac = OpenSSL::HMAC.hexdigest(
|
|
203
|
+
hmac = OpenSSL::HMAC.hexdigest(OpenSSL::Digest::SHA256.new, @app_secret, encoded_envelope.tr("-_", "+/"))
|
|
229
204
|
raise 'SignedRequest: Invalid signature' if (signature != hmac)
|
|
230
205
|
|
|
231
206
|
return envelope
|
|
232
207
|
end
|
|
233
208
|
|
|
234
209
|
# from session keys
|
|
235
|
-
def get_token_info_from_session_keys(sessions)
|
|
210
|
+
def get_token_info_from_session_keys(sessions, options = {})
|
|
236
211
|
# fetch the OAuth tokens from Facebook
|
|
237
212
|
response = fetch_token_string({
|
|
238
213
|
:type => 'client_cred',
|
|
239
214
|
:sessions => sessions.join(",")
|
|
240
|
-
}, true, "exchange_sessions")
|
|
215
|
+
}, true, "exchange_sessions", options)
|
|
241
216
|
|
|
242
217
|
# Facebook returns an empty body in certain error conditions
|
|
243
218
|
if response == ""
|
|
@@ -250,24 +225,24 @@ module Koala
|
|
|
250
225
|
JSON.parse(response)
|
|
251
226
|
end
|
|
252
227
|
|
|
253
|
-
def get_tokens_from_session_keys(sessions)
|
|
228
|
+
def get_tokens_from_session_keys(sessions, options = {})
|
|
254
229
|
# get the original hash results
|
|
255
|
-
results = get_token_info_from_session_keys(sessions)
|
|
230
|
+
results = get_token_info_from_session_keys(sessions, options)
|
|
256
231
|
# now recollect them as just the access tokens
|
|
257
232
|
results.collect { |r| r ? r["access_token"] : nil }
|
|
258
233
|
end
|
|
259
234
|
|
|
260
|
-
def get_token_from_session_key(session)
|
|
235
|
+
def get_token_from_session_key(session, options = {})
|
|
261
236
|
# convenience method for a single key
|
|
262
237
|
# gets the overlaoded strings automatically
|
|
263
|
-
get_tokens_from_session_keys([session])[0]
|
|
238
|
+
get_tokens_from_session_keys([session], options)[0]
|
|
264
239
|
end
|
|
265
240
|
|
|
266
241
|
protected
|
|
267
242
|
|
|
268
|
-
def get_token_from_server(args, post = false)
|
|
243
|
+
def get_token_from_server(args, post = false, options = {})
|
|
269
244
|
# fetch the result from Facebook's servers
|
|
270
|
-
result = fetch_token_string(args, post)
|
|
245
|
+
result = fetch_token_string(args, post, "access_token", options)
|
|
271
246
|
|
|
272
247
|
# if we have an error, parse the error JSON and raise an error
|
|
273
248
|
raise APIError.new((JSON.parse(result)["error"] rescue nil) || {}) if result =~ /error/
|
|
@@ -284,11 +259,11 @@ module Koala
|
|
|
284
259
|
components
|
|
285
260
|
end
|
|
286
261
|
|
|
287
|
-
def fetch_token_string(args, post = false, endpoint = "access_token")
|
|
262
|
+
def fetch_token_string(args, post = false, endpoint = "access_token", options = {})
|
|
288
263
|
Koala.make_request("/oauth/#{endpoint}", {
|
|
289
264
|
:client_id => @app_id,
|
|
290
265
|
:client_secret => @app_secret
|
|
291
|
-
}.merge!(args), post ? "post" : "get", :use_ssl => true).body
|
|
266
|
+
}.merge!(args), post ? "post" : "get", {:use_ssl => true}.merge!(options)).body
|
|
292
267
|
end
|
|
293
268
|
|
|
294
269
|
# base 64
|
|
@@ -299,7 +274,7 @@ module Koala
|
|
|
299
274
|
end
|
|
300
275
|
end
|
|
301
276
|
end
|
|
302
|
-
|
|
277
|
+
|
|
303
278
|
class KoalaError< StandardError; end
|
|
304
279
|
|
|
305
280
|
# finally, set up the http service Koala methods used to make requests
|
data/readme.md
CHANGED
|
@@ -7,12 +7,16 @@ Koala (<a href="http://github.com/arsduo/koala" target="_blank">http://github.co
|
|
|
7
7
|
* Flexible: Koala should be useful to everyone, regardless of their current configuration. (We have no dependencies beyond the JSON gem. Koala also has a built-in mechanism for using whichever HTTP library you prefer to make requests against the graph.)
|
|
8
8
|
* Tested: Koala should have complete test coverage, so you can rely on it. (Our complete test coverage can be run against either mocked responses or the live Facebook servers.)
|
|
9
9
|
|
|
10
|
-
1.0
|
|
10
|
+
1.0
|
|
11
11
|
---
|
|
12
|
-
Version 1.0 is
|
|
12
|
+
Version 1.0 is due out on May 1st, 2011 with a ton of great features.
|
|
13
13
|
|
|
14
|
-
sudo gem install koala
|
|
14
|
+
sudo gem install koala
|
|
15
15
|
|
|
16
|
+
Until then, you can install the release candidate like so:
|
|
17
|
+
|
|
18
|
+
sudo gem install koala --pre
|
|
19
|
+
|
|
16
20
|
Graph API
|
|
17
21
|
----
|
|
18
22
|
The Graph API is the simple, slick new interface to Facebook's data. Using it with Koala is quite straightforward:
|
|
@@ -126,11 +130,14 @@ Testing
|
|
|
126
130
|
-----
|
|
127
131
|
|
|
128
132
|
Unit tests are provided for all of Koala's methods. By default, these tests run against mock responses and hence are ready out of the box:
|
|
129
|
-
|
|
130
|
-
|
|
133
|
+
|
|
134
|
+
# From anywhere in the project directory:
|
|
135
|
+
rake spec
|
|
136
|
+
|
|
131
137
|
|
|
132
138
|
You can also run live tests against Facebook's servers:
|
|
133
|
-
|
|
134
|
-
|
|
139
|
+
|
|
140
|
+
# Again from anywhere in the project directory:
|
|
141
|
+
LIVE=true rake spec
|
|
135
142
|
|
|
136
|
-
Important Note: to run the live tests, you have to provide some of your own data: a valid OAuth access token with publish\_stream, read\_stream, and user\_photos permissions and an OAuth code that can be used to generate an access token. You can get
|
|
143
|
+
Important Note: to run the live tests, you have to provide some of your own data in spec/fixtures/facebook_data.yml: a valid OAuth access token with publish\_stream, read\_stream, and user\_photos permissions and an OAuth code that can be used to generate an access token. You can get thisdata at the OAuth Playground; if you want to use your own app, remember to swap out the app ID, secret, and other values. (The file also provides valid values for other tests, which you're welcome to swap out for data specific to your own application.)
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
|
|
3
|
+
describe "Koala::Facebook::API" do
|
|
4
|
+
before(:each) do
|
|
5
|
+
@service = Koala::Facebook::API.new
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
it "should not include an access token if none was given" do
|
|
9
|
+
Koala.should_receive(:make_request).with(
|
|
10
|
+
anything,
|
|
11
|
+
hash_not_including('access_token' => 1),
|
|
12
|
+
anything,
|
|
13
|
+
anything
|
|
14
|
+
).and_return(Koala::Response.new(200, "", ""))
|
|
15
|
+
|
|
16
|
+
@service.api('anything')
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
it "should include an access token if given" do
|
|
20
|
+
token = 'adfadf'
|
|
21
|
+
service = Koala::Facebook::API.new token
|
|
22
|
+
|
|
23
|
+
Koala.should_receive(:make_request).with(
|
|
24
|
+
anything,
|
|
25
|
+
hash_including('access_token' => token),
|
|
26
|
+
anything,
|
|
27
|
+
anything
|
|
28
|
+
).and_return(Koala::Response.new(200, "", ""))
|
|
29
|
+
|
|
30
|
+
service.api('anything')
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
it "should have an attr_reader for access token" do
|
|
34
|
+
token = 'adfadf'
|
|
35
|
+
service = Koala::Facebook::API.new token
|
|
36
|
+
service.access_token.should == token
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
it "should get the attribute of a Koala::Response given by the http_component parameter" do
|
|
40
|
+
http_component = :method_name
|
|
41
|
+
|
|
42
|
+
response = mock('Mock KoalaResponse', :body => '', :status => 200)
|
|
43
|
+
response.should_receive(http_component).and_return('')
|
|
44
|
+
|
|
45
|
+
Koala.stub(:make_request).and_return(response)
|
|
46
|
+
|
|
47
|
+
@service.api('anything', 'get', {}, :http_component => http_component)
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
it "should return the body of the request as JSON if no http_component is given" do
|
|
51
|
+
response = stub('response', :body => 'body', :status => 200)
|
|
52
|
+
Koala.stub(:make_request).and_return(response)
|
|
53
|
+
|
|
54
|
+
json_body = mock('JSON body')
|
|
55
|
+
JSON.stub(:parse).and_return([json_body])
|
|
56
|
+
|
|
57
|
+
@service.api('anything').should == json_body
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
it "should execute a block with the response body if passed one" do
|
|
61
|
+
body = '{}'
|
|
62
|
+
Koala.stub(:make_request).and_return(Koala::Response.new(200, body, {}))
|
|
63
|
+
|
|
64
|
+
yield_test = mock('Yield Tester')
|
|
65
|
+
yield_test.should_receive(:pass)
|
|
66
|
+
|
|
67
|
+
@service.api('anything') do |arg|
|
|
68
|
+
yield_test.pass
|
|
69
|
+
arg.should == JSON.parse(body)
|
|
70
|
+
end
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
it "should raise an API error if the HTTP response code is greater than or equal to 500" do
|
|
74
|
+
Koala.stub(:make_request).and_return(Koala::Response.new(500, 'response body', {}))
|
|
75
|
+
|
|
76
|
+
lambda { @service.api('anything') }.should raise_exception(Koala::Facebook::APIError)
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
it "should handle rogue true/false as responses" do
|
|
80
|
+
Koala.should_receive(:make_request).and_return(Koala::Response.new(200, 'true', {}))
|
|
81
|
+
@service.api('anything').should be_true
|
|
82
|
+
|
|
83
|
+
Koala.should_receive(:make_request).and_return(Koala::Response.new(200, 'false', {}))
|
|
84
|
+
@service.api('anything').should be_false
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
describe "with regard to leading slashes" do
|
|
88
|
+
it "should add a leading / to the path if not present" do
|
|
89
|
+
path = "anything"
|
|
90
|
+
Koala.should_receive(:make_request).with("/#{path}", anything, anything, anything).and_return(Koala::Response.new(200, 'true', {}))
|
|
91
|
+
@service.api(path)
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
it "shouldn't change the path if a leading / is present" do
|
|
95
|
+
path = "/anything"
|
|
96
|
+
Koala.should_receive(:make_request).with(path, anything, anything, anything).and_return(Koala::Response.new(200, 'true', {}))
|
|
97
|
+
@service.api(path)
|
|
98
|
+
end
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
end
|