koala 1.1.0 → 1.2.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.
Files changed (52) hide show
  1. data/.travis.yml +2 -1
  2. data/CHANGELOG +36 -0
  3. data/Gemfile +6 -2
  4. data/Rakefile +0 -1
  5. data/koala.gemspec +7 -8
  6. data/lib/koala/batch_operation.rb +15 -15
  7. data/lib/koala/graph_api.rb +85 -73
  8. data/lib/koala/graph_batch_api.rb +21 -11
  9. data/lib/koala/graph_collection.rb +13 -8
  10. data/lib/koala/http_service.rb +176 -0
  11. data/lib/koala/oauth.rb +34 -24
  12. data/lib/koala/realtime_updates.rb +21 -18
  13. data/lib/koala/rest_api.rb +1 -1
  14. data/lib/koala/test_users.rb +33 -17
  15. data/lib/koala/uploadable_io.rb +49 -43
  16. data/lib/koala/utils.rb +11 -0
  17. data/lib/koala/version.rb +3 -0
  18. data/lib/koala.rb +47 -45
  19. data/readme.md +58 -38
  20. data/spec/cases/{api_base_spec.rb → api_spec.rb} +27 -2
  21. data/spec/cases/error_spec.rb +32 -0
  22. data/spec/cases/graph_and_rest_api_spec.rb +12 -21
  23. data/spec/cases/graph_api_batch_spec.rb +92 -119
  24. data/spec/cases/graph_api_spec.rb +11 -14
  25. data/spec/cases/graph_collection_spec.rb +116 -0
  26. data/spec/cases/http_service_spec.rb +446 -0
  27. data/spec/cases/koala_spec.rb +36 -37
  28. data/spec/cases/oauth_spec.rb +318 -212
  29. data/spec/cases/realtime_updates_spec.rb +45 -31
  30. data/spec/cases/rest_api_spec.rb +23 -7
  31. data/spec/cases/test_users_spec.rb +123 -75
  32. data/spec/cases/uploadable_io_spec.rb +77 -36
  33. data/spec/cases/utils_spec.rb +10 -0
  34. data/spec/fixtures/facebook_data.yml +26 -24
  35. data/spec/fixtures/mock_facebook_responses.yml +131 -101
  36. data/spec/spec_helper.rb +29 -5
  37. data/spec/support/graph_api_shared_examples.rb +80 -120
  38. data/spec/support/json_testing_fix.rb +35 -11
  39. data/spec/support/koala_test.rb +187 -0
  40. data/spec/support/mock_http_service.rb +8 -5
  41. data/spec/support/ordered_hash.rb +205 -0
  42. data/spec/support/rest_api_shared_examples.rb +37 -37
  43. data/spec/support/uploadable_io_shared_examples.rb +2 -8
  44. metadata +72 -83
  45. data/lib/koala/http_services/net_http_service.rb +0 -92
  46. data/lib/koala/http_services/typhoeus_service.rb +0 -37
  47. data/lib/koala/http_services.rb +0 -46
  48. data/spec/cases/http_services/http_service_spec.rb +0 -129
  49. data/spec/cases/http_services/net_http_service_spec.rb +0 -532
  50. data/spec/cases/http_services/typhoeus_service_spec.rb +0 -152
  51. data/spec/support/live_testing_data_helper.rb +0 -40
  52. data/spec/support/setup_mocks_or_live.rb +0 -51
@@ -1,92 +0,0 @@
1
- require "net/http" unless defined?(Net::HTTP)
2
- require "net/https"
3
- require "net/http/post/multipart"
4
-
5
- module Koala
6
- module NetHTTPService
7
- # this service uses Net::HTTP to send requests to the graph
8
- include Koala::HTTPService
9
-
10
- # Net::HTTP-specific values
11
- class << self
12
- attr_accessor :ca_file, :ca_path, :verify_mode
13
- end
14
-
15
- def self.make_request(path, args, verb, options = {})
16
- # We translate args to a valid query string. If post is specified,
17
- # we send a POST request to the given path with the given arguments.
18
-
19
- # by default, we use SSL only for private requests
20
- # this makes public requests faster
21
- private_request = args["access_token"] || @always_use_ssl || options[:use_ssl]
22
-
23
- # if the verb isn't get or post, send it as a post argument
24
- args.merge!({:method => verb}) && verb = "post" if verb != "get" && verb != "post"
25
-
26
- http = create_http(server(options), private_request, options)
27
-
28
- response = http.start do |http|
29
- if verb == "post"
30
- if params_require_multipart? args
31
- http.request Net::HTTP::Post::Multipart.new path, encode_multipart_params(args)
32
- else
33
- http.post(path, encode_params(args))
34
- end
35
- else
36
- http.get("#{path}?#{encode_params(args)}")
37
- end
38
- end
39
-
40
- Koala::Response.new(response.code.to_i, response.body, response)
41
- end
42
-
43
- protected
44
- def self.encode_params(param_hash)
45
- # unfortunately, we can't use to_query because that's Rails, not Ruby
46
- # if no hash (e.g. no auth token) return empty string
47
- ((param_hash || {}).collect do |key_and_value|
48
- key_and_value[1] = MultiJson.encode(key_and_value[1]) if key_and_value[1].class != String
49
- "#{key_and_value[0].to_s}=#{CGI.escape key_and_value[1]}"
50
- end).join("&")
51
- end
52
-
53
- def self.encode_multipart_params(param_hash)
54
- Hash[*param_hash.collect do |key, value|
55
- [key, value.kind_of?(Koala::UploadableIO) ? value.to_upload_io : value]
56
- end.flatten]
57
- end
58
-
59
- def self.create_http(server, private_request, options)
60
- if proxy_server = options[:proxy] || proxy
61
- proxy = URI.parse(proxy_server)
62
- http = Net::HTTP.new(server, private_request ? 443 : nil,
63
- proxy.host, proxy.port, proxy.user, proxy.password)
64
- else
65
- http = Net::HTTP.new(server, private_request ? 443 : nil)
66
- end
67
-
68
- if timeout_value = options[:timeout] || timeout
69
- http.open_timeout = timeout_value
70
- http.read_timeout = timeout_value
71
- end
72
-
73
- # For HTTPS requests, set the proper CA certificates
74
- if private_request
75
- http.use_ssl = true
76
- http.verify_mode = options[:verify_mode] || verify_mode || OpenSSL::SSL::VERIFY_PEER
77
-
78
- if cert_file = options[:ca_file] || ca_file
79
- raise Errno::ENOENT, "Certificate file #{cert_file.inspect} does not exist!" unless File.exists?(cert_file)
80
- http.ca_file = cert_file
81
- end
82
-
83
- if cert_path = options[:ca_path] || ca_path
84
- raise Errno::ENOENT, "Certificate path #{cert_path.inspect} does not exist!" unless File.directory?(cert_path)
85
- http.ca_path = cert_path
86
- end
87
- end
88
-
89
- http
90
- end
91
- end
92
- end
@@ -1,37 +0,0 @@
1
- require "typhoeus" unless defined?(Typhoeus)
2
-
3
- module Koala
4
- module TyphoeusService
5
- # this service uses Typhoeus to send requests to the graph
6
- include Typhoeus
7
- include Koala::HTTPService
8
-
9
- def self.make_request(path, args, verb, options = {})
10
- # if the verb isn't get or post, send it as a post argument
11
- args.merge!({:method => verb}) && verb = "post" if verb != "get" && verb != "post"
12
-
13
- # switch any UploadableIOs to the files Typhoeus expects
14
- args.each_pair {|key, value| args[key] = value.to_file if value.is_a?(UploadableIO)}
15
-
16
- # you can pass arguments directly to Typhoeus using the :typhoeus_options key
17
- typhoeus_options = {:params => args}.merge(options[:typhoeus_options] || {})
18
-
19
- # if proxy/timeout options aren't passed, check if defaults are set
20
- typhoeus_options[:proxy] ||= proxy
21
- typhoeus_options[:timeout] ||= timeout
22
-
23
- # by default, we use SSL only for private requests (e.g. with access token)
24
- # this makes public requests faster
25
- prefix = (args["access_token"] || @always_use_ssl || options[:use_ssl]) ? "https" : "http"
26
-
27
- response = Typhoeus::Request.send(verb, "#{prefix}://#{server(options)}#{path}", typhoeus_options)
28
- Koala::Response.new(response.code, response.body, response.headers_hash)
29
- end
30
-
31
- protected
32
-
33
- def self.multipart_requires_content_type?
34
- false # Typhoeus handles multipart file types, we don't have to require it
35
- end
36
- end
37
- end
@@ -1,46 +0,0 @@
1
- module Koala
2
- class Response
3
- attr_reader :status, :body, :headers
4
- def initialize(status, body, headers)
5
- @status = status
6
- @body = body
7
- @headers = headers
8
- end
9
- end
10
-
11
- module HTTPService
12
- # common functionality for all HTTP services
13
- def self.included(base)
14
- base.class_eval do
15
- class << self
16
- attr_accessor :always_use_ssl, :proxy, :timeout
17
- end
18
-
19
- def self.server(options = {})
20
- server = "#{options[:rest_api] ? Facebook::REST_SERVER : Facebook::GRAPH_SERVER}"
21
- server.gsub!(/\.facebook/, "-video.facebook") if options[:video]
22
- "#{options[:beta] ? "beta." : ""}#{server}"
23
- end
24
-
25
- def self.encode_params(param_hash)
26
- # unfortunately, we can't use to_query because that's Rails, not Ruby
27
- # if no hash (e.g. no auth token) return empty string
28
- ((param_hash || {}).collect do |key_and_value|
29
- key_and_value[1] = MultiJson.encode(key_and_value[1]) unless key_and_value[1].is_a? String
30
- "#{key_and_value[0].to_s}=#{CGI.escape key_and_value[1]}"
31
- end).join("&")
32
- end
33
-
34
- protected
35
-
36
- def self.params_require_multipart?(param_hash)
37
- param_hash.any? { |key, value| value.kind_of?(Koala::UploadableIO) }
38
- end
39
-
40
- def self.multipart_requires_content_type?
41
- true
42
- end
43
- end
44
- end
45
- end
46
- end
@@ -1,129 +0,0 @@
1
- require 'spec_helper'
2
-
3
-
4
- class Bear
5
- include Koala::HTTPService
6
- end
7
-
8
- describe "Koala::HTTPService" do
9
-
10
- describe "common methods" do
11
- describe "always_use_ssl accessor" do
12
- it "should be added" do
13
- # in Ruby 1.8, .methods returns strings
14
- # in Ruby 1.9, .method returns symbols
15
- Bear.methods.collect {|m| m.to_sym}.should include(:always_use_ssl)
16
- Bear.methods.collect {|m| m.to_sym}.should include(:always_use_ssl=)
17
- end
18
- end
19
-
20
- describe "proxy accessor" do
21
- it "should be added" do
22
- # in Ruby 1.8, .methods returns strings
23
- # in Ruby 1.9, .method returns symbols
24
- Bear.methods.collect {|m| m.to_sym}.should include(:proxy)
25
- Bear.methods.collect {|m| m.to_sym}.should include(:proxy=)
26
- end
27
- end
28
-
29
- describe "timeout accessor" do
30
- it "should be added" do
31
- # in Ruby 1.8, .methods returns strings
32
- # in Ruby 1.9, .method returns symbols
33
- Bear.methods.collect {|m| m.to_sym}.should include(:timeout)
34
- Bear.methods.collect {|m| m.to_sym}.should include(:timeout=)
35
- end
36
- end
37
-
38
- describe "server" do
39
- describe "with no options" do
40
- it "returns the REST server if options[:rest_api]" do
41
- Bear.server(:rest_api => true).should == Koala::Facebook::REST_SERVER
42
- end
43
-
44
- it "returns the graph server if !options[:rest_api]" do
45
- Bear.server(:rest_api => false).should == Koala::Facebook::GRAPH_SERVER
46
- Bear.server({}).should == Koala::Facebook::GRAPH_SERVER
47
- end
48
- end
49
-
50
- describe "with options[:beta]" do
51
- before :each do
52
- @options = {:beta => true}
53
- end
54
-
55
- it "returns the beta REST server if options[:rest_api]" do
56
- server = Bear.server(@options.merge(:rest_api => true))
57
- server.should =~ Regexp.new("beta.#{Koala::Facebook::REST_SERVER}")
58
- end
59
-
60
- it "returns the beta rest server if !options[:rest_api]" do
61
- server = Bear.server(@options)
62
- server.should =~ Regexp.new("beta.#{Koala::Facebook::GRAPH_SERVER}")
63
- end
64
- end
65
-
66
- describe "with options[:video]" do
67
- before :each do
68
- @options = {:video => true}
69
- end
70
-
71
- it "should return the REST video server if options[:rest_api]" do
72
- server = Bear.server(@options.merge(:rest_api => true))
73
- server.should =~ Regexp.new(Koala::Facebook::REST_SERVER.gsub(/\.facebook/, "-video.facebook"))
74
- end
75
-
76
- it "should return the graph video server if !options[:rest_api]" do
77
- server = Bear.server(@options)
78
- server.should =~ Regexp.new(Koala::Facebook::GRAPH_SERVER.gsub(/\.facebook/, "-video.facebook"))
79
- end
80
- end
81
- end
82
-
83
- describe "#encode_params" do
84
- it "should return an empty string if param_hash evaluates to false" do
85
- Bear.encode_params(nil).should == ''
86
- end
87
-
88
- it "should convert values to JSON if the value is not a String" do
89
- val = 'json_value'
90
- not_a_string = 'not_a_string'
91
- not_a_string.stub(:is_a?).and_return(false)
92
- MultiJson.should_receive(:encode).with(not_a_string).and_return(val)
93
-
94
- string = "hi"
95
-
96
- args = {
97
- not_a_string => not_a_string,
98
- string => string
99
- }
100
-
101
- result = Bear.encode_params(args)
102
- result.split('&').find do |key_and_val|
103
- key_and_val.match("#{not_a_string}=#{val}")
104
- end.should be_true
105
- end
106
-
107
- it "should escape all values" do
108
- args = Hash[*(1..4).map {|i| [i.to_s, "Value #{i}($"]}.flatten]
109
-
110
- result = Bear.encode_params(args)
111
- result.split('&').each do |key_val|
112
- key, val = key_val.split('=')
113
- val.should == CGI.escape(args[key])
114
- end
115
- end
116
-
117
- it "should convert all keys to Strings" do
118
- args = Hash[*(1..4).map {|i| [i, "val#{i}"]}.flatten]
119
-
120
- result = Bear.encode_params(args)
121
- result.split('&').each do |key_val|
122
- key, val = key_val.split('=')
123
- key.should == args.find{|key_val_arr| key_val_arr.last == val}.first.to_s
124
- end
125
- end
126
- end
127
- end
128
-
129
- end