koala 2.5.0 → 3.0.0.beta1

Sign up to get free protection for your applications and to get access to all the features.
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