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.
Files changed (40) hide show
  1. checksums.yaml +4 -4
  2. data/.travis.yml +4 -2
  3. data/Gemfile +1 -1
  4. data/changelog.md +26 -0
  5. data/lib/koala/api/batch_operation.rb +3 -6
  6. data/lib/koala/api/graph_api.rb +6 -45
  7. data/lib/koala/api/graph_batch_api.rb +1 -2
  8. data/lib/koala/api/graph_collection.rb +1 -5
  9. data/lib/koala/api/graph_error_checker.rb +1 -1
  10. data/lib/koala/api.rb +3 -7
  11. data/lib/koala/errors.rb +1 -1
  12. data/lib/koala/http_service/multipart_request.rb +6 -10
  13. data/lib/koala/http_service/request.rb +139 -0
  14. data/lib/koala/http_service/response.rb +0 -4
  15. data/lib/koala/http_service/uploadable_io.rb +0 -4
  16. data/lib/koala/http_service.rb +16 -68
  17. data/lib/koala/oauth.rb +3 -3
  18. data/lib/koala/version.rb +1 -1
  19. data/lib/koala.rb +2 -1
  20. data/readme.md +5 -26
  21. data/spec/cases/api_spec.rb +1 -7
  22. data/spec/cases/graph_api_batch_spec.rb +12 -22
  23. data/spec/cases/graph_api_spec.rb +0 -19
  24. data/spec/cases/graph_collection_spec.rb +18 -18
  25. data/spec/cases/graph_error_checker_spec.rb +6 -1
  26. data/spec/cases/http_service/request_spec.rb +240 -0
  27. data/spec/cases/http_service_spec.rb +102 -296
  28. data/spec/cases/koala_spec.rb +6 -1
  29. data/spec/cases/oauth_spec.rb +1 -1
  30. data/spec/cases/test_users_spec.rb +4 -1
  31. data/spec/cases/uploadable_io_spec.rb +31 -31
  32. data/spec/fixtures/mock_facebook_responses.yml +0 -37
  33. data/spec/spec_helper.rb +2 -2
  34. data/spec/support/graph_api_shared_examples.rb +6 -142
  35. data/spec/support/koala_test.rb +6 -6
  36. data/spec/support/mock_http_service.rb +6 -6
  37. data/spec/support/uploadable_io_shared_examples.rb +4 -4
  38. metadata +7 -7
  39. data/lib/koala/api/rest_api.rb +0 -135
  40. 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: cb4d756e15fa642ec1e30f91d951f33d49c436f8
4
- data.tar.gz: a3ba0cc83d91175c351ffccb09eef6078d299a28
3
+ metadata.gz: 04714e9f9ae4e70420567406530119f6560518d1
4
+ data.tar.gz: 92ec819da43149fc5de98f6ec931afc6736c8199
5
5
  SHA512:
6
- metadata.gz: c67c06d0e2978428f01a8e4f6d245715a6486fc2b572a152f49fcaf58c53fafc570885bd9df88450cded73e6b90b2ce72f6802b947ebdbf02aad8b5f2e3ca97f
7
- data.tar.gz: b65059fbac83cd3d891baf4ce84a92cd53926644877be4ac76d80cebd5fc8ae630cd2997721bfb998b5067eb05a2576e12156ab62cee32c0f2fe0318f5e0f5c4
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.0
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
@@ -15,7 +15,7 @@ group :test do
15
15
  gem "rspec", '~> 3.4'
16
16
  gem "vcr"
17
17
  gem "webmock"
18
- gem "codeclimate-test-reporter", require: nil
18
+ gem "codeclimate-test-reporter", "~> 1.0.0", require: nil
19
19
  end
20
20
 
21
21
  gem "jruby-openssl" if defined? JRUBY_VERSION
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
@@ -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} or {#fql_multiquery} for examples.
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.load("[#{call_result['body'].to_s}]")[0]
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
@@ -61,7 +61,7 @@ module Koala
61
61
  # Normally, we start with the response body. If it isn't valid JSON, we start with an empty
62
62
  # hash and fill it with error data.
63
63
  @response_hash ||= begin
64
- JSON.load(body)
64
+ JSON.parse(body)
65
65
  rescue JSON::ParserError
66
66
  {}
67
67
  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/rest_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.load to fail -- so we account for
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.load("[#{result.body.to_s}]")[0]
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
@@ -50,7 +50,7 @@ module Koala
50
50
  else
51
51
  unless error_info
52
52
  begin
53
- error_info = JSON.load(response_body)['error'] if response_body
53
+ error_info = JSON.parse(response_body)['error'] if response_body
54
54
  rescue
55
55
  end
56
56
  error_info ||= {}
@@ -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
@@ -11,8 +11,4 @@ module Koala
11
11
  end
12
12
  end
13
13
  end
14
-
15
- # @private
16
- # legacy support for when Response lived directly under Koala
17
- Response = HTTPService::Response
18
14
  end
@@ -181,8 +181,4 @@ module Koala
181
181
  end
182
182
  end
183
183
  end
184
-
185
- # @private
186
- # legacy support for when UploadableIO lived directly under Koala
187
- UploadableIO = HTTPService::UploadableIO
188
184
  end
@@ -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 path the server path for this request
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(path, args, verb, options = {})
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
- # we have to manually assign params to the URL or the
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
- # remember, all non-GET requests are turned into POSTs -- see the the start of this method
105
- if verb == "post" && options[:format] == :json
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 = params.to_json
64
+ req.body = request.post_args.to_json
110
65
  req
111
66
  end
112
67
  else
113
- response = conn.send(verb, path, (verb == "post" ? params : {}))
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: #{params.inspect}"
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
- key_and_value[1] = JSON.dump(key_and_value[1]) unless key_and_value[1].is_a? String
134
- "#{key_and_value[0].to_s}=#{CGI.escape key_and_value[1]}"
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.load(response)
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.load(base64_url_decode(encoded_envelope))
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.load(response_text)
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
@@ -1,3 +1,3 @@
1
1
  module Koala
2
- VERSION = "2.5.0"
2
+ VERSION = "3.0.0.beta1"
3
3
  end
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