rest-core 2.1.2 → 3.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +1 -2
- data/.travis.yml +3 -5
- data/CHANGES.md +65 -5
- data/Gemfile +10 -5
- data/NOTE.md +1 -1
- data/README.md +194 -128
- data/Rakefile +8 -34
- data/TODO.md +3 -2
- data/example/simple.rb +6 -4
- data/example/use-cases.rb +39 -122
- data/lib/rest-core.rb +14 -5
- data/lib/rest-core/builder.rb +12 -2
- data/lib/rest-core/client.rb +31 -25
- data/lib/rest-core/engine.rb +39 -0
- data/lib/rest-core/engine/http-client.rb +41 -0
- data/lib/rest-core/engine/net-http-persistent.rb +21 -0
- data/lib/rest-core/engine/rest-client.rb +13 -42
- data/lib/rest-core/event_source.rb +91 -0
- data/lib/rest-core/middleware.rb +17 -11
- data/lib/rest-core/middleware/error_detector.rb +1 -6
- data/lib/rest-core/middleware/oauth1_header.rb +1 -0
- data/lib/rest-core/middleware/oauth2_header.rb +20 -8
- data/lib/rest-core/middleware/oauth2_query.rb +1 -0
- data/lib/rest-core/middleware/timeout.rb +5 -19
- data/lib/rest-core/promise.rb +137 -0
- data/lib/rest-core/test.rb +2 -43
- data/lib/rest-core/thread_pool.rb +122 -0
- data/lib/rest-core/timer.rb +30 -0
- data/lib/rest-core/util/hmac.rb +0 -8
- data/lib/rest-core/version.rb +1 -1
- data/lib/rest-core/wrapper.rb +1 -1
- data/rest-core.gemspec +36 -25
- data/task/README.md +54 -0
- data/task/gemgem.rb +150 -156
- data/test/test_builder.rb +2 -2
- data/test/test_cache.rb +8 -8
- data/test/test_client.rb +16 -6
- data/test/test_client_oauth1.rb +1 -1
- data/test/test_event_source.rb +77 -0
- data/test/test_follow_redirect.rb +1 -1
- data/test/test_future.rb +16 -0
- data/test/test_oauth2_header.rb +28 -0
- data/test/test_promise.rb +89 -0
- data/test/test_rest-client.rb +21 -0
- data/test/test_thread_pool.rb +10 -0
- data/test/test_timeout.rb +13 -8
- metadata +61 -37
- data/example/multi.rb +0 -44
- data/lib/rest-core/engine/auto.rb +0 -25
- data/lib/rest-core/engine/em-http-request.rb +0 -90
- data/lib/rest-core/engine/future/future.rb +0 -107
- data/lib/rest-core/engine/future/future_fiber.rb +0 -32
- data/lib/rest-core/engine/future/future_thread.rb +0 -29
- data/lib/rest-core/middleware/timeout/timer_em.rb +0 -26
- data/lib/rest-core/middleware/timeout/timer_thread.rb +0 -36
- data/task/.gitignore +0 -1
- data/test/test_em-http-request.rb +0 -186
data/Rakefile
CHANGED
@@ -1,41 +1,15 @@
|
|
1
|
-
# encoding: utf-8
|
2
1
|
|
3
2
|
begin
|
4
3
|
require "#{dir = File.dirname(__FILE__)}/task/gemgem"
|
5
4
|
rescue LoadError
|
6
|
-
sh
|
7
|
-
exec Gem.ruby,
|
5
|
+
sh 'git submodule update --init'
|
6
|
+
exec Gem.ruby, '-S', $PROGRAM_NAME, *ARGV
|
8
7
|
end
|
9
8
|
|
10
|
-
Gemgem.dir
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
require 'rest-core/version'
|
17
|
-
s.name = 'rest-core'
|
18
|
-
s.version = RestCore::VERSION
|
19
|
-
s.homepage = 'https://github.com/cardinalblue/rest-core'
|
20
|
-
|
21
|
-
%w[rest-client].each{ |g| s.add_runtime_dependency(g) }
|
22
|
-
|
23
|
-
s.authors = ['Cardinal Blue', 'Lin Jen-Shin (godfat)']
|
24
|
-
s.email = ['dev (XD) cardinalblue.com']
|
25
|
-
|
26
|
-
s.post_install_message = <<-MARKDOWN
|
27
|
-
# [rest-core] Since 2.1.0, Incompatible changes for POST requests:
|
28
|
-
|
29
|
-
* We no longer support Rails-like POST payload, like translating
|
30
|
-
`{:foo => [1, 2]}` to `'foo[]=1&foo[]=2'`. It would now be translated to
|
31
|
-
`'foo=1&foo=2'`. If you like `'foo[]'` as the key, simply pass it as
|
32
|
-
`{'foo[]' => [1, 2]}`.
|
33
|
-
|
34
|
-
* This also applies to nested hashes like `{:foo => {:bar => 1}`. If you
|
35
|
-
want that behaviour, just pass `{'foo[bar]' => 1}` which would then be
|
36
|
-
translated to `'foo[bar]=1'`.
|
37
|
-
MARKDOWN
|
38
|
-
end
|
39
|
-
|
40
|
-
Gemgem.write
|
9
|
+
Gemgem.init(dir) do |s|
|
10
|
+
require 'rest-core/version'
|
11
|
+
s.name = 'rest-core'
|
12
|
+
s.version = RestCore::VERSION
|
13
|
+
s.homepage = 'https://github.com/godfat/rest-core'
|
14
|
+
%w[httpclient mime-types timers].each{ |g| s.add_runtime_dependency(g) }
|
41
15
|
end
|
data/TODO.md
CHANGED
@@ -1,8 +1,6 @@
|
|
1
1
|
# TODO
|
2
2
|
|
3
3
|
* middleware revisit (how to initialize?)
|
4
|
-
* streaming?
|
5
|
-
* connection pool?
|
6
4
|
* X-Method-Override
|
7
5
|
|
8
6
|
# BUG
|
@@ -15,3 +13,6 @@
|
|
15
13
|
* headers and payload logs for CommonLogger
|
16
14
|
|
17
15
|
# rest-request
|
16
|
+
|
17
|
+
* fix DRY by defining `prepare :: env -> env`
|
18
|
+
* FAIL and LOG need to be reimplemented as well.
|
data/example/simple.rb
CHANGED
@@ -8,21 +8,23 @@ YourClient = RC::Builder.client do
|
|
8
8
|
use RC::Cache , nil, 3600
|
9
9
|
end
|
10
10
|
|
11
|
+
YourClient.pool_size = 5
|
12
|
+
|
11
13
|
client = YourClient.new(:cache => {})
|
12
|
-
p client.get('
|
14
|
+
p client.get('godfat') # cache miss
|
13
15
|
puts
|
14
|
-
p client.get('
|
16
|
+
p client.get('godfat') # cache hit
|
15
17
|
|
16
18
|
client.cache = false
|
17
19
|
|
18
20
|
puts "concurrent requests"
|
19
|
-
a = [client.get('
|
21
|
+
a = [client.get('godfat'), client.get('cardinalblue')]
|
20
22
|
puts "It's not blocking... but doing concurrent requests underneath"
|
21
23
|
p a.map{ |r| r['name'] } # here we want the values, so it blocks here
|
22
24
|
puts "DONE"
|
23
25
|
|
24
26
|
puts "callback"
|
25
|
-
client.get('
|
27
|
+
client.get('godfat'){ |v| p v }
|
26
28
|
puts "It's not blocking... but doing concurrent requests underneath"
|
27
29
|
client.wait # we block here to wait for the request done
|
28
30
|
puts "DONE"
|
data/example/use-cases.rb
CHANGED
@@ -1,11 +1,17 @@
|
|
1
1
|
|
2
|
-
require 'fiber'
|
3
|
-
require 'em-http-request'
|
4
2
|
require 'rest-core'
|
5
3
|
RC.eagerload
|
6
4
|
|
5
|
+
RC::Universal.pool_size = 0 # default to no thread pool
|
6
|
+
|
7
7
|
def def_use_case name, &block
|
8
|
-
singleton_class.send(:define_method, "#{name}_"
|
8
|
+
singleton_class.send(:define_method, "#{name}_") do
|
9
|
+
begin
|
10
|
+
yield
|
11
|
+
rescue => e
|
12
|
+
q "Encountering: #{e}"
|
13
|
+
end
|
14
|
+
end
|
9
15
|
singleton_class.send(:define_method, name) do
|
10
16
|
@count ||= 0
|
11
17
|
printf "Use case #%02d: %s\n", @count+=1, name
|
@@ -30,29 +36,37 @@ end
|
|
30
36
|
|
31
37
|
def_use_case 'pure_ruby_single_request' do
|
32
38
|
q RC::Universal.new(:json_response => true).
|
33
|
-
get('https://
|
39
|
+
get('https://graph.facebook.com/4')['name']
|
34
40
|
end
|
35
41
|
|
36
42
|
def_use_case 'pure_ruby_concurrent_requests' do
|
37
43
|
client = RC::Universal.new(:json_response => true,
|
38
|
-
:site => 'https://
|
39
|
-
q [client.get('
|
44
|
+
:site => 'https://graph.facebook.com/')
|
45
|
+
q [client.get('4'), client.get('5')].map{ |u| u['name'] }
|
40
46
|
end
|
41
47
|
|
42
48
|
def_use_case 'pure_ruby_cache_requests' do
|
43
49
|
client = RC::Universal.new(:json_response => true, :cache => {})
|
44
|
-
3.times{ q client.get('https://
|
50
|
+
3.times{ q client.get('https://graph.facebook.com/4')['name'] }
|
45
51
|
end
|
46
52
|
|
47
53
|
def_use_case 'pure_ruby_callback_requests' do
|
48
54
|
m = Mutex.new
|
49
55
|
RC::Universal.new(:json_response => true ,
|
50
|
-
:site => 'https://
|
56
|
+
:site => 'https://graph.facebook.com/' ,
|
51
57
|
:log_method => lambda{|str| m.synchronize{puts(str)}}).
|
52
|
-
get('
|
58
|
+
get('4'){ |res|
|
59
|
+
if res.kind_of?(Exception)
|
60
|
+
p "Encountering: #{res}"
|
61
|
+
next
|
62
|
+
end
|
53
63
|
q res['name'], m
|
54
64
|
}.
|
55
|
-
get('
|
65
|
+
get('5'){ |res|
|
66
|
+
if res.kind_of?(Exception)
|
67
|
+
p "Encountering: #{res}"
|
68
|
+
next
|
69
|
+
end
|
56
70
|
q res['name'], m
|
57
71
|
}.wait
|
58
72
|
end
|
@@ -60,30 +74,26 @@ end
|
|
60
74
|
def_use_case 'pure_ruby_nested_concurrent_requests' do
|
61
75
|
m = Mutex.new
|
62
76
|
c = RC::Universal.new(:json_response => true ,
|
63
|
-
:site => 'https://
|
77
|
+
:site => 'https://graph.facebook.com/' ,
|
64
78
|
:log_method => lambda{|str| m.synchronize{puts(str)}})
|
65
79
|
|
66
|
-
%w[
|
67
|
-
c.get(
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
watch_contri = c.get("/repos/#{user}/#{most_watched}/contributors")
|
74
|
-
size_contri = c.get("/repos/#{user}/#{most_size}/contributors")
|
80
|
+
%w[4 5].each{ |user|
|
81
|
+
c.get(user, :fields => 'cover'){ |data|
|
82
|
+
if data.kind_of?(Exception)
|
83
|
+
q "Encountering: #{data}", m
|
84
|
+
next
|
85
|
+
end
|
75
86
|
|
76
|
-
|
77
|
-
|
87
|
+
cover = data['cover']
|
88
|
+
comments = c.get("#{cover['id']}/comments")
|
89
|
+
likes = c.get("#{cover['id']}/likes")
|
90
|
+
most_liked_comment = comments['data'].max_by{|d|d['like_count']}
|
78
91
|
|
79
|
-
|
80
|
-
|
92
|
+
q "Author of most liked comment from #{user}'s cover photo:", m
|
93
|
+
q most_liked_comment['from']['name'], m
|
81
94
|
|
82
|
-
|
83
|
-
q
|
84
|
-
|
85
|
-
q "Most contributed user for most size : #{user}/#{most_size}:", m
|
86
|
-
q most_size_most_contri['login'], m
|
95
|
+
y = !!likes['data'].find{|d|d['id'] == most_liked_comment['from']['id']}
|
96
|
+
q "Did the user also like the cover?: #{y}", m
|
87
97
|
}
|
88
98
|
}
|
89
99
|
|
@@ -92,72 +102,6 @@ end
|
|
92
102
|
|
93
103
|
# ----------------------------------------------------------------------
|
94
104
|
|
95
|
-
def_use_case 'eventmachine_fiber_single_request' do
|
96
|
-
EM.run{ Fiber.new{ pure_ruby_single_request_ ; EM.stop }.resume}
|
97
|
-
end
|
98
|
-
|
99
|
-
def_use_case 'eventmachine_fiber_concurrent_requests' do
|
100
|
-
EM.run{ Fiber.new{ pure_ruby_concurrent_requests_ ; EM.stop }.resume}
|
101
|
-
end
|
102
|
-
|
103
|
-
def_use_case 'eventmachine_fiber_cache_requests' do
|
104
|
-
EM.run{ Fiber.new{ pure_ruby_cache_requests_ ; EM.stop }.resume}
|
105
|
-
end
|
106
|
-
|
107
|
-
def_use_case 'eventmachine_fiber_callback_requests' do
|
108
|
-
EM.run{ Fiber.new{ pure_ruby_callback_requests_ ; EM.stop }.resume}
|
109
|
-
end
|
110
|
-
|
111
|
-
def_use_case 'eventmachine_fiber_nested_concurrent_requests' do
|
112
|
-
EM.run{ Fiber.new{ pure_ruby_nested_concurrent_requests_; EM.stop }.resume}
|
113
|
-
end
|
114
|
-
|
115
|
-
# ----------------------------------------------------------------------
|
116
|
-
|
117
|
-
def_use_case 'eventmachine_thread_single_request' do
|
118
|
-
EM.run{ Thread.new{ pure_ruby_single_request_ ; EM.stop } }
|
119
|
-
end
|
120
|
-
|
121
|
-
def_use_case 'eventmachine_thread_concurrent_requests' do
|
122
|
-
EM.run{ Thread.new{ pure_ruby_concurrent_requests_ ; EM.stop } }
|
123
|
-
end
|
124
|
-
|
125
|
-
def_use_case 'eventmachine_thread_cache_requests' do
|
126
|
-
EM.run{ Thread.new{ pure_ruby_cache_requests_ ; EM.stop } }
|
127
|
-
end
|
128
|
-
|
129
|
-
def_use_case 'eventmachine_thread_callback_requests' do
|
130
|
-
EM.run{ Thread.new{ pure_ruby_callback_requests_ ; EM.stop } }
|
131
|
-
end
|
132
|
-
|
133
|
-
def_use_case 'eventmachine_thread_nested_concurrent_requests' do
|
134
|
-
EM.run{ Thread.new{ pure_ruby_nested_concurrent_requests_; EM.stop } }
|
135
|
-
end
|
136
|
-
|
137
|
-
# ----------------------------------------------------------------------
|
138
|
-
|
139
|
-
def_use_case 'eventmachine_rest_client_single_request' do
|
140
|
-
EM.run{ pure_ruby_single_request_ ; EM.stop }
|
141
|
-
end
|
142
|
-
|
143
|
-
def_use_case 'eventmachine_rest_client_concurrent_requests' do
|
144
|
-
EM.run{ pure_ruby_concurrent_requests_ ; EM.stop }
|
145
|
-
end
|
146
|
-
|
147
|
-
def_use_case 'eventmachine_rest_client_cache_requests' do
|
148
|
-
EM.run{ pure_ruby_cache_requests_ ; EM.stop }
|
149
|
-
end
|
150
|
-
|
151
|
-
def_use_case 'eventmachine_rest_client_callback_requests' do
|
152
|
-
EM.run{ pure_ruby_callback_requests_ ; EM.stop }
|
153
|
-
end
|
154
|
-
|
155
|
-
def_use_case 'eventmachine_rest_client_nested_concurrent_requests' do
|
156
|
-
EM.run{ pure_ruby_nested_concurrent_requests_; EM.stop }
|
157
|
-
end
|
158
|
-
|
159
|
-
# ----------------------------------------------------------------------
|
160
|
-
|
161
105
|
def_use_case 'pure_ruby' do
|
162
106
|
pure_ruby_single_request
|
163
107
|
pure_ruby_concurrent_requests
|
@@ -166,33 +110,6 @@ def_use_case 'pure_ruby' do
|
|
166
110
|
pure_ruby_nested_concurrent_requests
|
167
111
|
end
|
168
112
|
|
169
|
-
def_use_case 'eventmachine_fiber' do
|
170
|
-
eventmachine_fiber_single_request
|
171
|
-
eventmachine_fiber_concurrent_requests
|
172
|
-
eventmachine_fiber_cache_requests
|
173
|
-
eventmachine_fiber_callback_requests
|
174
|
-
eventmachine_fiber_nested_concurrent_requests
|
175
|
-
end
|
176
|
-
|
177
|
-
def_use_case 'eventmachine_thread' do
|
178
|
-
eventmachine_thread_single_request
|
179
|
-
eventmachine_thread_concurrent_requests
|
180
|
-
eventmachine_thread_cache_requests
|
181
|
-
eventmachine_thread_callback_requests
|
182
|
-
eventmachine_thread_nested_concurrent_requests
|
183
|
-
end
|
184
|
-
|
185
|
-
def_use_case 'eventmachine_rest_client' do
|
186
|
-
eventmachine_rest_client_single_request
|
187
|
-
eventmachine_rest_client_concurrent_requests
|
188
|
-
eventmachine_rest_client_cache_requests
|
189
|
-
eventmachine_rest_client_callback_requests
|
190
|
-
eventmachine_rest_client_nested_concurrent_requests
|
191
|
-
end
|
192
|
-
|
193
113
|
# ----------------------------------------------------------------------
|
194
114
|
|
195
115
|
pure_ruby
|
196
|
-
eventmachine_fiber
|
197
|
-
eventmachine_thread
|
198
|
-
eventmachine_rest_client
|
data/lib/rest-core.rb
CHANGED
@@ -9,16 +9,17 @@ module RestCore
|
|
9
9
|
RESPONSE_BODY = 'RESPONSE_BODY'
|
10
10
|
RESPONSE_STATUS = 'RESPONSE_STATUS'
|
11
11
|
RESPONSE_HEADERS = 'RESPONSE_HEADERS'
|
12
|
+
RESPONSE_SOCKET = 'RESPONSE_SOCKET'
|
12
13
|
|
13
14
|
DRY = 'core.dry'
|
14
15
|
FAIL = 'core.fail'
|
15
16
|
LOG = 'core.log'
|
17
|
+
CLIENT = 'core.client'
|
16
18
|
|
17
19
|
ASYNC = 'async.callback'
|
18
20
|
TIMER = 'async.timer'
|
19
|
-
|
20
|
-
|
21
|
-
RootFiber = Fiber.respond_to?(:current) && Fiber.current
|
21
|
+
PROMISE = 'async.promise'
|
22
|
+
HIJACK = 'async.hijack'
|
22
23
|
|
23
24
|
# core utilities
|
24
25
|
autoload :Builder , 'rest-core/builder'
|
@@ -27,6 +28,9 @@ module RestCore
|
|
27
28
|
autoload :Event , 'rest-core/event'
|
28
29
|
autoload :Middleware , 'rest-core/middleware'
|
29
30
|
autoload :Wrapper , 'rest-core/wrapper'
|
31
|
+
autoload :Promise , 'rest-core/promise'
|
32
|
+
autoload :ThreadPool , 'rest-core/thread_pool'
|
33
|
+
autoload :EventSource , 'rest-core/event_source'
|
30
34
|
|
31
35
|
# oauth1 utilities
|
32
36
|
autoload :ClientOauth1 , 'rest-core/client_oauth1'
|
@@ -59,10 +63,10 @@ module RestCore
|
|
59
63
|
autoload :Timeout , 'rest-core/middleware/timeout'
|
60
64
|
|
61
65
|
# engines
|
62
|
-
autoload :Auto , 'rest-core/engine/auto'
|
63
66
|
autoload :Dry , 'rest-core/engine/dry'
|
67
|
+
autoload :HttpClient , 'rest-core/engine/http-client'
|
64
68
|
autoload :RestClient , 'rest-core/engine/rest-client'
|
65
|
-
autoload :
|
69
|
+
autoload :NetHttpPersistent, 'rest-core/engine/net-http-persistent'
|
66
70
|
|
67
71
|
# clients
|
68
72
|
autoload :Simple , 'rest-core/client/simple'
|
@@ -83,6 +87,11 @@ module RestCore
|
|
83
87
|
eagerload(c, loaded) if c.respond_to?(:constants) && !loaded[n]
|
84
88
|
}
|
85
89
|
end
|
90
|
+
|
91
|
+
# identity function
|
92
|
+
def self.id
|
93
|
+
@id ||= lambda{ |a| a }
|
94
|
+
end
|
86
95
|
end
|
87
96
|
|
88
97
|
RC = RestCore unless Object.const_defined?(:RC)
|
data/lib/rest-core/builder.rb
CHANGED
@@ -7,7 +7,7 @@ class RestCore::Builder
|
|
7
7
|
include Wrapper
|
8
8
|
|
9
9
|
def self.default_engine
|
10
|
-
@default_engine ||= RestCore::
|
10
|
+
@default_engine ||= RestCore::HttpClient
|
11
11
|
end
|
12
12
|
|
13
13
|
def self.client *attrs, &block
|
@@ -24,12 +24,22 @@ class RestCore::Builder
|
|
24
24
|
client = Class.new(struct)
|
25
25
|
client.const_set('Struct', struct)
|
26
26
|
client.send(:include, Client)
|
27
|
-
class << client
|
27
|
+
class << client
|
28
|
+
attr_reader :builder
|
29
|
+
attr_accessor :pool_size, :pool_idle_time
|
30
|
+
|
31
|
+
def thread_pool
|
32
|
+
RestCore::ThreadPool[self]
|
33
|
+
end
|
34
|
+
end
|
28
35
|
client.instance_variable_set(:@builder, self)
|
36
|
+
client.instance_variable_set(:@pool_size, 0) # default to no pool
|
37
|
+
client.instance_variable_set(:@pool_idle_time, 60) # default to 60 seconds
|
29
38
|
client
|
30
39
|
end
|
31
40
|
|
32
41
|
def initialize &block
|
42
|
+
@engine = nil
|
33
43
|
@middles ||= []
|
34
44
|
instance_eval(&block) if block_given?
|
35
45
|
end
|
data/lib/rest-core/client.rb
CHANGED
@@ -1,7 +1,6 @@
|
|
1
1
|
|
2
|
-
require 'rest-core'
|
3
|
-
|
4
2
|
require 'weakref'
|
3
|
+
require 'rest-core'
|
5
4
|
|
6
5
|
module RestCore::Client
|
7
6
|
include RestCore
|
@@ -43,12 +42,13 @@ module RestCore::Client
|
|
43
42
|
mod.send(:include, accessor)
|
44
43
|
end
|
45
44
|
|
46
|
-
attr_reader :app, :dry, :
|
45
|
+
attr_reader :app, :dry, :promises
|
47
46
|
def initialize o={}
|
48
47
|
@app ||= self.class.builder.to_app # lighten! would reinitialize anyway
|
49
48
|
@dry ||= self.class.builder.to_app(Dry)
|
50
|
-
@
|
51
|
-
@mutex
|
49
|
+
@promises = [] # don't record any promises in lighten!
|
50
|
+
@mutex = nil # for locking promises, lazily initialized
|
51
|
+
# for serialization
|
52
52
|
o.each{ |key, value| send("#{key}=", value) if respond_to?("#{key}=") }
|
53
53
|
end
|
54
54
|
|
@@ -85,13 +85,13 @@ module RestCore::Client
|
|
85
85
|
end
|
86
86
|
|
87
87
|
def wait
|
88
|
-
return self if
|
89
|
-
|
88
|
+
return self if promises.empty?
|
89
|
+
current_promises = nil
|
90
90
|
mutex.synchronize{
|
91
|
-
|
92
|
-
|
91
|
+
current_promises = promises.dup
|
92
|
+
promises.clear
|
93
93
|
}
|
94
|
-
|
94
|
+
current_promises.each{ |f|
|
95
95
|
begin
|
96
96
|
f.wait
|
97
97
|
rescue WeakRef::RefError # it's gc'ed after we think it's alive
|
@@ -111,14 +111,14 @@ module RestCore::Client
|
|
111
111
|
request(
|
112
112
|
{REQUEST_METHOD => :get ,
|
113
113
|
REQUEST_PATH => path ,
|
114
|
-
REQUEST_QUERY => query }.merge(opts), &cb)
|
114
|
+
REQUEST_QUERY => query }.merge(opts), response_key(opts), &cb)
|
115
115
|
end
|
116
116
|
|
117
117
|
def delete path, query={}, opts={}, &cb
|
118
118
|
request(
|
119
119
|
{REQUEST_METHOD => :delete,
|
120
120
|
REQUEST_PATH => path ,
|
121
|
-
REQUEST_QUERY => query }.merge(opts), &cb)
|
121
|
+
REQUEST_QUERY => query }.merge(opts), response_key(opts), &cb)
|
122
122
|
end
|
123
123
|
|
124
124
|
def head path, query={}, opts={}, &cb
|
@@ -132,7 +132,7 @@ module RestCore::Client
|
|
132
132
|
request(
|
133
133
|
{REQUEST_METHOD => :options,
|
134
134
|
REQUEST_PATH => path ,
|
135
|
-
REQUEST_QUERY => query }.merge(opts), &cb)
|
135
|
+
REQUEST_QUERY => query }.merge(opts), RESPONSE_HEADERS, &cb)
|
136
136
|
end
|
137
137
|
|
138
138
|
def post path, payload={}, query={}, opts={}, &cb
|
@@ -140,7 +140,7 @@ module RestCore::Client
|
|
140
140
|
{REQUEST_METHOD => :post ,
|
141
141
|
REQUEST_PATH => path ,
|
142
142
|
REQUEST_QUERY => query ,
|
143
|
-
REQUEST_PAYLOAD => payload}.merge(opts), &cb)
|
143
|
+
REQUEST_PAYLOAD => payload}.merge(opts), response_key(opts), &cb)
|
144
144
|
end
|
145
145
|
|
146
146
|
def put path, payload={}, query={}, opts={}, &cb
|
@@ -148,7 +148,7 @@ module RestCore::Client
|
|
148
148
|
{REQUEST_METHOD => :put ,
|
149
149
|
REQUEST_PATH => path ,
|
150
150
|
REQUEST_QUERY => query ,
|
151
|
-
REQUEST_PAYLOAD => payload}.merge(opts), &cb)
|
151
|
+
REQUEST_PAYLOAD => payload}.merge(opts), response_key(opts), &cb)
|
152
152
|
end
|
153
153
|
|
154
154
|
def patch path, payload={}, query={}, opts={}, &cb
|
@@ -156,14 +156,16 @@ module RestCore::Client
|
|
156
156
|
{REQUEST_METHOD => :patch ,
|
157
157
|
REQUEST_PATH => path ,
|
158
158
|
REQUEST_QUERY => query ,
|
159
|
-
REQUEST_PAYLOAD => payload}.merge(opts), &cb)
|
159
|
+
REQUEST_PAYLOAD => payload}.merge(opts), response_key(opts), &cb)
|
160
|
+
end
|
161
|
+
|
162
|
+
def event_source path, query={}, opts={}
|
163
|
+
EventSource.new(self, path, query, opts)
|
160
164
|
end
|
161
165
|
|
162
166
|
def request env, key=RESPONSE_BODY, app=app
|
163
167
|
if block_given?
|
164
|
-
request_full(env, app){ |response|
|
165
|
-
yield(response[key])
|
166
|
-
}
|
168
|
+
request_full(env, app){ |response| yield(response[key]) }
|
167
169
|
else
|
168
170
|
request_full(env, app)[key]
|
169
171
|
end
|
@@ -171,14 +173,13 @@ module RestCore::Client
|
|
171
173
|
|
172
174
|
def request_full env, app=app, &k
|
173
175
|
response = app.call(build_env({ASYNC => !!k}.merge(env)),
|
174
|
-
&(k ||
|
176
|
+
&(k || RC.id))
|
175
177
|
|
176
178
|
# under ASYNC callback, response might not be a response hash
|
177
179
|
# in that case (maybe in a user created engine), Client#wait
|
178
|
-
# won't work because we have no way to track the
|
179
|
-
if response.kind_of?(Hash) &&
|
180
|
-
|
181
|
-
mutex.synchronize{ futures << WeakRef.new(response[FUTURE]) }
|
180
|
+
# won't work because we have no way to track the promise.
|
181
|
+
if response.kind_of?(Hash) && response[PROMISE].kind_of?(Promise)
|
182
|
+
mutex.synchronize{ promises << WeakRef.new(response[PROMISE]) }
|
182
183
|
end
|
183
184
|
|
184
185
|
if block_given?
|
@@ -200,7 +201,8 @@ module RestCore::Client
|
|
200
201
|
REQUEST_PAYLOAD => {} ,
|
201
202
|
REQUEST_HEADERS => {} ,
|
202
203
|
FAIL => [] ,
|
203
|
-
LOG => []
|
204
|
+
LOG => [] ,
|
205
|
+
CLIENT => self}
|
204
206
|
end
|
205
207
|
# ------------------------ instance ---------------------
|
206
208
|
|
@@ -211,6 +213,10 @@ module RestCore::Client
|
|
211
213
|
@mutex ||= Mutex.new
|
212
214
|
end
|
213
215
|
|
216
|
+
def response_key opts
|
217
|
+
if opts[HIJACK] then RESPONSE_SOCKET else RESPONSE_BODY end
|
218
|
+
end
|
219
|
+
|
214
220
|
def lighten_hash hash
|
215
221
|
Hash[hash.map{ |(key, value)|
|
216
222
|
case value
|