rest-core 0.8.2 → 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.travis.yml +4 -2
- data/CHANGES.md +130 -19
- data/Gemfile +4 -0
- data/README.md +147 -13
- data/TODO.md +0 -10
- data/doc/ToC.md +7 -0
- data/doc/dependency.md +4 -0
- data/doc/design.md +4 -0
- data/example/auto.rb +51 -0
- data/example/coolio.rb +21 -0
- data/example/eventmachine.rb +28 -0
- data/example/multi.rb +33 -0
- data/example/rest-client.rb +16 -0
- data/lib/rest-core/app/abstract/async_fiber.rb +13 -0
- data/lib/rest-core/app/auto.rb +22 -0
- data/lib/rest-core/app/coolio-async.rb +32 -0
- data/lib/rest-core/app/coolio-fiber.rb +30 -0
- data/lib/rest-core/app/coolio.rb +9 -0
- data/lib/rest-core/app/dry.rb +1 -0
- data/lib/rest-core/app/em-http-request-async.rb +34 -0
- data/lib/rest-core/app/em-http-request-fiber.rb +39 -0
- data/lib/rest-core/app/em-http-request.rb +9 -0
- data/lib/rest-core/app/rest-client.rb +24 -7
- data/lib/rest-core/client/universal.rb +3 -4
- data/lib/rest-core/client.rb +31 -4
- data/lib/rest-core/middleware/cache.rb +23 -5
- data/lib/rest-core/middleware/common_logger.rb +13 -3
- data/lib/rest-core/middleware/error_detector.rb +10 -1
- data/lib/rest-core/middleware/error_handler.rb +7 -1
- data/lib/rest-core/middleware/follow_redirect.rb +42 -0
- data/lib/rest-core/middleware/json_decode.rb +11 -2
- data/lib/rest-core/middleware/timeout/coolio_timer.rb +4 -0
- data/lib/rest-core/middleware/timeout/eventmachine_timer.rb +14 -0
- data/lib/rest-core/middleware/timeout.rb +73 -1
- data/lib/rest-core/middleware.rb +7 -0
- data/lib/rest-core/patch/rest-client.rb +35 -0
- data/lib/rest-core/version.rb +1 -1
- data/lib/rest-core.rb +19 -0
- data/rest-core.gemspec +28 -8
- data/test/test_client.rb +20 -3
- data/test/test_follow_redirect.rb +47 -0
- data/test/test_json_decode.rb +24 -0
- metadata +36 -11
- data/example/facebook.rb +0 -9
- data/example/github.rb +0 -4
- data/example/linkedin.rb +0 -8
- data/example/twitter.rb +0 -11
data/.travis.yml
CHANGED
@@ -1,4 +1,5 @@
|
|
1
|
-
|
1
|
+
before_install: 'git submodule update --init'
|
2
|
+
script: 'bundle exec rake test'
|
2
3
|
|
3
4
|
rvm:
|
4
5
|
- 1.8.7
|
@@ -6,4 +7,5 @@ rvm:
|
|
6
7
|
- 1.9.3
|
7
8
|
- rbx-18mode
|
8
9
|
- rbx-19mode
|
9
|
-
- jruby
|
10
|
+
- jruby-18mode
|
11
|
+
- jruby-19mode
|
data/CHANGES.md
CHANGED
@@ -1,33 +1,143 @@
|
|
1
1
|
# CHANGES
|
2
2
|
|
3
|
+
## rest-core 1.0.0 -- 2012-03-17
|
4
|
+
|
5
|
+
This is a very significant release. The most important change is now we
|
6
|
+
support asynchronous requests, by either passing a callback block or using
|
7
|
+
fibers in Ruby 1.9 to make the whole program still look synchronous.
|
8
|
+
|
9
|
+
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)
|
11
|
+
for more detail.
|
12
|
+
|
13
|
+
* [`Client`] Client#inspect is fixed for clients which do not have any
|
14
|
+
attributes.
|
15
|
+
|
16
|
+
* [`Client`] HEAD, OPTIONS, and PATCH requests are added. For example:
|
17
|
+
|
18
|
+
``` ruby
|
19
|
+
client = Client.new
|
20
|
+
client.head('path')
|
21
|
+
client.options('path')
|
22
|
+
client.patch('path')
|
23
|
+
```
|
24
|
+
|
25
|
+
* [`Client`] Now if you passed a block to either `get` or `post` or other
|
26
|
+
requests, the response would be returned to the block instead the caller.
|
27
|
+
In this case, the return value of `get` or `post` would be the client
|
28
|
+
itself. For example:
|
29
|
+
|
30
|
+
``` ruby
|
31
|
+
client = Client.new
|
32
|
+
client.get('path'){ |response| puts response.insepct }.
|
33
|
+
get('math'){ |response| puts response.insepct }
|
34
|
+
```
|
35
|
+
|
36
|
+
* [`RestClient`] Now all the response headers names are converted to upper
|
37
|
+
cases and underscores (_). Also, if a header has only presented once, it
|
38
|
+
would not be wrapped inside an array. This is more consistent with
|
39
|
+
em-http-request, cool.io-http, and http_parser.rb
|
40
|
+
|
41
|
+
* [`RestClient`] From now on, the default HTTP client, i.e. `RestClient` won't
|
42
|
+
follow any redirect. To follow redirect, please use `FollowRedirect`
|
43
|
+
middleware. Two reasons. One is that the underlying HTTP client should
|
44
|
+
be minimal. Another one is that a FollowRedirect middleware could be
|
45
|
+
used for all HTTP clients. This would make it more consistent across
|
46
|
+
all HTTP clients.
|
47
|
+
|
48
|
+
* [`RestClient`] Added a patch to avoid `"123".to_i` returning `200`,
|
49
|
+
please see: <https://github.com/archiloque/rest-client/pull/103>
|
50
|
+
I would remove this once after this patch is merged.
|
51
|
+
|
52
|
+
* [`RestClient`] Added a patch to properly returning response whenever
|
53
|
+
a redirect is happened. Please see:
|
54
|
+
<https://github.com/archiloque/rest-client/pull/118>
|
55
|
+
I would remove this once after this patch is merged.
|
56
|
+
|
57
|
+
* [`FollowRedirect`] This middleware would follow the redirect. Pass
|
58
|
+
:max_redirects for the maximum redirect times. For example:
|
59
|
+
|
60
|
+
``` ruby
|
61
|
+
Client = RestCore::Builder.client do
|
62
|
+
use FollowRedirect, 2 # default :max_redirects
|
63
|
+
end
|
64
|
+
client = Client.new
|
65
|
+
client.get('path', {}, :max_redirects => 5)
|
66
|
+
```
|
67
|
+
|
68
|
+
* [`Middleware`] Added `Middleware#run` which can return the underlying HTTP
|
69
|
+
client, if you need to know the underlying HTTP client can support
|
70
|
+
asynchronous requests or not.
|
71
|
+
|
72
|
+
* [`Cache`] Now it's asynchrony-aware.
|
73
|
+
* [`CommonLogger`] Now it's asynchrony-aware.
|
74
|
+
* [`ErrorDetector`] Now it's asynchrony-aware.
|
75
|
+
* [`ErrorHandler`] Now it's asynchrony-aware.
|
76
|
+
* [`JsonDecode`] Now it's asynchrony-aware.
|
77
|
+
* [`Timeout`] Now it's asynchrony-aware.
|
78
|
+
|
79
|
+
* [`Universal`] `FollowRedirect` middleware is added.
|
80
|
+
* [`Universal`] `Defaults` middleware is removed.
|
81
|
+
|
82
|
+
* Added `RestCore::ASYNC` which should be the callback function which is
|
83
|
+
called whenever the response is available. It's similar to Rack's
|
84
|
+
async.callback.
|
85
|
+
|
86
|
+
* Added `RestCore::TIMER` which is only used in Timeout middleware. We need
|
87
|
+
this to disable timer whenever the response is back.
|
88
|
+
|
89
|
+
* [`EmHttpRequestAsync`] This HTTP client accepts a block to make asynchronous
|
90
|
+
HTTP requests via em-http-request gem.
|
91
|
+
|
92
|
+
* [`EmHttpRequestFiber`] This HTTP client would make asynchronous HTTP
|
93
|
+
requests with em-http-request but also wrapped inside a fiber, so that it
|
94
|
+
looks synchronous to the program who calls it.
|
95
|
+
|
96
|
+
* [`EmHttpRequest`] This HTTP client would would use `EmHttpRequestAsync` if
|
97
|
+
a block (`RestCore::ASYNC`) is passed, otherwise use `EmHttpRequestFiber`.
|
98
|
+
|
99
|
+
* [`CoolioAsync`] This HTTP client is basically the same as
|
100
|
+
`EmHttpRequestAsync`, but using cool.io-http instead of em-http-request.
|
101
|
+
|
102
|
+
* [`CoolioFiber`] This HTTP client is basically the same as
|
103
|
+
`EmHttpRequestFiber`, but using cool.io-http instead of em-http-request.
|
104
|
+
|
105
|
+
* [`Coolio`] This HTTP client is basically the same as `EmHttpRequest`,
|
106
|
+
but using cool.io-http instead of em-http-request.
|
107
|
+
|
108
|
+
* [`Auto`] This HTTP client would auto-select a suitable client. Under
|
109
|
+
eventmachine, it would use `EmHttpRequest`. Under cool.io, it would use
|
110
|
+
`Coolio`. Otherwise, it would use `RestClient`.
|
111
|
+
|
3
112
|
## rest-core 0.8.2 -- 2012-02-18
|
4
113
|
|
5
114
|
### Enhancement
|
6
115
|
|
7
|
-
* [DefaultPayload] This middleware allows you to have default payload for
|
116
|
+
* [`DefaultPayload`] This middleware allows you to have default payload for
|
8
117
|
POST and PUT requests.
|
9
118
|
|
10
|
-
* [Client] Now `lighten` would give all Unserializable to nil instead of
|
119
|
+
* [`Client`] Now `lighten` would give all Unserializable to nil instead of
|
120
|
+
false
|
11
121
|
|
12
122
|
### Bugs fixes
|
13
123
|
|
14
|
-
* [ErrorDetector] Now it would do nothing instead of crashing if there's no
|
124
|
+
* [`ErrorDetector`] Now it would do nothing instead of crashing if there's no
|
15
125
|
any error_detector.
|
16
126
|
|
17
127
|
## rest-core 0.8.1 -- 2012-02-09
|
18
128
|
|
19
129
|
### Enhancement
|
20
130
|
|
21
|
-
* [Wrapper] Introducing `Wrapper.default_app` (also `Builder.default_app`)
|
131
|
+
* [`Wrapper`] Introducing `Wrapper.default_app` (also `Builder.default_app`)
|
22
132
|
which you can change the default app from `RestClient` to other HTTP
|
23
133
|
clients.
|
24
134
|
|
25
135
|
### Bugs fixes
|
26
136
|
|
27
|
-
* [OAuth1Header] Correctly handle the signature when it comes to multipart
|
137
|
+
* [`OAuth1Header`] Correctly handle the signature when it comes to multipart
|
28
138
|
requests.
|
29
139
|
|
30
|
-
* [ErrorDetectorHttp] Fixed argument error upon calling `lighten` for
|
140
|
+
* [`ErrorDetectorHttp`] Fixed argument error upon calling `lighten` for
|
31
141
|
clients using this middleware. (e.g. rest-more's Twitter client)
|
32
142
|
|
33
143
|
## rest-core 0.8.0 -- 2011-11-29
|
@@ -36,16 +146,16 @@ Changes are mostly related to OAuth.
|
|
36
146
|
|
37
147
|
### Incompatible changes
|
38
148
|
|
39
|
-
* [OAuth1Header] `callback` is renamed to `oauth_callback`
|
40
|
-
* [OAuth1Header] `verifier` is renamed to `oauth_verifier`
|
149
|
+
* [`OAuth1Header`] `callback` is renamed to `oauth_callback`
|
150
|
+
* [`OAuth1Header`] `verifier` is renamed to `oauth_verifier`
|
41
151
|
|
42
|
-
* [Oauth2Header] The first argument is changed from `access_token` to
|
152
|
+
* [`Oauth2Header`] The first argument is changed from `access_token` to
|
43
153
|
`access_token_type`. Previously, the access_token_type is "OAuth" which
|
44
154
|
is used in Mixi. But mostly, we might want to use "Bearer" (according to
|
45
155
|
[OAuth 2.0 spec][]) Argument for the access_token is changed to the second
|
46
156
|
argument.
|
47
157
|
|
48
|
-
* [Defaults] Now we're no longer call `call` for any default values.
|
158
|
+
* [`Defaults`] Now we're no longer call `call` for any default values.
|
49
159
|
That is, if you're using this: `use s::Defaults, :data => lambda{{}}`
|
50
160
|
that would break. Previously, this middleware would call `call` on the
|
51
161
|
lambda so that `data` is default to a newly created hash. Now, it would
|
@@ -57,35 +167,36 @@ Changes are mostly related to OAuth.
|
|
57
167
|
|
58
168
|
### Enhancement
|
59
169
|
|
60
|
-
* [AuthBasic] Added a new middleware which could do
|
170
|
+
* [`AuthBasic`] Added a new middleware which could do
|
171
|
+
[basic authentication][].
|
61
172
|
|
62
|
-
* [OAuth1Header] Introduced `data` which is a hash and is used to store
|
173
|
+
* [`OAuth1Header`] Introduced `data` which is a hash and is used to store
|
63
174
|
tokens and other information sent from authorization servers.
|
64
175
|
|
65
|
-
* [ClientOauth1] Now `authorize_url!` accepts opts which you can pass
|
176
|
+
* [`ClientOauth1`] Now `authorize_url!` accepts opts which you can pass
|
66
177
|
`authorize_url!(:oauth_callback => 'http://localhost/callback')`.
|
67
178
|
|
68
|
-
* [ClientOauth1] Introduced `authorize_url` which would not try to ask
|
179
|
+
* [`ClientOauth1`] Introduced `authorize_url` which would not try to ask
|
69
180
|
for a request token, instead, it would use the current token as the
|
70
181
|
request token. If you don't understand what does this mean, then keep
|
71
182
|
using `authorize_url!`, which would call this underneath.
|
72
183
|
|
73
|
-
* [ClientOauth1] Introduced `authorized?`
|
74
|
-
* [ClientOauth1] Now it would set `data['authorized'] = 'true'` when
|
184
|
+
* [`ClientOauth1`] Introduced `authorized?`
|
185
|
+
* [`ClientOauth1`] Now it would set `data['authorized'] = 'true'` when
|
75
186
|
`authorize!` is called, and it is also used to check if we're authorized
|
76
187
|
or not in `authorized?`
|
77
188
|
|
78
|
-
* [ClientOauth1] Introduced `data_json` and `data_json=` which allow you to
|
189
|
+
* [`ClientOauth1`] Introduced `data_json` and `data_json=` which allow you to
|
79
190
|
serialize and deserialize `data` with JSON along with a `sig` to check
|
80
191
|
if it hasn't been changed. You can put this into browser cookie. Because
|
81
192
|
of the `sig`, you would know if the user changed something in data without
|
82
193
|
using `consumer_secret` to generate a correct sig corresponded to the data.
|
83
194
|
|
84
|
-
* [ClientOauth1] Introduced `oauth_token`, `oauth_token=`,
|
195
|
+
* [`ClientOauth1`] Introduced `oauth_token`, `oauth_token=`,
|
85
196
|
`oauth_token_secret`, `oauth_token_secret=`, `oauth_callback`,
|
86
197
|
and `oauth_callback=` which take the advantage of `data`.
|
87
198
|
|
88
|
-
* [ClientOauth1] Introduced `default_data` which is a hash.
|
199
|
+
* [`ClientOauth1`] Introduced `default_data` which is a hash.
|
89
200
|
|
90
201
|
[basic authentication]: http://en.wikipedia.org/wiki/Basic_access_authentication
|
91
202
|
|
data/Gemfile
CHANGED
@@ -3,6 +3,9 @@ source 'http://rubygems.org'
|
|
3
3
|
|
4
4
|
gemspec
|
5
5
|
|
6
|
+
gem 'rest-client'
|
7
|
+
gem 'em-http-request'
|
8
|
+
|
6
9
|
gem 'rake'
|
7
10
|
gem 'bacon'
|
8
11
|
gem 'rr'
|
@@ -16,6 +19,7 @@ gem 'ruby-hmac'
|
|
16
19
|
|
17
20
|
platforms(:ruby) do
|
18
21
|
gem 'yajl-ruby'
|
22
|
+
gem 'cool.io-http'
|
19
23
|
end
|
20
24
|
|
21
25
|
platforms(:jruby) do
|
data/README.md
CHANGED
@@ -1,9 +1,12 @@
|
|
1
|
-
# rest-core [![Build Status](
|
1
|
+
# rest-core [![Build Status](https://secure.travis-ci.org/godfat/rest-core.png?branch=master)](http://travis-ci.org/godfat/rest-core)
|
2
2
|
|
3
3
|
by Cardinal Blue <http://cardinalblue.com>
|
4
4
|
|
5
|
-
Lin Jen-Shin ([godfat][]) had given a talk about rest-core on
|
6
|
-
The slide is in English, but the
|
5
|
+
Lin Jen-Shin ([godfat][]) had given a talk about rest-core on
|
6
|
+
[RubyConf Taiwan 2011][talk]. The slide is in English, but the
|
7
|
+
talk is in Mandarin.
|
8
|
+
|
9
|
+
You can also read some other topics at [doc](https://github.com/cardinalblue/rest-core/blob/master/doc/ToC.md).
|
7
10
|
|
8
11
|
[godfat]: https://github.com/godfat
|
9
12
|
[talk]: http://rubyconf.tw/2011/#6
|
@@ -26,13 +29,30 @@ that allows you to build a REST client for any REST API. Or in the case of
|
|
26
29
|
common APIs such as Facebook, Github, and Twitter, you can simply use the
|
27
30
|
dedicated clients provided by [rest-more][].
|
28
31
|
|
29
|
-
[rest-core]:
|
30
|
-
[rest-more]:
|
32
|
+
[rest-core]: https://github.com/cardinalblue/rest-core
|
33
|
+
[rest-more]: https://github.com/cardinalblue/rest-more
|
34
|
+
|
35
|
+
## FEATURES:
|
36
|
+
|
37
|
+
* Modular interface for REST clients similar to WSGI/Rack for servers.
|
38
|
+
* Asynchronous/Synchronous styles with or without fibers are both supported.
|
31
39
|
|
32
40
|
## REQUIREMENTS:
|
33
41
|
|
34
|
-
|
35
|
-
|
42
|
+
### Mandatory:
|
43
|
+
|
44
|
+
* MRI (official CRuby) 1.8.7, 1.9.2, 1.9.3, Rubinius 1.8/1.9 and JRuby 1.8/1.9
|
45
|
+
* gem rest-client
|
46
|
+
|
47
|
+
### Optional:
|
48
|
+
|
49
|
+
* Fibers only work on Ruby 1.9+
|
50
|
+
* gem [em-http-request][] (if using eventmachine)
|
51
|
+
* gem [cool.io-http][] (if using cool.io)
|
52
|
+
* gem json or yajl-ruby (if using JsonDecode middleware)
|
53
|
+
|
54
|
+
[em-http-request]: https://github.com/igrigorik/em-http-request
|
55
|
+
[cool.io-http]: https://github.com/godfat/cool.io-http
|
36
56
|
|
37
57
|
## INSTALLATION:
|
38
58
|
|
@@ -40,8 +60,10 @@ dedicated clients provided by [rest-more][].
|
|
40
60
|
|
41
61
|
Or if you want development version, put this in Gemfile:
|
42
62
|
|
63
|
+
``` ruby
|
43
64
|
gem 'rest-core', :git => 'git://github.com/cardinalblue/rest-core.git',
|
44
65
|
:submodules => true
|
66
|
+
```
|
45
67
|
|
46
68
|
If you just want to use Facebook or Twitter clients, please take a look at
|
47
69
|
[rest-more][] which has a lot of clients built with rest-core.
|
@@ -50,6 +72,9 @@ If you just want to use Facebook or Twitter clients, please take a look at
|
|
50
72
|
|
51
73
|
## Build Your Own Clients:
|
52
74
|
|
75
|
+
You can use `RestCore::Builder` to build your own dedicated client:
|
76
|
+
|
77
|
+
``` ruby
|
53
78
|
require 'rest-core'
|
54
79
|
|
55
80
|
YourClient = RestCore::Builder.client do
|
@@ -57,31 +82,140 @@ If you just want to use Facebook or Twitter clients, please take a look at
|
|
57
82
|
use s::DefaultSite , 'https://api.github.com/users/'
|
58
83
|
use s::JsonDecode , true
|
59
84
|
use s::CommonLogger, method(:puts)
|
60
|
-
use s::Cache ,
|
61
|
-
run s::RestClient
|
85
|
+
use s::Cache , nil, 3600
|
86
|
+
run s::RestClient # the simplest and easier HTTP client
|
62
87
|
end
|
88
|
+
```
|
63
89
|
|
64
|
-
|
90
|
+
And use it with per-instance basis (clients could have different
|
91
|
+
configuration, e.g. different cache time or timeout time):
|
92
|
+
|
93
|
+
``` ruby
|
94
|
+
client = YourClient.new(:cache => {})
|
65
95
|
client.get('cardinalblue') # cache miss
|
66
96
|
client.get('cardinalblue') # cache hit
|
67
97
|
|
68
98
|
client.site = 'http://github.com/api/v2/json/user/show/'
|
69
99
|
client.get('cardinalblue') # cache miss
|
70
100
|
client.get('cardinalblue') # cache hit
|
101
|
+
```
|
71
102
|
|
72
|
-
Please see [rest-more][]
|
73
|
-
and [slides][] from [rubyconf.tw/2011][rubyconf.tw]
|
103
|
+
Runnable example is here: [example/rest-client.rb][]. Please see [rest-more][]
|
104
|
+
for more complex examples, and [slides][] from [rubyconf.tw/2011][rubyconf.tw]
|
105
|
+
for concepts.
|
74
106
|
|
107
|
+
[example/rest-client.rb]: https://github.com/cardinalblue/rest-core/blob/master/example/rest-client.rb
|
75
108
|
[rest-more]: https://github.com/cardinalblue/rest-more
|
76
109
|
[rubyconf.tw]: http://rubyconf.tw/2011/#6
|
77
110
|
[slides]: http://www.godfat.org/slide/2011-08-27-rest-core.html
|
78
111
|
|
112
|
+
## Asynchronous HTTP Requests:
|
113
|
+
|
114
|
+
I/O bound operations shouldn't be blocking the CPU! If you have a reactor,
|
115
|
+
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
|
117
|
+
cool.io. Below is an example for eventmachine:
|
118
|
+
|
119
|
+
``` ruby
|
120
|
+
require 'rest-core'
|
121
|
+
|
122
|
+
AsynchronousClient = RestCore::Builder.client do
|
123
|
+
s = self.class # this is only for ruby 1.8!
|
124
|
+
use s::DefaultSite , 'https://api.github.com/users/'
|
125
|
+
use s::JsonDecode , true
|
126
|
+
use s::CommonLogger, method(:puts)
|
127
|
+
use s::Cache , nil, 3600
|
128
|
+
run s::EmHttpRequest
|
129
|
+
end
|
130
|
+
```
|
131
|
+
|
132
|
+
If you're passing a block, the block is called after the response is
|
133
|
+
available. That is the block is the callback for the request.
|
134
|
+
|
135
|
+
``` ruby
|
136
|
+
client = AsynchronousClient.new(:cache => {})
|
137
|
+
EM.run{
|
138
|
+
client.get('cardinalblue'){ |response|
|
139
|
+
p response
|
140
|
+
EM.stop
|
141
|
+
}
|
142
|
+
}
|
143
|
+
```
|
144
|
+
|
145
|
+
Otherwise, if you don't pass a block as the callback, EmHttpRequest (i.e.
|
146
|
+
the HTTP client for eventmachine) would call `Fiber.yield` to yield to the
|
147
|
+
original fiber, making asynchronous HTTP requests look like synchronous.
|
148
|
+
If you don't understand what does this mean, you can take a look at
|
149
|
+
[em-synchrony][]. It's basically the same idea.
|
150
|
+
|
151
|
+
``` ruby
|
152
|
+
EM.run{
|
153
|
+
Fiber.new{
|
154
|
+
p client.get('cardinalblue')
|
155
|
+
EM.stop
|
156
|
+
}.resume
|
157
|
+
}
|
158
|
+
```
|
159
|
+
|
160
|
+
[em-synchrony]: https://github.com/igrigorik/em-synchrony
|
161
|
+
|
162
|
+
Runnable example is here: [example/eventmachine.rb][].
|
163
|
+
You can also make multi-requests synchronously like this:
|
164
|
+
|
165
|
+
``` ruby
|
166
|
+
EM.run{
|
167
|
+
Fiber.new{
|
168
|
+
fiber = Fiber.current
|
169
|
+
result = {}
|
170
|
+
client.get('cardinalblue'){ |response|
|
171
|
+
result[0] = response
|
172
|
+
fiber.resume(result) if result.size == 2
|
173
|
+
}
|
174
|
+
client.get('cardinalblue'){ |response|
|
175
|
+
result[1] = response
|
176
|
+
fiber.resume(result) if result.size == 2
|
177
|
+
}
|
178
|
+
p Fiber.yield
|
179
|
+
EM.stop
|
180
|
+
}.resume
|
181
|
+
}
|
182
|
+
```
|
183
|
+
|
184
|
+
Runnable example is here: [example/multi.rb][].
|
185
|
+
|
186
|
+
[example/eventmachine.rb]: https://github.com/cardinalblue/rest-core/blob/master/example/eventmachine.rb
|
187
|
+
[example/multi.rb]: https://github.com/cardinalblue/rest-core/blob/master/example/multi.rb
|
188
|
+
|
189
|
+
## Supported HTTP clients:
|
190
|
+
|
191
|
+
* `RestCore::RestClient` (gem rest-client)
|
192
|
+
* `RestCore::EmHttpRequest` (gem em-http-request)
|
193
|
+
* `RestCore::Coolio` (gem cool.io)
|
194
|
+
* `RestCore::Auto` (which would pick one of the above depending on the
|
195
|
+
context)
|
196
|
+
|
197
|
+
## Build Your Own Middlewares:
|
198
|
+
|
199
|
+
To be added.
|
200
|
+
|
201
|
+
## Build Your Own HTTP clients:
|
202
|
+
|
203
|
+
To be added.
|
204
|
+
|
79
205
|
## rest-core users:
|
80
206
|
|
81
207
|
* [topcoder](https://github.com/miaout17/topcoder)
|
82
208
|
* [s2sync](https://github.com/brucehsu/s2sync)
|
83
209
|
* [s2sync_web](https://github.com/brucehsu/s2sync_web)
|
84
210
|
|
211
|
+
## Powered sites:
|
212
|
+
|
213
|
+
* [PicCollage](http://pic-collage.com/)
|
214
|
+
|
215
|
+
## CHANGES:
|
216
|
+
|
217
|
+
* [CHANGES](https://github.com/cardinalblue/rest-core/blob/master/CHANGES.md)
|
218
|
+
|
85
219
|
## GLOSSARY:
|
86
220
|
|
87
221
|
* A _client_ is a class which can new connections to make requests.
|
@@ -184,7 +318,7 @@ and [slides][] from [rubyconf.tw/2011][rubyconf.tw] for concepts.
|
|
184
318
|
|
185
319
|
Apache License 2.0
|
186
320
|
|
187
|
-
Copyright (c) 2011, Cardinal Blue
|
321
|
+
Copyright (c) 2011-2012, Cardinal Blue
|
188
322
|
|
189
323
|
Licensed under the Apache License, Version 2.0 (the "License");
|
190
324
|
you may not use this file except in compliance with the License.
|
data/TODO.md
CHANGED
data/doc/ToC.md
ADDED
data/doc/dependency.md
ADDED
data/doc/design.md
ADDED
data/example/auto.rb
ADDED
@@ -0,0 +1,51 @@
|
|
1
|
+
|
2
|
+
require 'rest-core'
|
3
|
+
require 'eventmachine'
|
4
|
+
require 'cool.io'
|
5
|
+
|
6
|
+
YourClient = RestCore::Builder.client do
|
7
|
+
s = self.class # this is only for ruby 1.8!
|
8
|
+
use s::DefaultSite , 'https://api.github.com/users/'
|
9
|
+
use s::JsonDecode , true
|
10
|
+
use s::CommonLogger, method(:puts)
|
11
|
+
use s::Cache , nil, 3600
|
12
|
+
run s::Auto
|
13
|
+
end
|
14
|
+
|
15
|
+
client = YourClient.new(:cache => {})
|
16
|
+
p client.get('cardinalblue') # cache miss
|
17
|
+
puts
|
18
|
+
p client.get('cardinalblue') # cache hit
|
19
|
+
|
20
|
+
puts
|
21
|
+
|
22
|
+
client = YourClient.new(:cache => {})
|
23
|
+
EM.run{
|
24
|
+
client.get('cardinalblue'){ |response|
|
25
|
+
p response
|
26
|
+
EM.stop
|
27
|
+
}
|
28
|
+
}
|
29
|
+
|
30
|
+
puts
|
31
|
+
|
32
|
+
EM.run{
|
33
|
+
Fiber.new{
|
34
|
+
p client.get('cardinalblue')
|
35
|
+
EM.stop
|
36
|
+
}.resume
|
37
|
+
}
|
38
|
+
|
39
|
+
puts
|
40
|
+
|
41
|
+
client = YourClient.new(:cache => {})
|
42
|
+
Coolio::TimerWatcher.new(1).attach(Coolio::Loop.default).on_timer{detach}
|
43
|
+
client.get('cardinalblue'){ |response|
|
44
|
+
p response
|
45
|
+
}
|
46
|
+
Coolio::Loop.default.run
|
47
|
+
|
48
|
+
puts
|
49
|
+
Coolio::TimerWatcher.new(1).attach(Coolio::Loop.default).on_timer{detach}
|
50
|
+
Fiber.new{ p client.get('cardinalblue') }.resume
|
51
|
+
Coolio::Loop.default.run
|
data/example/coolio.rb
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
|
2
|
+
require 'rest-core'
|
3
|
+
|
4
|
+
AsynchronousClient = RestCore::Builder.client do
|
5
|
+
s = self.class # this is only for ruby 1.8!
|
6
|
+
use s::DefaultSite , 'https://api.github.com/users/'
|
7
|
+
use s::JsonDecode , true
|
8
|
+
use s::CommonLogger, method(:puts)
|
9
|
+
use s::Cache , nil, 3600
|
10
|
+
run s::Coolio
|
11
|
+
end
|
12
|
+
|
13
|
+
AsynchronousClient.new.get('cardinalblue'){ |response|
|
14
|
+
p response
|
15
|
+
}
|
16
|
+
Coolio::Loop.default.run
|
17
|
+
|
18
|
+
puts
|
19
|
+
|
20
|
+
Fiber.new{ p AsynchronousClient.new.get('cardinalblue') }.resume
|
21
|
+
Coolio::Loop.default.run
|
@@ -0,0 +1,28 @@
|
|
1
|
+
|
2
|
+
require 'rest-core'
|
3
|
+
|
4
|
+
AsynchronousClient = RestCore::Builder.client do
|
5
|
+
s = self.class # this is only for ruby 1.8!
|
6
|
+
use s::DefaultSite , 'https://api.github.com/users/'
|
7
|
+
use s::JsonDecode , true
|
8
|
+
use s::CommonLogger, method(:puts)
|
9
|
+
use s::Cache , nil, 3600
|
10
|
+
run s::EmHttpRequest
|
11
|
+
end
|
12
|
+
|
13
|
+
client = AsynchronousClient.new(:cache => {})
|
14
|
+
EM.run{
|
15
|
+
client.get('cardinalblue'){ |response|
|
16
|
+
p response
|
17
|
+
EM.stop
|
18
|
+
}
|
19
|
+
}
|
20
|
+
|
21
|
+
puts
|
22
|
+
|
23
|
+
EM.run{
|
24
|
+
Fiber.new{
|
25
|
+
p client.get('cardinalblue')
|
26
|
+
EM.stop
|
27
|
+
}.resume
|
28
|
+
}
|
data/example/multi.rb
ADDED
@@ -0,0 +1,33 @@
|
|
1
|
+
|
2
|
+
require 'rest-core'
|
3
|
+
require 'eventmachine'
|
4
|
+
RestCore::EmHttpRequest # there might be a autoload bug?
|
5
|
+
# omitting this line would cause
|
6
|
+
# stack level too deep (SystemStackError)
|
7
|
+
|
8
|
+
YourClient = RestCore::Builder.client do
|
9
|
+
s = self.class # this is only for ruby 1.8!
|
10
|
+
use s::DefaultSite , 'https://api.github.com/users/'
|
11
|
+
use s::JsonDecode , true
|
12
|
+
use s::CommonLogger, method(:puts)
|
13
|
+
use s::Cache , nil, 3600
|
14
|
+
run s::Auto
|
15
|
+
end
|
16
|
+
|
17
|
+
client = YourClient.new
|
18
|
+
EM.run{
|
19
|
+
Fiber.new{
|
20
|
+
fiber = Fiber.current
|
21
|
+
result = {}
|
22
|
+
client.get('cardinalblue'){ |response|
|
23
|
+
result[0] = response
|
24
|
+
fiber.resume(result) if result.size == 2
|
25
|
+
}
|
26
|
+
client.get('cardinalblue'){ |response|
|
27
|
+
result[1] = response
|
28
|
+
fiber.resume(result) if result.size == 2
|
29
|
+
}
|
30
|
+
p Fiber.yield
|
31
|
+
EM.stop
|
32
|
+
}.resume
|
33
|
+
}
|
@@ -0,0 +1,16 @@
|
|
1
|
+
|
2
|
+
require 'rest-core'
|
3
|
+
|
4
|
+
YourClient = RestCore::Builder.client do
|
5
|
+
s = self.class # this is only for ruby 1.8!
|
6
|
+
use s::DefaultSite , 'https://api.github.com/users/'
|
7
|
+
use s::JsonDecode , true
|
8
|
+
use s::CommonLogger, method(:puts)
|
9
|
+
use s::Cache , nil, 3600
|
10
|
+
run s::RestClient
|
11
|
+
end
|
12
|
+
|
13
|
+
client = YourClient.new(:cache => {})
|
14
|
+
p client.get('cardinalblue') # cache miss
|
15
|
+
puts
|
16
|
+
p client.get('cardinalblue') # cache hit
|