rest-core 1.0.0 → 1.0.1

Sign up to get free protection for your applications and to get access to all the features.
data/CHANGES.md CHANGED
@@ -1,5 +1,11 @@
1
1
  # CHANGES
2
2
 
3
+ ## rest-core 1.0.1 -- 2012-05-14
4
+
5
+ * [`Auto`] Check for eventmachine first instead of cool.io
6
+ * [`EmHttpRequestFiber`] Also pass callback for errback
7
+ * [`DefaultQuery`] Make default query to {} instead of nil
8
+
3
9
  ## rest-core 1.0.0 -- 2012-03-17
4
10
 
5
11
  This is a very significant release. The most important change is now we
@@ -7,7 +13,7 @@ support asynchronous requests, by either passing a callback block or using
7
13
  fibers in Ruby 1.9 to make the whole program still look synchronous.
8
14
 
9
15
  Please read [README.md](https://github.com/cardinalblue/rest-core/blob/master/README.md)
10
- or [example](https://github.com/cardinalblue/rest-core/blob/master/example)
16
+ or [example](https://github.com/cardinalblue/rest-core/tree/master/example)
11
17
  for more detail.
12
18
 
13
19
  * [`Client`] Client#inspect is fixed for clients which do not have any
data/README.md CHANGED
@@ -49,14 +49,16 @@ dedicated clients provided by [rest-more][].
49
49
  * Fibers only work on Ruby 1.9+
50
50
  * gem [em-http-request][] (if using eventmachine)
51
51
  * gem [cool.io-http][] (if using cool.io)
52
- * gem json or yajl-ruby (if using JsonDecode middleware)
52
+ * gem json or yajl-ruby (if using `JsonDecode` middleware)
53
53
 
54
54
  [em-http-request]: https://github.com/igrigorik/em-http-request
55
55
  [cool.io-http]: https://github.com/godfat/cool.io-http
56
56
 
57
57
  ## INSTALLATION:
58
58
 
59
+ ``` shell
59
60
  gem install rest-core
61
+ ```
60
62
 
61
63
  Or if you want development version, put this in Gemfile:
62
64
 
@@ -106,14 +108,14 @@ for concepts.
106
108
 
107
109
  [example/rest-client.rb]: https://github.com/cardinalblue/rest-core/blob/master/example/rest-client.rb
108
110
  [rest-more]: https://github.com/cardinalblue/rest-more
109
- [rubyconf.tw]: http://rubyconf.tw/2011/#6
110
111
  [slides]: http://www.godfat.org/slide/2011-08-27-rest-core.html
112
+ [rubyconf.tw]: http://rubyconf.tw/2011/#6
111
113
 
112
114
  ## Asynchronous HTTP Requests:
113
115
 
114
116
  I/O bound operations shouldn't be blocking the CPU! If you have a reactor,
115
117
  i.e. event loop, you should take the advantage of that to make HTTP requests
116
- non-blocking the whole process/thread. For now, we support eventmachine and
118
+ not block the whole process/thread. For now, we support eventmachine and
117
119
  cool.io. Below is an example for eventmachine:
118
120
 
119
121
  ``` ruby
@@ -133,12 +135,13 @@ If you're passing a block, the block is called after the response is
133
135
  available. That is the block is the callback for the request.
134
136
 
135
137
  ``` ruby
136
- client = AsynchronousClient.new(:cache => {})
138
+ client = AsynchronousClient.new
137
139
  EM.run{
138
140
  client.get('cardinalblue'){ |response|
139
141
  p response
140
142
  EM.stop
141
143
  }
144
+ puts "It's not blocking..."
142
145
  }
143
146
  ```
144
147
 
@@ -154,6 +157,7 @@ If you don't understand what does this mean, you can take a look at
154
157
  p client.get('cardinalblue')
155
158
  EM.stop
156
159
  }.resume
160
+ puts "It's not blocking..."
157
161
  }
158
162
  ```
159
163
 
@@ -178,6 +182,7 @@ You can also make multi-requests synchronously like this:
178
182
  p Fiber.yield
179
183
  EM.stop
180
184
  }.resume
185
+ puts "It's not blocking..."
181
186
  }
182
187
  ```
183
188
 
data/TODO.md CHANGED
@@ -1,4 +1,22 @@
1
1
  # TODO
2
2
 
3
+ * Auto should also pick RestClient if it's not inside a fiber
4
+ * HTTP method in Requested log
3
5
  * middleware revisit (how to initialize?)
4
6
  * test utility
7
+
8
+ # BUG
9
+
10
+ * inheritance should work; assign builder?
11
+ * no error handling in cool.io
12
+
13
+ # FEATURE
14
+
15
+ * middleware composer
16
+ * RC::Payload which can handle Content-Type: application/json
17
+ * how to pass a arbitrary payload generator?
18
+ * RC::JsonRequest
19
+ * RC::FakeGetWithPayload
20
+
21
+ * ResponseThunk and EmHttpRequestThunk
22
+ * options for apps
@@ -10,12 +10,13 @@ AsynchronousClient = RestCore::Builder.client do
10
10
  run s::EmHttpRequest
11
11
  end
12
12
 
13
- client = AsynchronousClient.new(:cache => {})
13
+ client = AsynchronousClient.new
14
14
  EM.run{
15
15
  client.get('cardinalblue'){ |response|
16
16
  p response
17
17
  EM.stop
18
18
  }
19
+ puts "It's not blocking..."
19
20
  }
20
21
 
21
22
  puts
@@ -25,4 +26,5 @@ EM.run{
25
26
  p client.get('cardinalblue')
26
27
  EM.stop
27
28
  }.resume
29
+ puts "It's not blocking..."
28
30
  }
@@ -23,6 +23,7 @@ EM.run{
23
23
  result[0] = response
24
24
  fiber.resume(result) if result.size == 2
25
25
  }
26
+ puts "It's not blocking..."
26
27
  client.get('cardinalblue'){ |response|
27
28
  result[1] = response
28
29
  fiber.resume(result) if result.size == 2
@@ -30,4 +31,5 @@ EM.run{
30
31
  p Fiber.yield
31
32
  EM.stop
32
33
  }.resume
34
+ puts "It's not blocking..."
33
35
  }
@@ -9,12 +9,13 @@ class RestCore::Auto
9
9
  end
10
10
 
11
11
  def http_client
12
- if Object.const_defined?(:Coolio) && ::Coolio::Loop.default.
13
- has_active_watchers?
14
- @coolio ||= RestCore::Coolio.new
15
- elsif Object.const_defined?(:EventMachine) && ::EventMachine.
16
- reactor_running?
12
+ if Object.const_defined?(:EventMachine) && ::EventMachine.reactor_running?
17
13
  @emhttprequest ||= RestCore::EmHttpRequest.new
14
+
15
+ elsif Object.const_defined?(:Coolio) && ::Coolio::Loop.default.
16
+ has_active_watchers?
17
+ @coolio ||= RestCore::Coolio.new
18
+
18
19
  else
19
20
  @restclient ||= RestCore::RestClient.new
20
21
  end
@@ -13,13 +13,8 @@ class RestCore::EmHttpRequestAsync
13
13
  :body => payload.read,
14
14
  :head => payload.headers.merge(env[REQUEST_HEADERS]))
15
15
 
16
- client.callback{
17
- env[TIMER].cancel if env[TIMER]
18
- env[ASYNC].call(env.merge(
19
- RESPONSE_BODY => client.response,
20
- RESPONSE_STATUS => client.response_header.status,
21
- RESPONSE_HEADERS => client.response_header)) if env[ASYNC]
22
- }
16
+ client.callback{ respond(env, client) }
17
+ client. errback{ respond(env, client) }
23
18
 
24
19
  env[TIMER].on_timeout{
25
20
  client.close
@@ -31,4 +26,12 @@ class RestCore::EmHttpRequestAsync
31
26
 
32
27
  env
33
28
  end
29
+
30
+ def respond env, client
31
+ env[TIMER].cancel if env[TIMER]
32
+ env[ASYNC].call(env.merge(
33
+ RESPONSE_BODY => client.response,
34
+ RESPONSE_STATUS => client.response_header.status,
35
+ RESPONSE_HEADERS => client.response_header)) if env[ASYNC]
36
+ end
34
37
  end
@@ -16,10 +16,8 @@ class RestCore::EmHttpRequestFiber
16
16
  :body => payload.read,
17
17
  :head => payload.headers.merge(env[REQUEST_HEADERS]))
18
18
 
19
- client.callback{
20
- env[TIMER].cancel if env[TIMER]
21
- f.resume(process(env, client)) if f.alive?
22
- }
19
+ client.callback{ respond(f, env, client) }
20
+ client. errback{ respond(f, env, client) }
23
21
 
24
22
  if (response = Fiber.yield).kind_of?(::Exception)
25
23
  client.close
@@ -29,6 +27,11 @@ class RestCore::EmHttpRequestFiber
29
27
  end
30
28
  end
31
29
 
30
+ def respond f, env, client
31
+ env[TIMER].cancel if env[TIMER]
32
+ f.resume(process(env, client)) if f.alive?
33
+ end
34
+
32
35
  def process env, client
33
36
  result = env.merge(RESPONSE_BODY => client.response,
34
37
  RESPONSE_STATUS => client.response_header.status,
@@ -4,6 +4,12 @@ require 'rest-core/middleware'
4
4
  class RestCore::DefaultQuery
5
5
  def self.members; [:query]; end
6
6
  include RestCore::Middleware
7
+
8
+ def initialize *args
9
+ super
10
+ @query ||= {}
11
+ end
12
+
7
13
  def call env
8
14
  app.call(env.merge(REQUEST_QUERY =>
9
15
  @query.merge(query(env)).merge(env[REQUEST_QUERY] || {})))
@@ -8,7 +8,7 @@ class RestCore::Timeout
8
8
  include RestCore::Middleware
9
9
 
10
10
  def call env
11
- return app.call(env) if env[DRY]
11
+ return app.call(env) if env[DRY] || timeout(env) == 0
12
12
  monitor(env){ |e| app.call(e) }
13
13
  end
14
14
 
@@ -21,7 +21,7 @@ class RestCore::Timeout
21
21
  end
22
22
 
23
23
  case class_name
24
- when /Coolio|EmHttpRequest/
24
+ when /EmHttpRequest|Coolio/
25
25
  if root_fiber? && env[ASYNC]
26
26
  yield(env.merge(TIMER => timeout_with_callback(env, class_name)))
27
27
  else
@@ -42,13 +42,13 @@ class RestCore::Timeout
42
42
 
43
43
  def timeout_with_callback env, class_name
44
44
  case class_name
45
+ when /EmHttpRequest/
46
+ EventMachineTimer.new(timeout(env), timeout_error)
45
47
  when /Coolio/
46
48
  timer = CoolioTimer.new(timeout(env))
47
49
  timer.error = timeout_error
48
50
  timer.attach(::Coolio::Loop.default)
49
51
  timer
50
- when /EmHttpRequest/
51
- EventMachineTimer.new(timeout(env), timeout_error)
52
52
  else
53
53
  raise "BUG: #{run} is not supported"
54
54
  end
@@ -56,6 +56,12 @@ class RestCore::Timeout
56
56
 
57
57
  def timeout_with_resume env, class_name
58
58
  case class_name
59
+ when /EmHttpRequest/
60
+ f = Fiber.current
61
+ EventMachineTimer.new(timeout(env), error = timeout_error){
62
+ f.resume(error) if f.alive?
63
+ }
64
+
59
65
  when /Coolio/
60
66
  f = Fiber.current
61
67
  timer = CoolioTimer.new(timeout(env))
@@ -64,11 +70,6 @@ class RestCore::Timeout
64
70
  timer.attach(::Coolio::Loop.default)
65
71
  timer
66
72
 
67
- when /EmHttpRequest/
68
- f = Fiber.current
69
- EventMachineTimer.new(timeout(env), error = timeout_error){
70
- f.resume(error) if f.alive?
71
- }
72
73
  else
73
74
  raise "BUG: #{run} is not supported"
74
75
  end
@@ -78,8 +79,8 @@ class RestCore::Timeout
78
79
  ::Timeout::Error.new('execution expired')
79
80
  end
80
81
 
81
- autoload :CoolioTimer,
82
- 'rest-core/middleware/timeout/coolio_timer'
83
82
  autoload :EventMachineTimer,
84
83
  'rest-core/middleware/timeout/eventmachine_timer'
84
+ autoload :CoolioTimer,
85
+ 'rest-core/middleware/timeout/coolio_timer'
85
86
  end
@@ -1,4 +1,4 @@
1
1
 
2
2
  module RestCore
3
- VERSION = '1.0.0'
3
+ VERSION = '1.0.1'
4
4
  end
@@ -2,13 +2,13 @@
2
2
 
3
3
  Gem::Specification.new do |s|
4
4
  s.name = "rest-core"
5
- s.version = "1.0.0"
5
+ s.version = "1.0.1"
6
6
 
7
7
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
8
8
  s.authors = [
9
9
  "Cardinal Blue",
10
10
  "Lin Jen-Shin (godfat)"]
11
- s.date = "2012-03-17"
11
+ s.date = "2012-05-14"
12
12
  s.description = "Modular Ruby clients interface for REST APIs\n\nThere has been an explosion in the number of REST APIs available today.\nTo address the need for a way to access these APIs easily and elegantly,\nwe have developed [rest-core][], which consists of composable middleware\nthat allows you to build a REST client for any REST API. Or in the case of\ncommon APIs such as Facebook, Github, and Twitter, you can simply use the\ndedicated clients provided by [rest-more][].\n\n[rest-core]: https://github.com/cardinalblue/rest-core\n[rest-more]: https://github.com/cardinalblue/rest-more"
13
13
  s.email = ["dev (XD) cardinalblue.com"]
14
14
  s.files = [
@@ -84,29 +84,33 @@ Gem::Specification.new do |s|
84
84
  "test/test_builder.rb",
85
85
  "test/test_client.rb",
86
86
  "test/test_client_oauth1.rb",
87
+ "test/test_default_query.rb",
87
88
  "test/test_error_detector.rb",
88
89
  "test/test_error_detector_http.rb",
89
90
  "test/test_follow_redirect.rb",
90
91
  "test/test_json_decode.rb",
91
92
  "test/test_oauth1_header.rb",
92
93
  "test/test_payload.rb",
94
+ "test/test_timeout.rb",
93
95
  "test/test_universal.rb",
94
96
  "test/test_wrapper.rb"]
95
97
  s.homepage = "https://github.com/cardinalblue/rest-core"
96
98
  s.require_paths = ["lib"]
97
- s.rubygems_version = "1.8.19"
99
+ s.rubygems_version = "1.8.24"
98
100
  s.summary = "Modular Ruby clients interface for REST APIs"
99
101
  s.test_files = [
100
102
  "test/test_auth_basic.rb",
101
103
  "test/test_builder.rb",
102
104
  "test/test_client.rb",
103
105
  "test/test_client_oauth1.rb",
106
+ "test/test_default_query.rb",
104
107
  "test/test_error_detector.rb",
105
108
  "test/test_error_detector_http.rb",
106
109
  "test/test_follow_redirect.rb",
107
110
  "test/test_json_decode.rb",
108
111
  "test/test_oauth1_header.rb",
109
112
  "test/test_payload.rb",
113
+ "test/test_timeout.rb",
110
114
  "test/test_universal.rb",
111
115
  "test/test_wrapper.rb"]
112
116
 
@@ -0,0 +1,45 @@
1
+
2
+ require 'rest-core/test'
3
+
4
+ describe RC::DefaultQuery do
5
+ describe 'when given query' do
6
+ before do
7
+ @app = RC::DefaultQuery.new(RC::Dry.new, {})
8
+ end
9
+
10
+ def app
11
+ @app
12
+ end
13
+
14
+ should 'do nothing' do
15
+ app.call({})[RC::REQUEST_QUERY].should.eq({})
16
+ end
17
+
18
+ should 'merge query' do
19
+ app.instance_eval{@query = {'q' => 'uery'}}
20
+
21
+ app.call({}).should.eq({RC::REQUEST_QUERY =>
22
+ {'q' => 'uery'}})
23
+
24
+ format = {'format' => 'json'}
25
+ env = {RC::REQUEST_QUERY => format}
26
+
27
+ app.call(env).should.eq({RC::REQUEST_QUERY =>
28
+ {'q' => 'uery'}.merge(format)})
29
+ end
30
+ end
31
+
32
+ describe 'when not given query' do
33
+ before do
34
+ @app = RC::DefaultQuery.new(RC::Dry.new)
35
+ end
36
+
37
+ def app
38
+ @app
39
+ end
40
+
41
+ should 'merge query with {}' do
42
+ app.call({}).should.eq({RC::REQUEST_QUERY => {}})
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,19 @@
1
+
2
+ require 'rest-core/test'
3
+
4
+ describe RC::Timeout do
5
+ before do
6
+ @app = RC::Timeout.new(RC::Dry.new, 0)
7
+ end
8
+
9
+ should 'bypass timeout if timeout is 0' do
10
+ mock(@app).monitor.times(0)
11
+ @app.call({}).should.eq({})
12
+ end
13
+
14
+ should 'run the monitor to setup timeout' do
15
+ env = {'timeout' => 2}
16
+ mock.proxy(@app).monitor(env).times(1)
17
+ @app.call(env).should.eq(env)
18
+ end
19
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rest-core
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.0
4
+ version: 1.0.1
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -10,7 +10,7 @@ authors:
10
10
  autorequire:
11
11
  bindir: bin
12
12
  cert_chain: []
13
- date: 2012-03-17 00:00:00.000000000 Z
13
+ date: 2012-05-14 00:00:00.000000000 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: rest-client
@@ -125,12 +125,14 @@ files:
125
125
  - test/test_builder.rb
126
126
  - test/test_client.rb
127
127
  - test/test_client_oauth1.rb
128
+ - test/test_default_query.rb
128
129
  - test/test_error_detector.rb
129
130
  - test/test_error_detector_http.rb
130
131
  - test/test_follow_redirect.rb
131
132
  - test/test_json_decode.rb
132
133
  - test/test_oauth1_header.rb
133
134
  - test/test_payload.rb
135
+ - test/test_timeout.rb
134
136
  - test/test_universal.rb
135
137
  - test/test_wrapper.rb
136
138
  homepage: https://github.com/cardinalblue/rest-core
@@ -153,7 +155,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
153
155
  version: '0'
154
156
  requirements: []
155
157
  rubyforge_project:
156
- rubygems_version: 1.8.19
158
+ rubygems_version: 1.8.24
157
159
  signing_key:
158
160
  specification_version: 3
159
161
  summary: Modular Ruby clients interface for REST APIs
@@ -162,12 +164,14 @@ test_files:
162
164
  - test/test_builder.rb
163
165
  - test/test_client.rb
164
166
  - test/test_client_oauth1.rb
167
+ - test/test_default_query.rb
165
168
  - test/test_error_detector.rb
166
169
  - test/test_error_detector_http.rb
167
170
  - test/test_follow_redirect.rb
168
171
  - test/test_json_decode.rb
169
172
  - test/test_oauth1_header.rb
170
173
  - test/test_payload.rb
174
+ - test/test_timeout.rb
171
175
  - test/test_universal.rb
172
176
  - test/test_wrapper.rb
173
177
  has_rdoc: