koala 2.5.0 → 3.0.0.beta1
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.
- checksums.yaml +4 -4
- data/.travis.yml +4 -2
- data/Gemfile +1 -1
- data/changelog.md +26 -0
- data/lib/koala/api/batch_operation.rb +3 -6
- data/lib/koala/api/graph_api.rb +6 -45
- data/lib/koala/api/graph_batch_api.rb +1 -2
- data/lib/koala/api/graph_collection.rb +1 -5
- data/lib/koala/api/graph_error_checker.rb +1 -1
- data/lib/koala/api.rb +3 -7
- data/lib/koala/errors.rb +1 -1
- data/lib/koala/http_service/multipart_request.rb +6 -10
- data/lib/koala/http_service/request.rb +139 -0
- data/lib/koala/http_service/response.rb +0 -4
- data/lib/koala/http_service/uploadable_io.rb +0 -4
- data/lib/koala/http_service.rb +16 -68
- data/lib/koala/oauth.rb +3 -3
- data/lib/koala/version.rb +1 -1
- data/lib/koala.rb +2 -1
- data/readme.md +5 -26
- data/spec/cases/api_spec.rb +1 -7
- data/spec/cases/graph_api_batch_spec.rb +12 -22
- data/spec/cases/graph_api_spec.rb +0 -19
- data/spec/cases/graph_collection_spec.rb +18 -18
- data/spec/cases/graph_error_checker_spec.rb +6 -1
- data/spec/cases/http_service/request_spec.rb +240 -0
- data/spec/cases/http_service_spec.rb +102 -296
- data/spec/cases/koala_spec.rb +6 -1
- data/spec/cases/oauth_spec.rb +1 -1
- data/spec/cases/test_users_spec.rb +4 -1
- data/spec/cases/uploadable_io_spec.rb +31 -31
- data/spec/fixtures/mock_facebook_responses.yml +0 -37
- data/spec/spec_helper.rb +2 -2
- data/spec/support/graph_api_shared_examples.rb +6 -142
- data/spec/support/koala_test.rb +6 -6
- data/spec/support/mock_http_service.rb +6 -6
- data/spec/support/uploadable_io_shared_examples.rb +4 -4
- metadata +7 -7
- data/lib/koala/api/rest_api.rb +0 -135
- data/spec/support/rest_api_shared_examples.rb +0 -168
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 04714e9f9ae4e70420567406530119f6560518d1
|
4
|
+
data.tar.gz: 92ec819da43149fc5de98f6ec931afc6736c8199
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 51df761c7444da9dfb2c78b1fc30216b6fb3e5463c8e3bda322cae0f01e5e6fde5eecd62fc63f81527d25277972ff8ec00db71ca56aae9322bcfa626484e2470
|
7
|
+
data.tar.gz: f0545dd4651b30877186dd1f9bf3abe921a73a73f778980434536d4ad7923e17085fa64df53f7f449986d4fe5c460e08e6ceba605ddcc4a70de90c1ed21881c7
|
data/.travis.yml
CHANGED
@@ -6,12 +6,14 @@ rvm:
|
|
6
6
|
- 2.0
|
7
7
|
- 2.1
|
8
8
|
- 2.2
|
9
|
-
- 2.3.
|
9
|
+
- 2.3.1
|
10
10
|
# Rubinius is failing due to segfaults on Travis (and takes significantly longer to run)
|
11
11
|
# those builds will be restored later
|
12
12
|
# jruby
|
13
|
-
- jruby-19mode
|
13
|
+
# - jruby-19mode
|
14
14
|
bundler_args: --without development
|
15
15
|
addons:
|
16
16
|
code_climate:
|
17
17
|
repo_token: 7af99d9225b4c14640f9ec3cb2e24d2f7103ac49417b0bd989188fb6c25f2909
|
18
|
+
after_success:
|
19
|
+
- bundle exec codeclimate-test-reporter
|
data/Gemfile
CHANGED
data/changelog.md
CHANGED
@@ -1,3 +1,29 @@
|
|
1
|
+
v3.0.0
|
2
|
+
======
|
3
|
+
|
4
|
+
Key breaking changes:
|
5
|
+
|
6
|
+
* HTTPService.make_request now requires an HTTPService::Request object (Koala.make_request does
|
7
|
+
not)
|
8
|
+
* HTTPService behavior *should not* change, but in edge cases might. (If so, please let me know.)
|
9
|
+
* Empty response bodies in batch API calls will raise a JSON parse error rather than returning nil
|
10
|
+
|
11
|
+
Removed features:
|
12
|
+
|
13
|
+
* Removed support for the Rest API, since Facebook removed support for it (#568)
|
14
|
+
* Removed support for FQL, which Facebook removed on August 8, 2016 (#569)
|
15
|
+
* Removed legacy duplication of serveral constants in the Koala module (#569)
|
16
|
+
|
17
|
+
Internal improvements:
|
18
|
+
|
19
|
+
* Completely rewrote HTTPService.make_request and several others, extracting most logic into
|
20
|
+
HTTPService::Request (#566)
|
21
|
+
* Use the more secure JSON.parse instead of JSON.load (thanks, lautis!) (#567)
|
22
|
+
|
23
|
+
Testing improvements:
|
24
|
+
|
25
|
+
* Fixed a bunch of failing specs
|
26
|
+
|
1
27
|
v2.5.0
|
2
28
|
======
|
3
29
|
|
@@ -1,4 +1,5 @@
|
|
1
1
|
require 'koala/api'
|
2
|
+
require 'koala/api/graph_batch_api'
|
2
3
|
|
3
4
|
module Koala
|
4
5
|
module Facebook
|
@@ -65,13 +66,13 @@ module Koala
|
|
65
66
|
def process_binary_args
|
66
67
|
# collect binary files
|
67
68
|
@args.each_pair do |key, value|
|
68
|
-
if UploadableIO.binary_content?(value)
|
69
|
+
if HTTPService::UploadableIO.binary_content?(value)
|
69
70
|
@files ||= {}
|
70
71
|
# we use a class-level counter to ensure unique file identifiers across multiple batch operations
|
71
72
|
# (this is thread safe, since we just care about uniqueness)
|
72
73
|
# so remove the file from the original hash and add it to the file store
|
73
74
|
id = "op#{identifier}_file#{@files.keys.length}"
|
74
|
-
@files[id] = @args.delete(key).is_a?(UploadableIO) ? value : UploadableIO.new(value)
|
75
|
+
@files[id] = @args.delete(key).is_a?(HTTPService::UploadableIO) ? value : HTTPService::UploadableIO.new(value)
|
75
76
|
end
|
76
77
|
end
|
77
78
|
end
|
@@ -81,9 +82,5 @@ module Koala
|
|
81
82
|
end
|
82
83
|
end
|
83
84
|
end
|
84
|
-
|
85
|
-
# @private
|
86
|
-
# legacy support for when BatchOperation lived directly under Koala::Facebook
|
87
|
-
BatchOperation = GraphBatchAPI::BatchOperation
|
88
85
|
end
|
89
86
|
end
|
data/lib/koala/api/graph_api.rb
CHANGED
@@ -359,45 +359,6 @@ module Koala
|
|
359
359
|
# except to support cases where the Facebook API requires non-standard input
|
360
360
|
# such as JSON-encoding arguments, posts directly to objects, etc.
|
361
361
|
|
362
|
-
# Make an FQL query.
|
363
|
-
# Convenience method equivalent to get_object("fql", :q => query).
|
364
|
-
#
|
365
|
-
# @param query the FQL query to perform
|
366
|
-
# @param args (see #get_object)
|
367
|
-
# @param options (see #get_object)
|
368
|
-
# @param block (see Koala::Facebook::API#api)
|
369
|
-
#
|
370
|
-
# @return the result of the FQL query.
|
371
|
-
def fql_query(query, args = {}, options = {}, &block)
|
372
|
-
get_object("fql", args.merge(:q => query), options, &block)
|
373
|
-
end
|
374
|
-
|
375
|
-
# Make an FQL multiquery.
|
376
|
-
# This method simplifies the result returned from multiquery into a more logical format.
|
377
|
-
#
|
378
|
-
# @param queries a hash of query names => FQL queries
|
379
|
-
# @param args (see #get_object)
|
380
|
-
# @param options (see #get_object)
|
381
|
-
# @param block (see Koala::Facebook::API#api)
|
382
|
-
#
|
383
|
-
# @example
|
384
|
-
# @api.fql_multiquery({
|
385
|
-
# "query1" => "select post_id from stream where source_id = me()",
|
386
|
-
# "query2" => "select fromid from comment where post_id in (select post_id from #query1)"
|
387
|
-
# })
|
388
|
-
# # returns {"query1" => [obj1, obj2, ...], "query2" => [obj3, ...]}
|
389
|
-
# # instead of [{"name":"query1", "fql_result_set":[]},{"name":"query2", "fql_result_set":[]}]
|
390
|
-
#
|
391
|
-
# @return a hash of FQL results keyed to the appropriate query
|
392
|
-
def fql_multiquery(queries = {}, args = {}, options = {}, &block)
|
393
|
-
resolved_results = if results = get_object("fql", args.merge(:q => JSON.dump(queries)), options)
|
394
|
-
# simplify the multiquery result format
|
395
|
-
results.inject({}) {|outcome, data| outcome[data["name"]] = data["fql_result_set"]; outcome}
|
396
|
-
end
|
397
|
-
|
398
|
-
block ? block.call(resolved_results) : resolved_results
|
399
|
-
end
|
400
|
-
|
401
362
|
# Get a page's access token, allowing you to act as the page.
|
402
363
|
# Convenience method for @api.get_object(page_id, :fields => "access_token").
|
403
364
|
#
|
@@ -463,13 +424,13 @@ module Koala
|
|
463
424
|
# Those methods use get_page to request another set of results from Facebook.
|
464
425
|
#
|
465
426
|
# @note You'll rarely need to use this method unless you're using Sinatra or another non-Rails framework
|
466
|
-
# (see {Koala::Facebook::GraphCollection GraphCollection} for more information).
|
427
|
+
# (see {Koala::Facebook::API::GraphCollection GraphCollection} for more information).
|
467
428
|
#
|
468
429
|
# @param params an array of arguments to graph_call
|
469
|
-
# as returned by {Koala::Facebook::GraphCollection.parse_page_url}.
|
430
|
+
# as returned by {Koala::Facebook::API::GraphCollection.parse_page_url}.
|
470
431
|
# @param block (see Koala::Facebook::API#api)
|
471
432
|
#
|
472
|
-
# @return Koala::Facebook::GraphCollection the appropriate page of results (an empty array if there are none)
|
433
|
+
# @return Koala::Facebook::API::GraphCollection the appropriate page of results (an empty array if there are none)
|
473
434
|
def get_page(params, &block)
|
474
435
|
graph_call(*params, &block)
|
475
436
|
end
|
@@ -529,7 +490,7 @@ module Koala
|
|
529
490
|
# @yield response when making a batch API call, you can pass in a block
|
530
491
|
# that parses the results, allowing for cleaner code.
|
531
492
|
# The block's return value is returned in the batch results.
|
532
|
-
# See the code for {#get_picture}
|
493
|
+
# See the code for {#get_picture} for examples.
|
533
494
|
# (Not needed in regular calls; you'll probably rarely use this.)
|
534
495
|
#
|
535
496
|
# @raise [Koala::Facebook::APIError] if Facebook returns an error
|
@@ -544,7 +505,7 @@ module Koala
|
|
544
505
|
end
|
545
506
|
|
546
507
|
# turn this into a GraphCollection if it's pageable
|
547
|
-
result = GraphCollection.evaluate(result, self)
|
508
|
+
result = API::GraphCollection.evaluate(result, self)
|
548
509
|
|
549
510
|
# now process as appropriate for the given call (get picture header, etc.)
|
550
511
|
post_processing ? post_processing.call(result) : result
|
@@ -573,7 +534,7 @@ module Koala
|
|
573
534
|
fb_expected_arg_name = method == "photos" ? :url : :file_url
|
574
535
|
args.merge!(fb_expected_arg_name => media_args.first)
|
575
536
|
else
|
576
|
-
args["source"] = Koala::UploadableIO.new(*media_args.slice(0, 1 + args_offset))
|
537
|
+
args["source"] = Koala::HTTPService::UploadableIO.new(*media_args.slice(0, 1 + args_offset))
|
577
538
|
end
|
578
539
|
|
579
540
|
[target_id, method, args, options]
|
@@ -75,7 +75,7 @@ module Koala
|
|
75
75
|
raw_result = error
|
76
76
|
else
|
77
77
|
# (see note in regular api method about JSON parsing)
|
78
|
-
body = JSON.
|
78
|
+
body = JSON.parse("[#{call_result['body'].to_s}]")[0]
|
79
79
|
|
80
80
|
# Get the HTTP component they want
|
81
81
|
raw_result = case batch_op.http_options[:http_component]
|
@@ -101,7 +101,6 @@ module Koala
|
|
101
101
|
end
|
102
102
|
end
|
103
103
|
end
|
104
|
-
|
105
104
|
end
|
106
105
|
end
|
107
106
|
end
|
@@ -23,7 +23,7 @@ module Koala
|
|
23
23
|
# @param api the Graph {Koala::Facebook::API API} instance to use to make calls
|
24
24
|
# (usually the API that made the original call).
|
25
25
|
#
|
26
|
-
# @return [Koala::Facebook::GraphCollection] an initialized GraphCollection
|
26
|
+
# @return [Koala::Facebook::API::GraphCollection] an initialized GraphCollection
|
27
27
|
# whose paging, summary, raw_response, and api attributes are populated.
|
28
28
|
def initialize(response, api)
|
29
29
|
super response["data"]
|
@@ -113,9 +113,5 @@ module Koala
|
|
113
113
|
end
|
114
114
|
end
|
115
115
|
end
|
116
|
-
|
117
|
-
# @private
|
118
|
-
# legacy support for when GraphCollection lived directly under Koala::Facebook
|
119
|
-
GraphCollection = API::GraphCollection
|
120
116
|
end
|
121
117
|
end
|
data/lib/koala/api.rb
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
# graph_batch_api and legacy are required at the bottom, since they depend on API being defined
|
2
2
|
require 'koala/api/graph_api'
|
3
|
-
require 'koala/api/
|
3
|
+
require 'koala/api/graph_collection'
|
4
4
|
require 'openssl'
|
5
5
|
|
6
6
|
module Koala
|
@@ -23,13 +23,11 @@ module Koala
|
|
23
23
|
attr_reader :access_token, :app_secret
|
24
24
|
|
25
25
|
include GraphAPIMethods
|
26
|
-
include RestAPIMethods
|
27
26
|
|
28
27
|
# Makes a request to the appropriate Facebook API.
|
29
28
|
# @note You'll rarely need to call this method directly.
|
30
29
|
#
|
31
30
|
# @see GraphAPIMethods#graph_call
|
32
|
-
# @see RestAPIMethods#rest_call
|
33
31
|
#
|
34
32
|
# @param path the server path for this request (leading / is prepended if not present)
|
35
33
|
# @param args arguments to be sent to Facebook
|
@@ -85,9 +83,9 @@ module Koala
|
|
85
83
|
else
|
86
84
|
# parse the body as JSON and run it through the error checker (if provided)
|
87
85
|
# Note: Facebook sometimes sends results like "true" and "false", which are valid[RFC7159]
|
88
|
-
# but unsupported by Ruby's stdlib[RFC4627] and cause JSON.
|
86
|
+
# but unsupported by Ruby's stdlib[RFC4627] and cause JSON.parse to fail -- so we account for
|
89
87
|
# that by wrapping the result in []
|
90
|
-
JSON.
|
88
|
+
JSON.parse("[#{result.body.to_s}]")[0]
|
91
89
|
end
|
92
90
|
end
|
93
91
|
|
@@ -117,5 +115,3 @@ module Koala
|
|
117
115
|
end
|
118
116
|
end
|
119
117
|
end
|
120
|
-
|
121
|
-
require 'koala/api/graph_batch_api'
|
data/lib/koala/errors.rb
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
require 'faraday'
|
2
2
|
|
3
|
-
module Koala
|
3
|
+
module Koala
|
4
4
|
module HTTPService
|
5
5
|
class MultipartRequest < Faraday::Request::Multipart
|
6
6
|
# Facebook expects nested parameters to be passed in a certain way
|
@@ -8,15 +8,15 @@ module Koala
|
|
8
8
|
# Faraday needs two changes to make that work:
|
9
9
|
# 1) [] need to be escaped (e.g. params[foo]=bar ==> params%5Bfoo%5D=bar)
|
10
10
|
# 2) such messages need to be multipart-encoded
|
11
|
-
|
11
|
+
|
12
12
|
self.mime_type = 'multipart/form-data'.freeze
|
13
|
-
|
13
|
+
|
14
14
|
def process_request?(env)
|
15
15
|
# if the request values contain any hashes or arrays, multipart it
|
16
16
|
super || !!(env[:body].respond_to?(:values) && env[:body].values.find {|v| v.is_a?(Hash) || v.is_a?(Array)})
|
17
|
-
end
|
18
|
-
|
19
|
-
|
17
|
+
end
|
18
|
+
|
19
|
+
|
20
20
|
def process_params(params, prefix = nil, pieces = nil, &block)
|
21
21
|
params.inject(pieces || []) do |all, (key, value)|
|
22
22
|
key = "#{prefix}%5B#{key}%5D" if prefix
|
@@ -34,8 +34,4 @@ module Koala
|
|
34
34
|
end
|
35
35
|
end
|
36
36
|
end
|
37
|
-
|
38
|
-
# @private
|
39
|
-
# legacy support for when MultipartRequest lived directly under Koala
|
40
|
-
MultipartRequest = HTTPService::MultipartRequest
|
41
37
|
end
|
@@ -0,0 +1,139 @@
|
|
1
|
+
module Koala
|
2
|
+
module HTTPService
|
3
|
+
class Request
|
4
|
+
attr_reader :raw_path, :raw_args, :raw_verb, :raw_options
|
5
|
+
|
6
|
+
# @param path the server path for this request
|
7
|
+
# @param args (see Koala::Facebook::API#api)
|
8
|
+
# @param verb the HTTP method to use.
|
9
|
+
# If not get or post, this will be turned into a POST request with the appropriate :method
|
10
|
+
# specified in the arguments.
|
11
|
+
# @param options various flags to indicate which server to use. (see Koala::Facebook::API#api)
|
12
|
+
# @param options
|
13
|
+
# @option options :video use the server designated for video uploads
|
14
|
+
# @option options :beta use the beta tier
|
15
|
+
# @option options :use_ssl force https, even if not needed
|
16
|
+
# @option options :json whether or not to send JSON to Facebook
|
17
|
+
def initialize(path: nil, args: {}, verb: nil, options: {})
|
18
|
+
# we still support Ruby 2.0 so we can't use required keyword arguments
|
19
|
+
raise ArgumentError, "Missing required argument verb" unless verb
|
20
|
+
raise ArgumentError, "Missing required argument path" unless path
|
21
|
+
|
22
|
+
@raw_path = path
|
23
|
+
@raw_args = args
|
24
|
+
@raw_verb = verb
|
25
|
+
@raw_options = options
|
26
|
+
end
|
27
|
+
|
28
|
+
# Determines which type of request to send to Facebook. Facebook natively accepts GETs and POSTs, for others we have to include the method in the post body.
|
29
|
+
#
|
30
|
+
# @return one of get or post
|
31
|
+
def verb
|
32
|
+
["get", "post"].include?(raw_verb) ? raw_verb : "post"
|
33
|
+
end
|
34
|
+
|
35
|
+
# Determines the path to be requested on Facebook, incorporating an API version if specified.
|
36
|
+
#
|
37
|
+
# @return the original path, with API version if appropriate.
|
38
|
+
def path
|
39
|
+
# if an api_version is specified and the path does not already contain
|
40
|
+
# one, prepend it to the path
|
41
|
+
api_version = raw_options[:api_version] || Koala.config.api_version
|
42
|
+
if api_version && !path_contains_api_version?
|
43
|
+
begins_with_slash = raw_path[0] == "/"
|
44
|
+
divider = begins_with_slash ? "" : "/"
|
45
|
+
"/#{api_version}#{divider}#{raw_path}"
|
46
|
+
else
|
47
|
+
raw_path
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
# Determines any arguments to be sent in a POST body.
|
52
|
+
#
|
53
|
+
# @return {} for GET; the provided args for POST; those args with the method parameter for
|
54
|
+
# other values
|
55
|
+
def post_args
|
56
|
+
if raw_verb == "get"
|
57
|
+
{}
|
58
|
+
elsif raw_verb == "post"
|
59
|
+
args
|
60
|
+
else
|
61
|
+
args.merge(method: raw_verb)
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
def get_args
|
66
|
+
raw_verb == "get" ? args : {}
|
67
|
+
end
|
68
|
+
|
69
|
+
# Calculates a set of request options to pass to Faraday.
|
70
|
+
#
|
71
|
+
# @return a hash combining GET parameters (if appropriate), default options, and
|
72
|
+
# any specified for the request.
|
73
|
+
def options
|
74
|
+
# figure out our options for this request
|
75
|
+
add_ssl_options(
|
76
|
+
# for GETs, we pass the params to Faraday to encode
|
77
|
+
{params: get_args}.merge(HTTPService.http_options).merge(raw_options)
|
78
|
+
)
|
79
|
+
end
|
80
|
+
|
81
|
+
# Whether or not this request should use JSON.
|
82
|
+
#
|
83
|
+
# @return true or false
|
84
|
+
def json?
|
85
|
+
raw_options[:format] == :json
|
86
|
+
end
|
87
|
+
|
88
|
+
# The address of the appropriate Facebook server.
|
89
|
+
#
|
90
|
+
# @return a complete server address with protocol
|
91
|
+
def server
|
92
|
+
uri = "#{options[:use_ssl] ? "https" : "http"}://#{Koala.config.graph_server}"
|
93
|
+
# if we want to use the beta tier or the video server, make those substitutions as
|
94
|
+
# appropriate
|
95
|
+
replace_server_component(
|
96
|
+
replace_server_component(uri, options[:video], Koala.config.video_replace),
|
97
|
+
options[:beta],
|
98
|
+
Koala.config.beta_replace
|
99
|
+
)
|
100
|
+
end
|
101
|
+
|
102
|
+
protected
|
103
|
+
|
104
|
+
# The arguments to include in the request.
|
105
|
+
def args
|
106
|
+
raw_args.inject({}) do |hash, (key, value)|
|
107
|
+
# Resolve UploadableIOs into data Facebook can work with
|
108
|
+
hash.merge(key => value.is_a?(UploadableIO) ? value.to_upload_io : value)
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
112
|
+
def add_ssl_options(opts)
|
113
|
+
# require https if there's a token
|
114
|
+
return opts unless raw_args["access_token"]
|
115
|
+
|
116
|
+
{
|
117
|
+
use_ssl: true,
|
118
|
+
ssl: {verify: true}.merge(opts[:ssl] || {})
|
119
|
+
}.merge(opts)
|
120
|
+
end
|
121
|
+
|
122
|
+
# Determines whether a given path already contains an API version.
|
123
|
+
#
|
124
|
+
# @param path the URL path.
|
125
|
+
#
|
126
|
+
# @return true or false accordingly.
|
127
|
+
def path_contains_api_version?
|
128
|
+
# looks for "/$MAJOR[.$MINOR]/" in the path
|
129
|
+
match = /^\/?(v\d+(?:\.\d+)?)\//.match(raw_path)
|
130
|
+
!!(match && match[1])
|
131
|
+
end
|
132
|
+
|
133
|
+
def replace_server_component(host, condition_met, replacement)
|
134
|
+
return host unless condition_met
|
135
|
+
host.gsub(Koala.config.host_path_matcher, replacement)
|
136
|
+
end
|
137
|
+
end
|
138
|
+
end
|
139
|
+
end
|
data/lib/koala/http_service.rb
CHANGED
@@ -2,6 +2,7 @@ require 'faraday'
|
|
2
2
|
require 'koala/http_service/multipart_request'
|
3
3
|
require 'koala/http_service/uploadable_io'
|
4
4
|
require 'koala/http_service/response'
|
5
|
+
require 'koala/http_service/request'
|
5
6
|
|
6
7
|
module Koala
|
7
8
|
module HTTPService
|
@@ -28,7 +29,6 @@ module Koala
|
|
28
29
|
DEFAULT_SERVERS = {
|
29
30
|
:graph_server => 'graph.facebook.com',
|
30
31
|
:dialog_host => 'www.facebook.com',
|
31
|
-
:rest_server => 'api.facebook.com',
|
32
32
|
# certain Facebook services (beta, video) require you to access different
|
33
33
|
# servers. If you're using your own servers, for instance, for a proxy,
|
34
34
|
# you can change both the matcher and the replacement values.
|
@@ -40,81 +40,36 @@ module Koala
|
|
40
40
|
:beta_replace => '.beta.facebook'
|
41
41
|
}
|
42
42
|
|
43
|
-
# The address of the appropriate Facebook server.
|
44
|
-
#
|
45
|
-
# @param options various flags to indicate which server to use.
|
46
|
-
# @option options :rest_api use the old REST API instead of the Graph API
|
47
|
-
# @option options :video use the server designated for video uploads
|
48
|
-
# @option options :beta use the beta tier
|
49
|
-
# @option options :use_ssl force https, even if not needed
|
50
|
-
#
|
51
|
-
# @return a complete server address with protocol
|
52
|
-
def self.server(options = {})
|
53
|
-
server = "#{options[:rest_api] ? Koala.config.rest_server : Koala.config.graph_server}"
|
54
|
-
server.gsub!(Koala.config.host_path_matcher, Koala.config.video_replace) if options[:video]
|
55
|
-
server.gsub!(Koala.config.host_path_matcher, Koala.config.beta_replace) if options[:beta]
|
56
|
-
"#{options[:use_ssl] ? "https" : "http"}://#{server}"
|
57
|
-
end
|
58
|
-
|
59
43
|
# Makes a request directly to Facebook.
|
60
44
|
# @note You'll rarely need to call this method directly.
|
61
45
|
#
|
62
46
|
# @see Koala::Facebook::API#api
|
63
47
|
# @see Koala::Facebook::GraphAPIMethods#graph_call
|
64
|
-
# @see Koala::Facebook::RestAPIMethods#rest_call
|
65
48
|
#
|
66
|
-
# @param
|
67
|
-
# @param args (see Koala::Facebook::API#api)
|
68
|
-
# @param verb the HTTP method to use.
|
69
|
-
# If not get or post, this will be turned into a POST request with the appropriate :method
|
70
|
-
# specified in the arguments.
|
71
|
-
# @param options (see Koala::Facebook::API#api)
|
49
|
+
# @param request a Koala::HTTPService::Request object
|
72
50
|
#
|
73
51
|
# @raise an appropriate connection error if unable to make the request to Facebook
|
74
52
|
#
|
75
53
|
# @return [Koala::HTTPService::Response] a response object representing the results from Facebook
|
76
|
-
def self.make_request(
|
77
|
-
# if the verb isn't get or post, send it as a post argument with a method param
|
78
|
-
args.merge!({:method => verb}) && verb = "post" if verb != "get" && verb != "post"
|
79
|
-
|
80
|
-
# turn all the keys to strings (Faraday has issues with symbols under 1.8.7) and resolve UploadableIOs
|
81
|
-
params = args.inject({}) {|hash, kv| hash[kv.first.to_s] = kv.last.is_a?(UploadableIO) ? kv.last.to_upload_io : kv.last; hash}
|
82
|
-
|
83
|
-
# figure out our options for this request
|
84
|
-
request_options = {:params => (verb == "get" ? params : {})}.merge(http_options || {}).merge(options)
|
85
|
-
request_options[:use_ssl] = true if args["access_token"] # require https if there's a token
|
86
|
-
if request_options[:use_ssl]
|
87
|
-
ssl = (request_options[:ssl] ||= {})
|
88
|
-
ssl[:verify] = true unless ssl.has_key?(:verify)
|
89
|
-
end
|
90
|
-
|
91
|
-
# if an api_version is specified and the path does not already contain
|
92
|
-
# one, prepend it to the path
|
93
|
-
api_version = request_options[:api_version] || Koala.config.api_version
|
94
|
-
if api_version && !path_contains_api_version?(path)
|
95
|
-
begins_with_slash = path[0] == "/"
|
96
|
-
divider = begins_with_slash ? "" : "/"
|
97
|
-
path = "/#{api_version}#{divider}#{path}"
|
98
|
-
end
|
99
|
-
|
54
|
+
def self.make_request(request)
|
100
55
|
# set up our Faraday connection
|
101
|
-
|
102
|
-
conn = Faraday.new(server(request_options), faraday_options(request_options), &(faraday_middleware || DEFAULT_MIDDLEWARE))
|
56
|
+
conn = Faraday.new(request.server, faraday_options(request.options), &(faraday_middleware || DEFAULT_MIDDLEWARE))
|
103
57
|
|
104
|
-
|
105
|
-
|
58
|
+
if request.verb == "post" && request.json?
|
59
|
+
# JSON requires a bit more handling
|
60
|
+
# remember, all non-GET requests are turned into POSTs, so this covers everything but GETs
|
106
61
|
response = conn.post do |req|
|
107
|
-
req.path = path
|
62
|
+
req.path = request.path
|
108
63
|
req.headers["Content-Type"] = "application/json"
|
109
|
-
req.body =
|
64
|
+
req.body = request.post_args.to_json
|
110
65
|
req
|
111
66
|
end
|
112
67
|
else
|
113
|
-
response = conn.send(verb, path,
|
68
|
+
response = conn.send(request.verb, request.path, request.post_args)
|
114
69
|
end
|
115
70
|
|
116
71
|
# Log URL information
|
117
|
-
Koala::Utils.debug "#{verb.upcase}: #{path} params: #{
|
72
|
+
Koala::Utils.debug "#{request.verb.upcase}: #{request.path} params: #{request.raw_args.inspect}"
|
118
73
|
Koala::HTTPService::Response.new(response.status.to_i, response.body, response.headers)
|
119
74
|
end
|
120
75
|
|
@@ -130,21 +85,14 @@ module Koala
|
|
130
85
|
# @return the appropriately-encoded string
|
131
86
|
def self.encode_params(param_hash)
|
132
87
|
((param_hash || {}).sort_by{|k, v| k.to_s}.collect do |key_and_value|
|
133
|
-
|
134
|
-
|
88
|
+
value = key_and_value[1]
|
89
|
+
unless value.is_a? String
|
90
|
+
value = value.to_json
|
91
|
+
end
|
92
|
+
"#{key_and_value[0].to_s}=#{CGI.escape value}"
|
135
93
|
end).join("&")
|
136
94
|
end
|
137
95
|
|
138
|
-
# Determines whether a given path already contains an API version.
|
139
|
-
#
|
140
|
-
# @param path the URL path.
|
141
|
-
#
|
142
|
-
# @return true or false accordingly.
|
143
|
-
def self.path_contains_api_version?(path)
|
144
|
-
match = /^\/?(v\d+(?:\.\d+)?)\//.match(path)
|
145
|
-
!!(match && match[1])
|
146
|
-
end
|
147
|
-
|
148
96
|
private
|
149
97
|
|
150
98
|
def self.faraday_options(options)
|
data/lib/koala/oauth.rb
CHANGED
@@ -134,7 +134,7 @@ module Koala
|
|
134
134
|
if response == ''
|
135
135
|
raise BadFacebookResponse.new(200, '', 'generate_client_code received an error: empty response body')
|
136
136
|
else
|
137
|
-
result = JSON.
|
137
|
+
result = JSON.parse(response)
|
138
138
|
end
|
139
139
|
|
140
140
|
result.has_key?('code') ? result['code'] : raise(Koala::KoalaError.new("Facebook returned a valid response without the expected 'code' in the body (response = #{response})"))
|
@@ -240,7 +240,7 @@ module Koala
|
|
240
240
|
raise OAuthSignatureError, 'Invalid (incomplete) signature data' unless encoded_sig && encoded_envelope
|
241
241
|
|
242
242
|
signature = base64_url_decode(encoded_sig).unpack("H*").first
|
243
|
-
envelope = JSON.
|
243
|
+
envelope = JSON.parse(base64_url_decode(encoded_envelope))
|
244
244
|
|
245
245
|
raise OAuthSignatureError, "Unsupported algorithm #{envelope['algorithm']}" if envelope['algorithm'] != 'HMAC-SHA256'
|
246
246
|
|
@@ -260,7 +260,7 @@ module Koala
|
|
260
260
|
end
|
261
261
|
|
262
262
|
def parse_access_token(response_text)
|
263
|
-
JSON.
|
263
|
+
JSON.parse(response_text)
|
264
264
|
rescue JSON::ParserError
|
265
265
|
response_text.split("&").inject({}) do |hash, bit|
|
266
266
|
key, value = bit.split("=")
|
data/lib/koala/version.rb
CHANGED
data/lib/koala.rb
CHANGED
@@ -5,6 +5,7 @@ require 'json'
|
|
5
5
|
# include koala modules
|
6
6
|
require 'koala/errors'
|
7
7
|
require 'koala/api'
|
8
|
+
require 'koala/api/graph_batch_api'
|
8
9
|
require 'koala/oauth'
|
9
10
|
require 'koala/realtime_updates'
|
10
11
|
require 'koala/test_users'
|
@@ -61,7 +62,7 @@ module Koala
|
|
61
62
|
|
62
63
|
# An convenenient alias to Koala.http_service.make_request.
|
63
64
|
def self.make_request(path, args, verb, options = {})
|
64
|
-
http_service.make_request(path, args, verb, options)
|
65
|
+
http_service.make_request(HTTPService::Request.new(path: path, args: args, verb: verb, options: options))
|
65
66
|
end
|
66
67
|
|
67
68
|
# we use Faraday as our main service, with mock as the other main one
|