rest-more 1.0.2 → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (72) hide show
  1. data/.gitignore +0 -5
  2. data/.travis.yml +4 -6
  3. data/CHANGES.md +16 -0
  4. data/Gemfile +6 -3
  5. data/README.md +43 -129
  6. data/Rakefile +2 -3
  7. data/example/multi.rb +12 -23
  8. data/example/rails3/Gemfile +2 -1
  9. data/example/rails3/app/controllers/application_controller.rb +9 -4
  10. data/example/rails3/test/functional/application_controller_test.rb +1 -1
  11. data/example/rainbows.rb +48 -7
  12. data/example/simple.rb +3 -3
  13. data/example/sinatra/config.ru +1 -1
  14. data/lib/rest-core/client/dropbox.rb +19 -27
  15. data/lib/rest-core/client/facebook.rb +28 -51
  16. data/lib/rest-core/client/facebook/rails_util.rb +13 -11
  17. data/lib/rest-core/client/github.rb +13 -21
  18. data/lib/rest-core/client/linkedin.rb +19 -27
  19. data/lib/rest-core/client/twitter.rb +13 -21
  20. data/lib/rest-more.rb +0 -2
  21. data/lib/rest-more/test.rb +11 -0
  22. data/lib/rest-more/version.rb +1 -1
  23. data/rest-more.gemspec +7 -41
  24. data/task/.gitignore +1 -0
  25. data/task/gemgem.rb +267 -0
  26. data/test/dropbox/test_api.rb +1 -1
  27. data/test/facebook/config/rest-core.yaml +1 -1
  28. data/test/facebook/test_api.rb +10 -14
  29. data/test/facebook/test_error.rb +2 -2
  30. data/test/facebook/test_handler.rb +6 -6
  31. data/test/facebook/test_load_config.rb +4 -4
  32. data/test/facebook/test_misc.rb +3 -3
  33. data/test/facebook/test_old.rb +2 -37
  34. data/test/facebook/test_page.rb +26 -24
  35. data/test/facebook/test_parse.rb +1 -1
  36. data/test/facebook/test_serialize.rb +3 -19
  37. data/test/facebook/test_timeout.rb +6 -2
  38. data/test/twitter/test_api.rb +1 -1
  39. metadata +6 -40
  40. data/doc/ToC.md +0 -9
  41. data/doc/dependency.md +0 -4
  42. data/doc/design.md +0 -4
  43. data/doc/rest-graph.md +0 -4
  44. data/example/async.rb +0 -89
  45. data/example/facebook.rb +0 -13
  46. data/example/rails2/Gemfile +0 -22
  47. data/example/rails2/README +0 -4
  48. data/example/rails2/Rakefile +0 -11
  49. data/example/rails2/app/controllers/application_controller.rb +0 -138
  50. data/example/rails2/app/views/application/helper.html.erb +0 -1
  51. data/example/rails2/config/boot.rb +0 -130
  52. data/example/rails2/config/environment.rb +0 -25
  53. data/example/rails2/config/environments/development.rb +0 -17
  54. data/example/rails2/config/environments/production.rb +0 -28
  55. data/example/rails2/config/environments/test.rb +0 -30
  56. data/example/rails2/config/initializers/cookie_verification_secret.rb +0 -7
  57. data/example/rails2/config/initializers/new_rails_defaults.rb +0 -21
  58. data/example/rails2/config/initializers/session_store.rb +0 -15
  59. data/example/rails2/config/preinitializer.rb +0 -23
  60. data/example/rails2/config/rest-core.yaml +0 -12
  61. data/example/rails2/config/routes.rb +0 -43
  62. data/example/rails2/log +0 -0
  63. data/example/rails2/test/functional/application_controller_test.rb +0 -259
  64. data/example/rails2/test/test_helper.rb +0 -18
  65. data/example/rails2/test/unit/rails_util_test.rb +0 -49
  66. data/lib/rest-core/client/bing.rb +0 -102
  67. data/lib/rest-core/client/bing/rails_util.rb +0 -13
  68. data/lib/rest-core/client/mixi.rb +0 -60
  69. data/lib/rest-core/client/mixi/rails_util.rb +0 -13
  70. data/test/bing/test_api.rb +0 -34
  71. data/test/facebook/test_cache.rb +0 -58
  72. data/test/mixi/test_api.rb +0 -20
@@ -124,7 +124,7 @@ class ApplicationControllerTest < ActionController::TestCase
124
124
 
125
125
  get(:cache)
126
126
  assert_response :success
127
- assert_equal '{"message":"ok"}', @response.body
127
+ assert_equal %Q|200\n\n\n{"message":"ok"}|, @response.body
128
128
  end
129
129
 
130
130
  def test_handler
data/example/rainbows.rb CHANGED
@@ -4,7 +4,9 @@ preload_app true
4
4
 
5
5
  Rainbows! do
6
6
  use :EventMachine, :em_client_class => lambda{
7
- RainbowsEventMachineFiberClient
7
+ RainbowsEventMachineThreadPoolClient
8
+ # or
9
+ # RainbowsEventMachineFiberSpawnClient
8
10
  }
9
11
  worker_connections 100
10
12
 
@@ -12,14 +14,53 @@ Rainbows! do
12
14
  client_header_buffer_size 8*1024 # 8 kilobytes
13
15
  end
14
16
 
15
- require 'rest-more'
16
- ::RC::Builder.default_app = ::RC::Auto
17
+ after_fork{ |_, _|
18
+ EM.threadpool_size = 32
19
+ class RainbowsEventMachineThreadPoolClient < Rainbows::EventMachine::Client
20
+ def app_call input
21
+ set_comm_inactivity_timeout 0
22
+ @env[RACK_INPUT] = input
23
+ @env[REMOTE_ADDR] = @_io.kgio_addr
24
+ @env[ASYNC_CALLBACK] = method(:write_async_response)
25
+ @env[ASYNC_CLOSE] = EM::DefaultDeferrable.new
26
+ @deferred = true
27
+ EM.defer{
28
+ status, headers, body = catch(:async) {
29
+ APP.call(@env.merge!(RACK_DEFAULTS))
30
+ }
31
+ if nil == status || -1 == status
32
+ @deferred = true
33
+ else
34
+ @deferred = nil
35
+ ev_write_response(status, headers, body, @hp.next?)
36
+ end
37
+ }
38
+ end
39
+ end
17
40
 
18
- class RainbowsEventMachineFiberClient < Rainbows::EventMachine::Client
19
- def app_call input
20
- Fiber.new{ super }.resume
41
+ class RainbowsEventMachineFiberSpawnClient < Rainbows::EventMachine::Client
42
+ def app_call input
43
+ set_comm_inactivity_timeout 0
44
+ @env[RACK_INPUT] = input
45
+ @env[REMOTE_ADDR] = @_io.kgio_addr
46
+ @env[ASYNC_CALLBACK] = method(:write_async_response)
47
+ @env[ASYNC_CLOSE] = EM::DefaultDeferrable.new
48
+ f = Fiber.new{
49
+ status, headers, body = catch(:async) {
50
+ APP.call(@env.merge!(RACK_DEFAULTS))
51
+ }
52
+ if nil == status || -1 == status
53
+ @deferred = true
54
+ else
55
+ @deferred = nil
56
+ ev_write_response(status, headers, body, @hp.next?)
57
+ end
58
+ }
59
+ f.resume
60
+ @deferred = true if f.alive?
61
+ end
21
62
  end
22
- end
63
+ }
23
64
 
24
65
  EM.error_handler{ |e|
25
66
  puts "Error: EM.error_handler: #{e.inspect} #{e.backtrace.inspect}"
data/example/simple.rb CHANGED
@@ -1,8 +1,8 @@
1
1
 
2
2
  require 'rest-more'
3
3
 
4
- p RestCore::Twitter.new.statuses('_cardinalblue').first # get user tweets
4
+ p RC::Twitter.new.statuses('_cardinalblue').first # get user tweets
5
5
  puts
6
- p RestCore::Github.new.get('users/cardinalblue') # get user info
6
+ p RC::Github.new.get('users/cardinalblue') # get user info
7
7
  puts
8
- p RestCore::Facebook.new.get('4') # get user info
8
+ p RC::Facebook.new.get('4') # get user info
@@ -8,7 +8,7 @@ config = {:app_id => app_id,
8
8
  :secret => secret}
9
9
 
10
10
  post '/' do
11
- fb = RestCore::Facebook.new(config)
11
+ fb = RC::Facebook.new(config)
12
12
  fb.parse_signed_request!(params['signed_request'])
13
13
  "#{fb.get('me').inspect.gsub('<', '&lt;')}\n"
14
14
  end
@@ -2,32 +2,24 @@
2
2
  require 'rest-core'
3
3
 
4
4
  # https://www.dropbox.com/developers/reference/api
5
- RestCore::Dropbox = RestCore::Builder.client(:root) do
6
- s = RestCore
7
- use s::Timeout , 10
8
-
9
- use s::DefaultSite , 'https://api.dropbox.com/'
10
- use s::DefaultHeaders, {'Accept' => 'application/json',
11
- 'Content-Type' => 'application/octet-stream'}
12
-
13
- use s::Oauth1Header ,
14
- '1/oauth/request_token', '1/oauth/access_token',
15
- 'https://www.dropbox.com/1/oauth/authorize'
16
-
17
- use s::CommonLogger , nil
18
- use s::Cache , nil, 600 do
19
- use s::ErrorHandler, lambda{ |env|
20
- if env[s::ASYNC]
21
- if env[s::RESPONSE_BODY].kind_of?(::Exception)
22
- env
23
- else
24
- env.merge(s::RESPONSE_BODY => ::RestCore::Dropbox::Error.call(env))
25
- end
26
- else
27
- raise ::RestCore::Dropbox::Error.call(env)
28
- end}
29
- use s::ErrorDetectorHttp
30
- use s::JsonDecode , true
5
+ module RestCore
6
+ Dropbox = Builder.client(:root) do
7
+ use Timeout , 10
8
+
9
+ use DefaultSite , 'https://api.dropbox.com/'
10
+ use DefaultHeaders, {'Accept' => 'application/json',
11
+ 'Content-Type' => 'application/octet-stream'}
12
+
13
+ use Oauth1Header ,
14
+ '1/oauth/request_token', '1/oauth/access_token',
15
+ 'https://www.dropbox.com/1/oauth/authorize'
16
+
17
+ use CommonLogger , nil
18
+ use Cache , nil, 600 do
19
+ use ErrorHandler, lambda{ |env| Dropbox::Error.call(env) }
20
+ use ErrorDetectorHttp
21
+ use JsonResponse, true
22
+ end
31
23
  end
32
24
  end
33
25
 
@@ -86,7 +78,7 @@ module RestCore::Dropbox::Client
86
78
 
87
79
  def download path, query={}, opts={}
88
80
  get("https://api-content.dropbox.com/1/files/#{root}/#{path}",
89
- query, {:json_decode => false}.merge(opts))
81
+ query, {:json_response => false}.merge(opts))
90
82
  end
91
83
 
92
84
  def upload path, file, query={}, opts={}
@@ -4,39 +4,27 @@ require 'rest-core/util/hmac'
4
4
 
5
5
  # https://developers.facebook.com/docs/reference/api
6
6
  # https://developers.facebook.com/tools/explorer
7
- RestCore::Facebook = RestCore::Builder.client(
8
- :data, :app_id, :secret, :old_site) do
9
-
10
- s = RestCore
11
- use s::Timeout , 10
12
-
13
- use s::DefaultSite , 'https://graph.facebook.com/'
14
- use s::DefaultHeaders, {'Accept' => 'application/json',
15
- 'Accept-Language' => 'en-us'}
16
- use s::Oauth2Query , nil
17
-
18
- use s::CommonLogger , nil
19
- use s::Cache , nil, 600 do
20
- use s::ErrorHandler, lambda{ |env|
21
- if env[s::ASYNC]
22
- if env[s::RESPONSE_BODY].kind_of?(::Exception)
23
- env
24
- else
25
- env.merge(s::RESPONSE_BODY => ::RestCore::Facebook::Error.call(env))
26
- end
27
- else
28
- raise ::RestCore::Facebook::Error.call(env)
29
- end}
30
- use s::ErrorDetector, lambda{ |env|
31
- if env[s::RESPONSE_BODY].kind_of?(Hash)
32
- env[s::RESPONSE_BODY]['error'] ||
33
- env[s::RESPONSE_BODY]['error_code']
34
- end}
35
-
36
- use s::JsonDecode , true
37
- end
7
+ module RestCore
8
+ Facebook = Builder.client(:data, :app_id, :secret, :old_site) do
9
+ use Timeout , 10
10
+
11
+ use DefaultSite , 'https://graph.facebook.com/'
12
+ use DefaultHeaders, {'Accept' => 'application/json',
13
+ 'Accept-Language' => 'en-us'}
14
+ use Oauth2Query , nil
15
+
16
+ use CommonLogger , nil
17
+ use Cache , nil, 600 do
18
+ use ErrorHandler, lambda{ |env| Facebook::Error.call(env) }
19
+ use ErrorDetector, lambda{ |env|
20
+ env[RESPONSE_BODY].kind_of?(Hash) &&
21
+ (env[RESPONSE_BODY]['error'] || env[RESPONSE_BODY]['error_code'])}
22
+
23
+ use JsonResponse, true
24
+ end
38
25
 
39
- use s::Defaults , :old_site => 'https://api.facebook.com/'
26
+ use Defaults , :old_site => 'https://api.facebook.com/'
27
+ end
40
28
  end
41
29
 
42
30
  class RestCore::Facebook::Error < RestCore::Error
@@ -195,8 +183,8 @@ module RestCore::Facebook::Client
195
183
 
196
184
  def parse_json! json
197
185
  self.data = json &&
198
- check_sig_and_return_data(JsonDecode.json_decode(json))
199
- rescue JsonDecode::ParseError
186
+ check_sig_and_return_data(Json.decode(json))
187
+ rescue Json::ParseError
200
188
  self.data = nil
201
189
  end
202
190
 
@@ -213,10 +201,10 @@ module RestCore::Facebook::Client
213
201
  "#{str.tr('-_', '+/')}==".unpack('m').first
214
202
  }
215
203
  self.data = check_sig_and_return_data(
216
- JsonDecode.json_decode(json).merge('sig' => sig)){
204
+ Json.decode(json).merge('sig' => sig)){
217
205
  Hmac.sha256(secret, json_encoded)
218
206
  }
219
- rescue JsonDecode::ParseError
207
+ rescue Json::ParseError
220
208
  self.data = nil
221
209
  end
222
210
 
@@ -231,24 +219,14 @@ module RestCore::Facebook::Client
231
219
  payload = {:client_id => app_id, :client_secret => secret}.merge(opts)
232
220
  self.data = ParseQuery.parse_query(
233
221
  post('oauth/access_token', payload, {},
234
- {:json_decode => false}.merge(opts)))
222
+ {:json_response => false}.merge(opts)))
235
223
  end
236
224
 
237
225
  # old rest facebook api, i will definitely love to remove them someday
238
226
 
239
227
  def old_rest path, query={}, opts={}, &cb
240
- uri = url("method/#{path}", {:format => 'json'}.merge(query),
241
- {:site => old_site}.merge(opts))
242
- if opts[:post]
243
- post(url("method/#{path}", {:format => 'json'},
244
- {:site => old_site}.merge(opts)),
245
- query,
246
- {} ,
247
- opts.merge('cache.key' => uri, 'cache.post' => true),
248
- &cb)
249
- else
250
- get(uri, {}, opts, &cb)
251
- end
228
+ get("method/#{path}", {:format => 'json'}.merge(query),
229
+ {:site => old_site}.merge(opts), &cb)
252
230
  end
253
231
 
254
232
  def secret_old_rest path, query={}, opts={}, &cb
@@ -261,7 +239,7 @@ module RestCore::Facebook::Client
261
239
 
262
240
  def fql_multi codes, query={}, opts={}, &cb
263
241
  old_rest('fql.multiquery',
264
- {:queries => JsonDecode.json_encode(codes)}.merge(query), opts, &cb)
242
+ {:queries => Json.encode(codes)}.merge(query), opts, &cb)
265
243
  end
266
244
 
267
245
  def exchange_sessions query={}, opts={}, &cb
@@ -280,7 +258,6 @@ module RestCore::Facebook::Client
280
258
  super(env.inject({}){ |r, (k, v)|
281
259
  case k.to_s
282
260
  when 'secret' ; r['access_token'] = secret_access_token
283
- when 'cache' ; r['cache.update'] = !!!v
284
261
  else ; r[k.to_s] = v
285
262
  end
286
263
  r
@@ -268,17 +268,19 @@ module RestCore::Facebook::RailsUtil
268
268
  end
269
269
 
270
270
  def rc_facebook_normalized_request_uri
271
- uri = if rc_facebook_in_canvas?
272
- # rails 3 uses newer rack which has fullpath
273
- "http://apps.facebook.com/#{
274
- rc_options_get(RestCore::Facebook, :canvas)}" +
275
- (request.respond_to?(:fullpath) ?
276
- request.fullpath : request.request_uri)
277
- else
278
- request.url
279
- end
280
-
281
- rc_facebook_filter_uri(uri)
271
+ @rc_facebook_normalized_request_uri ||= begin
272
+ uri = if rc_facebook_in_canvas?
273
+ # rails 3 uses newer rack which has fullpath
274
+ "http://apps.facebook.com/#{
275
+ rc_options_get(RestCore::Facebook, :canvas)}" +
276
+ (request.respond_to?(:fullpath) ?
277
+ request.fullpath : request.request_uri)
278
+ else
279
+ request.url
280
+ end
281
+
282
+ rc_facebook_filter_uri(uri)
283
+ end
282
284
  end
283
285
 
284
286
  def rc_facebook_filter_uri uri
@@ -2,29 +2,21 @@
2
2
  require 'rest-core'
3
3
 
4
4
  # http://developer.github.com/v3/
5
- RestCore::Github = RestCore::Builder.client do
6
- s = RestCore
7
- use s::Timeout , 10
5
+ module RestCore
6
+ Github = Builder.client do
7
+ use Timeout , 10
8
8
 
9
- use s::DefaultSite , 'https://api.github.com/'
10
- use s::DefaultHeaders, {'Accept' => 'application/json'}
11
- use s::Oauth2Query , nil
9
+ use DefaultSite , 'https://api.github.com/'
10
+ use DefaultHeaders, {'Accept' => 'application/json'}
11
+ use Oauth2Query , nil
12
12
 
13
- use s::CommonLogger , nil
14
- use s::Cache , nil, 600 do
15
- use s::ErrorHandler, lambda{ |env|
16
- if env[s::ASYNC]
17
- if env[s::RESPONSE_BODY].kind_of?(::Exception)
18
- env
19
- else
20
- env.merge(s::RESPONSE_BODY =>
21
- RuntimeError.new(env[s::RESPONSE_BODY]['message']))
22
- end
23
- else
24
- raise env[s::RESPONSE_BODY]['message']
25
- end}
26
- use s::ErrorDetectorHttp
27
- use s::JsonDecode , true
13
+ use CommonLogger , nil
14
+ use Cache , nil, 600 do
15
+ use ErrorHandler, lambda{ |env|
16
+ RuntimeError.new(env[RESPONSE_BODY]['message'])}
17
+ use ErrorDetectorHttp
18
+ use JsonResponse, true
19
+ end
28
20
  end
29
21
  end
30
22
 
@@ -2,33 +2,25 @@
2
2
  require 'rest-core'
3
3
 
4
4
  # http://developer.linkedin.com/documents/linkedin-api-resource-map
5
- RestCore::Linkedin = RestCore::Builder.client do
6
- s = RestCore
7
- use s::Timeout , 10
8
-
9
- use s::DefaultSite , 'https://api.linkedin.com/'
10
- use s::DefaultHeaders, {'Accept' => 'application/json'}
11
- use s::DefaultQuery , {'format' => 'json'}
12
-
13
- use s::Oauth1Header ,
14
- 'uas/oauth/requestToken', 'uas/oauth/accessToken',
15
- 'https://www.linkedin.com/uas/oauth/authorize'
16
-
17
- use s::CommonLogger , nil
18
- use s::Cache , nil, 600 do
19
- use s::ErrorHandler, lambda{ |env|
20
- if env[s::ASYNC]
21
- if env[s::RESPONSE_BODY].kind_of?(::Exception)
22
- env
23
- else
24
- env.merge(s::RESPONSE_BODY =>
25
- RuntimeError.new(env[s::RESPONSE_BODY]['message']))
26
- end
27
- else
28
- raise env[s::RESPONSE_BODY]['message']
29
- end}
30
- use s::ErrorDetectorHttp
31
- use s::JsonDecode , true
5
+ module RestCore
6
+ Linkedin = Builder.client do
7
+ use Timeout , 10
8
+
9
+ use DefaultSite , 'https://api.linkedin.com/'
10
+ use DefaultHeaders, {'Accept' => 'application/json'}
11
+ use DefaultQuery , {'format' => 'json'}
12
+
13
+ use Oauth1Header ,
14
+ 'uas/oauth/requestToken', 'uas/oauth/accessToken',
15
+ 'https://www.linkedin.com/uas/oauth/authorize'
16
+
17
+ use CommonLogger , nil
18
+ use Cache , nil, 600 do
19
+ use ErrorHandler, lambda{ |env|
20
+ RuntimeError.new(env[RESPONSE_BODY]['message'])}
21
+ use ErrorDetectorHttp
22
+ use JsonResponse, true
23
+ end
32
24
  end
33
25
  end
34
26
 
@@ -2,30 +2,22 @@
2
2
  require 'rest-core'
3
3
 
4
4
  # https://dev.twitter.com/docs
5
- RestCore::Twitter = RestCore::Builder.client do
6
- s = RestCore
7
- use s::Timeout , 10
5
+ module RestCore
6
+ Twitter = Builder.client do
7
+ use Timeout , 10
8
8
 
9
- use s::DefaultSite , 'https://api.twitter.com/'
10
- use s::DefaultHeaders, {'Accept' => 'application/json'}
9
+ use DefaultSite , 'https://api.twitter.com/'
10
+ use DefaultHeaders, {'Accept' => 'application/json'}
11
11
 
12
- use s::Oauth1Header ,
13
- 'oauth/request_token', 'oauth/access_token', 'oauth/authorize'
12
+ use Oauth1Header ,
13
+ 'oauth/request_token', 'oauth/access_token', 'oauth/authorize'
14
14
 
15
- use s::CommonLogger , nil
16
- use s::Cache , nil, 600 do
17
- use s::ErrorHandler, lambda{ |env|
18
- if env[s::ASYNC]
19
- if env[s::RESPONSE_BODY].kind_of?(::Exception)
20
- env
21
- else
22
- env.merge(s::RESPONSE_BODY => ::RestCore::Twitter::Error.call(env))
23
- end
24
- else
25
- raise ::RestCore::Twitter::Error.call(env)
26
- end}
27
- use s::ErrorDetectorHttp
28
- use s::JsonDecode , true
15
+ use CommonLogger , nil
16
+ use Cache , nil, 600 do
17
+ use ErrorHandler, lambda{ |env| Twitter::Error.call(env) }
18
+ use ErrorDetectorHttp
19
+ use JsonResponse, true
20
+ end
29
21
  end
30
22
  end
31
23