rest-core 3.3.3 → 3.4.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.
- checksums.yaml +4 -4
- data/.gitignore +1 -0
- data/.travis.yml +4 -2
- data/CHANGES.md +32 -0
- data/Gemfile +3 -0
- data/README.md +1 -1
- data/example/use-cases.rb +14 -19
- data/lib/rest-core.rb +0 -2
- data/lib/rest-core/engine.rb +0 -5
- data/lib/rest-core/engine/http-client.rb +0 -3
- data/lib/rest-core/middleware/json_request.rb +3 -2
- data/lib/rest-core/promise.rb +64 -33
- data/lib/rest-core/thread_pool.rb +13 -12
- data/lib/rest-core/timer.rb +28 -6
- data/lib/rest-core/util/json.rb +0 -1
- data/lib/rest-core/version.rb +1 -1
- data/rest-core.gemspec +6 -10
- data/task/gemgem.rb +100 -51
- data/test/test_builder.rb +4 -4
- data/test/test_client.rb +1 -9
- data/test/{test_rest-client.rb → test_httpclient.rb} +6 -19
- data/test/test_json_request.rb +16 -4
- data/test/test_timeout.rb +54 -0
- metadata +5 -9
- data/lib/rest-core/engine/net-http-persistent.rb +0 -21
- data/lib/rest-core/engine/rest-client.rb +0 -29
- data/lib/rest-core/patch/multi_json.rb +0 -8
- data/lib/rest-core/patch/rest-client.rb +0 -35
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: ab6a9f5e489329946784228471a7647aac66bbdd
|
4
|
+
data.tar.gz: 4b8d30e22074977305146a9a0cc875334c473599
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 09378189003073e9e0fcde4b210c6ef3e5e7441388e006ba5f5e9bb916acd6b191ac7fd7e9649837dcd82e8e5d360a1efe41f3e6fa247fc9911e584b5dd074ce
|
7
|
+
data.tar.gz: cdf158fd0a2ca140d64792e7daa29575c9914ca5ede20b556ef04f64bc93792f053c3d2e49f59a6888823baa623fc467dbd41edac26544b9d97057e7b511b7e2
|
data/.gitignore
CHANGED
data/.travis.yml
CHANGED
data/CHANGES.md
CHANGED
@@ -1,5 +1,37 @@
|
|
1
1
|
# CHANGES
|
2
2
|
|
3
|
+
## rest-core 3.4.0 -- 2014-11-26
|
4
|
+
|
5
|
+
### Incompatible changes
|
6
|
+
|
7
|
+
* Removed rest-client support.
|
8
|
+
* Removed net-http-persistent support.
|
9
|
+
* Removed patch for old multi-json.
|
10
|
+
|
11
|
+
### Bugs fixed
|
12
|
+
|
13
|
+
* `RC::JsonRequest` can now POST, PUT, or PATCH with a single `false`.
|
14
|
+
|
15
|
+
* Previously, we're not handling timeout correctly. We left all that to
|
16
|
+
httpclient, and which would raise `HTTPClient::ConnectTimeoutError` and
|
17
|
+
`HTTPClient::ReceiveTimeoutError`. The problem is that connecting and
|
18
|
+
receiving are counted separately. That means, if we have 30 seconds timeout,
|
19
|
+
we might be ending up with 58 seconds requesting time, for 29 seconds
|
20
|
+
connecting time and 29 seconds receiving time. Now it should probably
|
21
|
+
interrupt the request in 30 seconds by handling this by ourselves with a
|
22
|
+
timer thread in the background. The timer thread would be shut down
|
23
|
+
automatically if there's no jobs left, and it would recreate the thread
|
24
|
+
when there's a job comes in, keeping working until there's no jobs left.
|
25
|
+
|
26
|
+
### Enhancements
|
27
|
+
|
28
|
+
* Introduced `RC::Timer.interval` which is the interval to check if there's
|
29
|
+
a request timed out. The default interval is 1 second, which means it would
|
30
|
+
check if there's a request timed out for every 1 second. This also means
|
31
|
+
timeout with less than 1 second won't be accurate at all. You could
|
32
|
+
decrease the value if you need timeout less than 1 second, or increase it
|
33
|
+
if your timeout is far from 30 second by calling `RC::Timer.interval = 5`.
|
34
|
+
|
3
35
|
## rest-core 3.3.3 -- 2014-11-07
|
4
36
|
|
5
37
|
### Bugs fixed
|
data/Gemfile
CHANGED
data/README.md
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
# rest-core [](http://travis-ci.org/godfat/rest-core)
|
1
|
+
# rest-core [](http://travis-ci.org/godfat/rest-core) [](https://coveralls.io/r/godfat/rest-core)
|
2
2
|
|
3
3
|
by Lin Jen-Shin ([godfat](http://godfat.org))
|
4
4
|
|
data/example/use-cases.rb
CHANGED
@@ -23,13 +23,8 @@ def def_use_case name, &block
|
|
23
23
|
end
|
24
24
|
end
|
25
25
|
|
26
|
-
def q str
|
27
|
-
|
28
|
-
if m
|
29
|
-
m.synchronize(&p)
|
30
|
-
else
|
31
|
-
p.call
|
32
|
-
end
|
26
|
+
def q str
|
27
|
+
Thread.exclusive{ puts "\e[33m=> #{str.inspect}\e[0m" }
|
33
28
|
end
|
34
29
|
|
35
30
|
# ----------------------------------------------------------------------
|
@@ -51,36 +46,36 @@ def_use_case 'pure_ruby_cache_requests' do
|
|
51
46
|
end
|
52
47
|
|
53
48
|
def_use_case 'pure_ruby_callback_requests' do
|
54
|
-
m = Mutex.new
|
55
49
|
RC::Universal.new(:json_response => true ,
|
56
50
|
:site => 'https://graph.facebook.com/' ,
|
57
|
-
:log_method => lambda{|str|
|
51
|
+
:log_method => lambda{|str|
|
52
|
+
Thread.exclusive{puts(str)}}).
|
58
53
|
get('4'){ |res|
|
59
54
|
if res.kind_of?(Exception)
|
60
|
-
|
55
|
+
q "Encountering: #{res}"
|
61
56
|
next
|
62
57
|
end
|
63
|
-
q res['name']
|
58
|
+
q res['name']
|
64
59
|
}.
|
65
60
|
get('5'){ |res|
|
66
61
|
if res.kind_of?(Exception)
|
67
|
-
|
62
|
+
q "Encountering: #{res}"
|
68
63
|
next
|
69
64
|
end
|
70
|
-
q res['name']
|
65
|
+
q res['name']
|
71
66
|
}.wait
|
72
67
|
end
|
73
68
|
|
74
69
|
def_use_case 'pure_ruby_nested_concurrent_requests' do
|
75
|
-
m = Mutex.new
|
76
70
|
c = RC::Universal.new(:json_response => true ,
|
77
71
|
:site => 'https://graph.facebook.com/' ,
|
78
|
-
:log_method => lambda{|str|
|
72
|
+
:log_method => lambda{ |str|
|
73
|
+
Thread.exclusive{puts(str)}})
|
79
74
|
|
80
75
|
%w[4 5].each{ |user|
|
81
76
|
c.get(user, :fields => 'cover'){ |data|
|
82
77
|
if data.kind_of?(Exception)
|
83
|
-
q "Encountering: #{data}"
|
78
|
+
q "Encountering: #{data}"
|
84
79
|
next
|
85
80
|
end
|
86
81
|
|
@@ -89,11 +84,11 @@ def_use_case 'pure_ruby_nested_concurrent_requests' do
|
|
89
84
|
likes = c.get("#{cover['id']}/likes")
|
90
85
|
most_liked_comment = comments['data'].max_by{|d|d['like_count']}
|
91
86
|
|
92
|
-
q "Author of most liked comment from #{user}'s cover photo:"
|
93
|
-
q most_liked_comment['from']['name']
|
87
|
+
q "Author of most liked comment from #{user}'s cover photo:"
|
88
|
+
q most_liked_comment['from']['name']
|
94
89
|
|
95
90
|
y = !!likes['data'].find{|d|d['id'] == most_liked_comment['from']['id']}
|
96
|
-
q "Did the user also like the cover?: #{y}"
|
91
|
+
q "Did the user also like the cover?: #{y}"
|
97
92
|
}
|
98
93
|
}
|
99
94
|
|
data/lib/rest-core.rb
CHANGED
@@ -73,8 +73,6 @@ module RestCore
|
|
73
73
|
# engines
|
74
74
|
autoload :Dry , 'rest-core/engine/dry'
|
75
75
|
autoload :HttpClient , 'rest-core/engine/http-client'
|
76
|
-
autoload :RestClient , 'rest-core/engine/rest-client'
|
77
|
-
autoload :NetHttpPersistent, 'rest-core/engine/net-http-persistent'
|
78
76
|
|
79
77
|
# clients
|
80
78
|
autoload :Simple , 'rest-core/client/simple'
|
data/lib/rest-core/engine.rb
CHANGED
@@ -17,11 +17,6 @@ class RestCore::Engine
|
|
17
17
|
Payload.generate_with_headers(env[REQUEST_PAYLOAD], env[REQUEST_HEADERS])
|
18
18
|
end
|
19
19
|
|
20
|
-
def calculate_timeout timer
|
21
|
-
return [] unless timer
|
22
|
-
[timer.timeout, timer.timeout]
|
23
|
-
end
|
24
|
-
|
25
20
|
def normalize_headers headers
|
26
21
|
headers.inject({}){ |r, (k, v)|
|
27
22
|
r[k.to_s.upcase.tr('-', '_')] = if v.kind_of?(Array) && v.size == 1
|
@@ -19,9 +19,6 @@ class RestCore::HttpClient < RestCore::Engine
|
|
19
19
|
end
|
20
20
|
|
21
21
|
def request_sync client, payload, headers, promise, env
|
22
|
-
client.connect_timeout, client.receive_timeout =
|
23
|
-
calculate_timeout(env[TIMER])
|
24
|
-
|
25
22
|
res = client.request(env[REQUEST_METHOD], env[REQUEST_URI], nil,
|
26
23
|
payload, {'User-Agent' => 'Ruby'}.merge(headers))
|
27
24
|
|
@@ -7,11 +7,12 @@ class RestCore::JsonRequest
|
|
7
7
|
include RestCore::Middleware
|
8
8
|
|
9
9
|
JSON_REQUEST_HEADER = {'Content-Type' => 'application/json'}.freeze
|
10
|
+
JSON_REQUEST_METHOD = [:post, :put, :patch]
|
10
11
|
|
11
12
|
def call env, &k
|
12
13
|
return app.call(env, &k) unless json_request(env)
|
13
|
-
return app.call(env, &k) unless
|
14
|
-
|
14
|
+
return app.call(env, &k) unless
|
15
|
+
JSON_REQUEST_METHOD.include?(env[REQUEST_METHOD])
|
15
16
|
|
16
17
|
app.call(env.merge(
|
17
18
|
REQUEST_HEADERS => JSON_REQUEST_HEADER.merge(env[REQUEST_HEADERS]||{}),
|
data/lib/rest-core/promise.rb
CHANGED
@@ -62,19 +62,28 @@ class RestCore::Promise
|
|
62
62
|
end
|
63
63
|
|
64
64
|
# called in client thread
|
65
|
-
def defer
|
65
|
+
def defer
|
66
66
|
if pool_size < 0 # negative number for blocking call
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
synchronized_yield(backtrace){ job.call }
|
72
|
-
end
|
67
|
+
self.thread = Thread.current
|
68
|
+
# set timeout after thread set, before yield (because yield is blocking)
|
69
|
+
env[TIMER].on_timeout{ cancel_task } if env[TIMER]
|
70
|
+
protected_yield{ yield }
|
73
71
|
else
|
74
72
|
backtrace = caller + self.class.backtrace
|
75
|
-
|
73
|
+
if pool_size > 0
|
74
|
+
self.task = client_class.thread_pool.defer(mutex) do
|
75
|
+
Thread.current[:backtrace] = backtrace
|
76
|
+
protected_yield{ yield }
|
77
|
+
end
|
78
|
+
else
|
79
|
+
self.thread = Thread.new do
|
80
|
+
Thread.current[:backtrace] = backtrace
|
81
|
+
protected_yield{ yield }
|
82
|
+
end
|
83
|
+
end
|
84
|
+
# set timeout after thread/task set
|
85
|
+
env[TIMER].on_timeout{ cancel_task } if env[TIMER]
|
76
86
|
end
|
77
|
-
env[TIMER].on_timeout{ reject(env[TIMER].error) } if env[TIMER]
|
78
87
|
end
|
79
88
|
|
80
89
|
# called in client thread (client.wait)
|
@@ -92,24 +101,13 @@ class RestCore::Promise
|
|
92
101
|
# called in requesting thread after the request is done
|
93
102
|
def fulfill body, status, headers, socket=nil
|
94
103
|
env[TIMER].cancel if env[TIMER]
|
95
|
-
|
96
|
-
body, status, headers, socket
|
97
|
-
# under ASYNC callback, should call immediately
|
98
|
-
callback if immediate
|
99
|
-
ensure
|
100
|
-
condv.broadcast # client or response might be waiting
|
104
|
+
mutex.synchronize{ fulfilling(body, status, headers, socket) }
|
101
105
|
end
|
102
106
|
|
103
107
|
# called in requesting thread if something goes wrong or timed out
|
104
108
|
def reject error
|
105
|
-
|
106
|
-
|
107
|
-
self.error = if error.kind_of?(Exception)
|
108
|
-
error
|
109
|
-
else
|
110
|
-
Error.new(error || 'unknown')
|
111
|
-
end
|
112
|
-
fulfill('', 0, {})
|
109
|
+
env[TIMER].cancel if env[TIMER]
|
110
|
+
mutex.synchronize{ rejecting(error) }
|
113
111
|
end
|
114
112
|
|
115
113
|
# append your actions, which would be called when we're calling back
|
@@ -130,21 +128,42 @@ class RestCore::Promise
|
|
130
128
|
attr_accessor :env, :k, :immediate,
|
131
129
|
:body, :status, :headers, :socket,
|
132
130
|
:response, :error, :called,
|
133
|
-
:condv, :mutex, :task
|
131
|
+
:condv, :mutex, :task, :thread
|
134
132
|
|
135
133
|
private
|
134
|
+
def fulfilling body, status, headers, socket=nil
|
135
|
+
self.body, self.status, self.headers, self.socket =
|
136
|
+
body, status, headers, socket
|
137
|
+
# under ASYNC callback, should call immediately
|
138
|
+
callback if immediate
|
139
|
+
ensure
|
140
|
+
condv.broadcast # client or response might be waiting
|
141
|
+
end
|
142
|
+
|
143
|
+
def rejecting error
|
144
|
+
self.error = if error.kind_of?(Exception)
|
145
|
+
error
|
146
|
+
else
|
147
|
+
Error.new(error || 'unknown')
|
148
|
+
end
|
149
|
+
fulfilling('', 0, {})
|
150
|
+
end
|
151
|
+
|
136
152
|
# called in a new thread if pool_size == 0, otherwise from the pool
|
137
153
|
# i.e. requesting thread
|
138
|
-
def
|
139
|
-
|
140
|
-
mutex.synchronize{ yield }
|
154
|
+
def protected_yield
|
155
|
+
yield
|
141
156
|
rescue Exception => e
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
157
|
+
# pray if timeout won't trigger here!
|
158
|
+
env[TIMER].cancel if env[TIMER]
|
159
|
+
mutex.synchronize do
|
160
|
+
self.class.set_backtrace(e)
|
161
|
+
# nothing we can do here for an asynchronous exception,
|
162
|
+
# so we just log the error
|
163
|
+
# TODO: add error_log_method
|
164
|
+
warn "RestCore: ERROR: #{e}\n from #{e.backtrace.inspect}"
|
165
|
+
rejecting(e) unless done? # not done: i/o error; done: callback error
|
166
|
+
end
|
148
167
|
end
|
149
168
|
|
150
169
|
# called in client thread, when yield is called
|
@@ -161,6 +180,18 @@ class RestCore::Promise
|
|
161
180
|
self.called = true
|
162
181
|
end
|
163
182
|
|
183
|
+
def cancel_task
|
184
|
+
mutex.synchronize do
|
185
|
+
next if done?
|
186
|
+
if t = thread || task.thread
|
187
|
+
t.raise(env[TIMER].error)
|
188
|
+
else
|
189
|
+
task.cancel
|
190
|
+
rejecting(env[TIMER].error)
|
191
|
+
end
|
192
|
+
end
|
193
|
+
end
|
194
|
+
|
164
195
|
def client_class; env[CLIENT].class; end
|
165
196
|
def pool_size
|
166
197
|
@pool_size ||= if client_class.respond_to?(:pool_size)
|
@@ -26,7 +26,7 @@ class RestCore::ThreadPool
|
|
26
26
|
mutex.synchronize do
|
27
27
|
if queue.empty?
|
28
28
|
condv.wait(mutex, timeout)
|
29
|
-
queue.shift || lambda{ false } # shutdown idle workers
|
29
|
+
queue.shift || lambda{ |_| false } # shutdown idle workers
|
30
30
|
else
|
31
31
|
queue.shift
|
32
32
|
end
|
@@ -41,19 +41,20 @@ class RestCore::ThreadPool
|
|
41
41
|
attr_reader :queue, :mutex, :condv
|
42
42
|
end
|
43
43
|
|
44
|
-
class Task < Struct.new(:job)
|
44
|
+
class Task < Struct.new(:job, :mutex, :thread, :cancelled)
|
45
45
|
# this should never fail
|
46
|
-
def call
|
47
|
-
|
46
|
+
def call working_thread
|
47
|
+
mutex.synchronize do
|
48
|
+
return if cancelled
|
49
|
+
self.thread = working_thread
|
50
|
+
end
|
51
|
+
job.call
|
48
52
|
true
|
49
53
|
end
|
50
54
|
|
51
|
-
# called from the other thread telling us it's timed out
|
52
55
|
def cancel
|
53
|
-
|
56
|
+
self.cancelled = true
|
54
57
|
end
|
55
|
-
protected
|
56
|
-
attr_reader :thread, :mutex, :cancelled
|
57
58
|
end
|
58
59
|
|
59
60
|
def self.[] client_class
|
@@ -86,9 +87,9 @@ class RestCore::ThreadPool
|
|
86
87
|
client_class.pool_idle_time
|
87
88
|
end
|
88
89
|
|
89
|
-
def defer &job
|
90
|
+
def defer mutex=nil, &job
|
90
91
|
mutex.synchronize do
|
91
|
-
task = Task.new(job)
|
92
|
+
task = Task.new(job, mutex)
|
92
93
|
queue << task
|
93
94
|
spawn_worker if waiting == 0 && workers.size < max_size
|
94
95
|
task
|
@@ -96,7 +97,7 @@ class RestCore::ThreadPool
|
|
96
97
|
end
|
97
98
|
|
98
99
|
def trim force=false
|
99
|
-
queue << lambda{ false } if force || waiting > 0
|
100
|
+
queue << lambda{ |_| false } if force || waiting > 0
|
100
101
|
end
|
101
102
|
|
102
103
|
# Block on shutting down, and should not add more jobs while shutting down
|
@@ -119,7 +120,7 @@ class RestCore::ThreadPool
|
|
119
120
|
mutex.synchronize{ @waiting += 1 }
|
120
121
|
task = queue.pop(idle_time)
|
121
122
|
mutex.synchronize{ @waiting -= 1 }
|
122
|
-
end while task.call
|
123
|
+
end while task.call(Thread.current)
|
123
124
|
|
124
125
|
mutex.synchronize{ workers.delete(Thread.current) }
|
125
126
|
}
|
data/lib/rest-core/timer.rb
CHANGED
@@ -1,12 +1,33 @@
|
|
1
1
|
|
2
|
+
require 'thread'
|
2
3
|
require 'timers'
|
3
4
|
|
4
5
|
class RestCore::Timer
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
6
|
+
@mutex = Mutex.new
|
7
|
+
@interval = 1
|
8
|
+
|
9
|
+
singleton_class.module_eval do
|
10
|
+
attr_accessor :interval
|
11
|
+
|
12
|
+
def group
|
13
|
+
@group ||= @mutex.synchronize{ @group || group_new }
|
14
|
+
end
|
15
|
+
|
16
|
+
private
|
17
|
+
def group_new
|
18
|
+
g = Timers::Group.new
|
19
|
+
g.every(interval){}
|
20
|
+
@thread = Thread.new do
|
21
|
+
begin
|
22
|
+
g.wait
|
23
|
+
rescue => e
|
24
|
+
warn "RestCore::Timer: ERROR: #{e}\n from #{e.backtrace.inspect}"
|
25
|
+
end while g.count > 1
|
26
|
+
@group = nil
|
27
|
+
end
|
28
|
+
g
|
29
|
+
end
|
30
|
+
end
|
10
31
|
|
11
32
|
attr_accessor :timeout, :error
|
12
33
|
def initialize timeout, error, &block
|
@@ -22,11 +43,12 @@ class RestCore::Timer
|
|
22
43
|
|
23
44
|
def cancel
|
24
45
|
timer.cancel
|
46
|
+
self.block = nil
|
25
47
|
end
|
26
48
|
|
27
49
|
def start
|
28
50
|
return if timeout.nil? || timeout.zero?
|
29
|
-
self.timer =
|
51
|
+
self.timer = self.class.group.after(timeout){ block.call if block }
|
30
52
|
end
|
31
53
|
|
32
54
|
protected
|
data/lib/rest-core/util/json.rb
CHANGED
data/lib/rest-core/version.rb
CHANGED
data/rest-core.gemspec
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
# -*- encoding: utf-8 -*-
|
2
|
-
# stub: rest-core 3.
|
2
|
+
# stub: rest-core 3.4.0 ruby lib
|
3
3
|
|
4
4
|
Gem::Specification.new do |s|
|
5
5
|
s.name = "rest-core"
|
6
|
-
s.version = "3.
|
6
|
+
s.version = "3.4.0"
|
7
7
|
|
8
8
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
9
9
|
s.require_paths = ["lib"]
|
10
10
|
s.authors = ["Lin Jen-Shin (godfat)"]
|
11
|
-
s.date = "2014-11-
|
11
|
+
s.date = "2014-11-26"
|
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-more]: https://github.com/godfat/rest-more"
|
13
13
|
s.email = ["godfat (XD) godfat.org"]
|
14
14
|
s.files = [
|
@@ -33,8 +33,6 @@ Gem::Specification.new do |s|
|
|
33
33
|
"lib/rest-core/engine.rb",
|
34
34
|
"lib/rest-core/engine/dry.rb",
|
35
35
|
"lib/rest-core/engine/http-client.rb",
|
36
|
-
"lib/rest-core/engine/net-http-persistent.rb",
|
37
|
-
"lib/rest-core/engine/rest-client.rb",
|
38
36
|
"lib/rest-core/error.rb",
|
39
37
|
"lib/rest-core/event.rb",
|
40
38
|
"lib/rest-core/event_source.rb",
|
@@ -61,8 +59,6 @@ Gem::Specification.new do |s|
|
|
61
59
|
"lib/rest-core/middleware/query_response.rb",
|
62
60
|
"lib/rest-core/middleware/smash_response.rb",
|
63
61
|
"lib/rest-core/middleware/timeout.rb",
|
64
|
-
"lib/rest-core/patch/multi_json.rb",
|
65
|
-
"lib/rest-core/patch/rest-client.rb",
|
66
62
|
"lib/rest-core/promise.rb",
|
67
63
|
"lib/rest-core/test.rb",
|
68
64
|
"lib/rest-core/thread_pool.rb",
|
@@ -98,6 +94,7 @@ Gem::Specification.new do |s|
|
|
98
94
|
"test/test_event_source.rb",
|
99
95
|
"test/test_follow_redirect.rb",
|
100
96
|
"test/test_future.rb",
|
97
|
+
"test/test_httpclient.rb",
|
101
98
|
"test/test_json_request.rb",
|
102
99
|
"test/test_json_response.rb",
|
103
100
|
"test/test_oauth1_header.rb",
|
@@ -106,7 +103,6 @@ Gem::Specification.new do |s|
|
|
106
103
|
"test/test_payload.rb",
|
107
104
|
"test/test_promise.rb",
|
108
105
|
"test/test_query_response.rb",
|
109
|
-
"test/test_rest-client.rb",
|
110
106
|
"test/test_simple.rb",
|
111
107
|
"test/test_smash.rb",
|
112
108
|
"test/test_smash_response.rb",
|
@@ -115,7 +111,7 @@ Gem::Specification.new do |s|
|
|
115
111
|
"test/test_universal.rb"]
|
116
112
|
s.homepage = "https://github.com/godfat/rest-core"
|
117
113
|
s.licenses = ["Apache License 2.0"]
|
118
|
-
s.rubygems_version = "2.4.
|
114
|
+
s.rubygems_version = "2.4.4"
|
119
115
|
s.summary = "Modular Ruby clients interface for REST APIs."
|
120
116
|
s.test_files = [
|
121
117
|
"test/test_auth_basic.rb",
|
@@ -136,6 +132,7 @@ Gem::Specification.new do |s|
|
|
136
132
|
"test/test_event_source.rb",
|
137
133
|
"test/test_follow_redirect.rb",
|
138
134
|
"test/test_future.rb",
|
135
|
+
"test/test_httpclient.rb",
|
139
136
|
"test/test_json_request.rb",
|
140
137
|
"test/test_json_response.rb",
|
141
138
|
"test/test_oauth1_header.rb",
|
@@ -144,7 +141,6 @@ Gem::Specification.new do |s|
|
|
144
141
|
"test/test_payload.rb",
|
145
142
|
"test/test_promise.rb",
|
146
143
|
"test/test_query_response.rb",
|
147
|
-
"test/test_rest-client.rb",
|
148
144
|
"test/test_simple.rb",
|
149
145
|
"test/test_smash.rb",
|
150
146
|
"test/test_smash_response.rb",
|
data/task/gemgem.rb
CHANGED
@@ -38,6 +38,99 @@ module Gemgem
|
|
38
38
|
self.spec = spec
|
39
39
|
end
|
40
40
|
|
41
|
+
def gem_install
|
42
|
+
require 'rubygems/commands/install_command'
|
43
|
+
# read ~/.gemrc
|
44
|
+
Gem.use_paths(Gem.configuration[:gemhome], Gem.configuration[:gempath])
|
45
|
+
Gem::Command.extra_args = Gem.configuration[:gem]
|
46
|
+
|
47
|
+
# setup install options
|
48
|
+
cmd = Gem::Commands::InstallCommand.new
|
49
|
+
cmd.handle_options([])
|
50
|
+
|
51
|
+
# install
|
52
|
+
install = Gem::Installer.new(gem_path, cmd.options)
|
53
|
+
install.install
|
54
|
+
puts "\e[35mGem installed: \e[33m#{strip_path(install.gem_dir)}\e[0m"
|
55
|
+
end
|
56
|
+
|
57
|
+
def gem_spec
|
58
|
+
create
|
59
|
+
write
|
60
|
+
end
|
61
|
+
|
62
|
+
def gem_build
|
63
|
+
require 'fileutils'
|
64
|
+
require 'rubygems/package'
|
65
|
+
gem = nil
|
66
|
+
Dir.chdir(dir) do
|
67
|
+
gem = Gem::Package.build(Gem::Specification.load(spec_path))
|
68
|
+
FileUtils.mkdir_p(pkg_dir)
|
69
|
+
FileUtils.mv(gem, pkg_dir) # gem is relative path, but might be ok
|
70
|
+
end
|
71
|
+
puts "\e[35mGem built: \e[33m#{strip_path("#{pkg_dir}/#{gem}")}\e[0m"
|
72
|
+
end
|
73
|
+
|
74
|
+
def gem_release
|
75
|
+
sh_git('tag', gem_tag)
|
76
|
+
sh_git('push')
|
77
|
+
sh_git('push', '--tags')
|
78
|
+
sh_gem('push', gem_path)
|
79
|
+
end
|
80
|
+
|
81
|
+
def gem_check
|
82
|
+
ver = spec.version.to_s
|
83
|
+
|
84
|
+
if ENV['VERSION'].nil?
|
85
|
+
puts("\e[35mExpected " \
|
86
|
+
"\e[33mVERSION\e[35m=\e[33m#{ver}\e[0m")
|
87
|
+
exit(1)
|
88
|
+
|
89
|
+
elsif ENV['VERSION'] != ver
|
90
|
+
puts("\e[35mExpected \e[33mVERSION\e[35m=\e[33m#{ver} " \
|
91
|
+
"\e[35mbut got\n " \
|
92
|
+
"\e[33mVERSION\e[35m=\e[33m#{ENV['VERSION']}\e[0m")
|
93
|
+
exit(2)
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
def test
|
98
|
+
return if test_files.empty?
|
99
|
+
|
100
|
+
if ENV['COV'] || ENV['CI']
|
101
|
+
require 'simplecov'
|
102
|
+
if ENV['CI']
|
103
|
+
require 'coveralls'
|
104
|
+
SimpleCov.formatter = Coveralls::SimpleCov::Formatter
|
105
|
+
end
|
106
|
+
SimpleCov.start do
|
107
|
+
add_filter('test/')
|
108
|
+
add_filter('test.rb')
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
112
|
+
test_files.each{ |file| require "#{dir}/#{file[0..-4]}" }
|
113
|
+
end
|
114
|
+
|
115
|
+
def clean
|
116
|
+
return if ignored_files.empty?
|
117
|
+
|
118
|
+
require 'fileutils'
|
119
|
+
trash = File.expand_path("~/.Trash/#{spec.name}")
|
120
|
+
puts "Move the following files into: \e[35m#{strip_path(trash)}\e[33m"
|
121
|
+
|
122
|
+
ignored_files.each do |file|
|
123
|
+
from = "#{dir}/#{file}"
|
124
|
+
to = "#{trash}/#{File.dirname(file)}"
|
125
|
+
puts strip_path(from)
|
126
|
+
|
127
|
+
FileUtils.mkdir_p(to)
|
128
|
+
FileUtils.mv(from, to)
|
129
|
+
end
|
130
|
+
|
131
|
+
print "\e[0m"
|
132
|
+
end
|
133
|
+
|
41
134
|
def write
|
42
135
|
File.open(spec_path, 'w'){ |f| f << split_lines(spec.to_ruby) }
|
43
136
|
end
|
@@ -173,82 +266,38 @@ namespace :gem do
|
|
173
266
|
|
174
267
|
desc 'Install gem'
|
175
268
|
task :install => [:build] do
|
176
|
-
Gemgem.
|
269
|
+
Gemgem.gem_install
|
177
270
|
end
|
178
271
|
|
179
272
|
desc 'Build gem'
|
180
273
|
task :build => [:spec] do
|
181
|
-
|
182
|
-
require 'rubygems/package'
|
183
|
-
gem = nil
|
184
|
-
Dir.chdir(Gemgem.dir) do
|
185
|
-
gem = Gem::Package.build(Gem::Specification.load(Gemgem.spec_path))
|
186
|
-
FileUtils.mkdir_p(Gemgem.pkg_dir)
|
187
|
-
FileUtils.mv(gem, Gemgem.pkg_dir) # gem is relative path, but might be ok
|
188
|
-
end
|
189
|
-
puts "\e[35mGem built: \e[33m" \
|
190
|
-
"#{Gemgem.strip_path("#{Gemgem.pkg_dir}/#{gem}")}\e[0m"
|
274
|
+
Gemgem.gem_build
|
191
275
|
end
|
192
276
|
|
193
277
|
desc 'Generate gemspec'
|
194
278
|
task :spec do
|
195
|
-
Gemgem.
|
196
|
-
Gemgem.write
|
279
|
+
Gemgem.gem_spec
|
197
280
|
end
|
198
281
|
|
199
282
|
desc 'Release gem'
|
200
283
|
task :release => [:spec, :check, :build] do
|
201
|
-
Gemgem.
|
202
|
-
sh_git('tag', Gemgem.gem_tag)
|
203
|
-
sh_git('push')
|
204
|
-
sh_git('push', '--tags')
|
205
|
-
sh_gem('push', Gemgem.gem_path)
|
206
|
-
end
|
284
|
+
Gemgem.gem_release
|
207
285
|
end
|
208
286
|
|
209
287
|
task :check do
|
210
|
-
|
211
|
-
|
212
|
-
if ENV['VERSION'].nil?
|
213
|
-
puts("\e[35mExpected " \
|
214
|
-
"\e[33mVERSION\e[35m=\e[33m#{ver}\e[0m")
|
215
|
-
exit(1)
|
216
|
-
|
217
|
-
elsif ENV['VERSION'] != ver
|
218
|
-
puts("\e[35mExpected \e[33mVERSION\e[35m=\e[33m#{ver} " \
|
219
|
-
"\e[35mbut got\n " \
|
220
|
-
"\e[33mVERSION\e[35m=\e[33m#{ENV['VERSION']}\e[0m")
|
221
|
-
exit(2)
|
222
|
-
end
|
288
|
+
Gemgem.gem_check
|
223
289
|
end
|
224
290
|
|
225
291
|
end # of gem namespace
|
226
292
|
|
227
293
|
desc 'Run tests'
|
228
294
|
task :test do
|
229
|
-
|
230
|
-
Gemgem.test_files.each{ |file| require "#{Gemgem.dir}/#{file[0..-4]}" }
|
295
|
+
Gemgem.test
|
231
296
|
end
|
232
297
|
|
233
298
|
desc 'Trash ignored files'
|
234
299
|
task :clean => ['gem:spec'] do
|
235
|
-
|
236
|
-
|
237
|
-
require 'fileutils'
|
238
|
-
trash = File.expand_path("~/.Trash/#{Gemgem.spec.name}")
|
239
|
-
puts "Move the following files into:" \
|
240
|
-
" \e[35m#{Gemgem.strip_path(trash)}\e[33m"
|
241
|
-
|
242
|
-
Gemgem.ignored_files.each do |file|
|
243
|
-
from = "#{Gemgem.dir}/#{file}"
|
244
|
-
to = "#{trash}/#{File.dirname(file)}"
|
245
|
-
puts Gemgem.strip_path(from)
|
246
|
-
|
247
|
-
FileUtils.mkdir_p(to)
|
248
|
-
FileUtils.mv(from, to)
|
249
|
-
end
|
250
|
-
|
251
|
-
print "\e[0m"
|
300
|
+
Gemgem.clean
|
252
301
|
end
|
253
302
|
|
254
303
|
task :default do
|
data/test/test_builder.rb
CHANGED
@@ -10,13 +10,13 @@ describe RC::Builder do
|
|
10
10
|
RC::Builder.new.to_app.should.kind_of? RC::Engine
|
11
11
|
end
|
12
12
|
|
13
|
-
would 'switch default_engine to RestCore::
|
13
|
+
would 'switch default_engine to RestCore::Dry a' do
|
14
14
|
builder = Class.new(RC::Builder)
|
15
|
-
builder.default_engine = RC::
|
16
|
-
builder.new.to_app.class.should.eq RC::
|
15
|
+
builder.default_engine = RC::Dry
|
16
|
+
builder.new.to_app.class.should.eq RC::Dry
|
17
17
|
end
|
18
18
|
|
19
|
-
would 'switch default_engine to RestCore::Dry' do
|
19
|
+
would 'switch default_engine to RestCore::Dry b' do
|
20
20
|
builder = RC::Builder.dup
|
21
21
|
builder.default_engine = RC::Dry
|
22
22
|
builder.client.new.app.class.should.eq RC::Dry
|
data/test/test_client.rb
CHANGED
@@ -137,7 +137,7 @@ describe RC::Simple do
|
|
137
137
|
client = Class.new(RC::Simple).new
|
138
138
|
stub_request(:get, url).to_return(:body => 'nnf')
|
139
139
|
|
140
|
-
(
|
140
|
+
(-1..1).each do |size|
|
141
141
|
mock(any_instance_of(RC::Promise)).warn(is_a(String)) do |msg|
|
142
142
|
msg.should.include?('nnf')
|
143
143
|
end
|
@@ -147,14 +147,6 @@ describe RC::Simple do
|
|
147
147
|
end
|
148
148
|
client.class.shutdown
|
149
149
|
end
|
150
|
-
|
151
|
-
client.class.pool_size = -1
|
152
|
-
should.raise do
|
153
|
-
client.get(url) do |body|
|
154
|
-
raise body
|
155
|
-
end
|
156
|
-
end.message.should.eq 'nnf'
|
157
|
-
client.class.shutdown
|
158
150
|
end
|
159
151
|
|
160
152
|
would 'be able to access caller outside the callback' do
|
@@ -1,14 +1,14 @@
|
|
1
1
|
|
2
2
|
require 'rest-core/test'
|
3
3
|
|
4
|
-
describe RC::
|
4
|
+
describe RC::HttpClient do
|
5
5
|
describe 'POST Payload' do
|
6
6
|
after do
|
7
7
|
WebMock.reset!
|
8
8
|
end
|
9
9
|
|
10
10
|
client = RC::Builder.client
|
11
|
-
client.builder.run(RC::
|
11
|
+
client.builder.run(RC::HttpClient)
|
12
12
|
path = 'http://example.com'
|
13
13
|
ok = 'OK'
|
14
14
|
c = client.new
|
@@ -39,24 +39,11 @@ describe RC::RestClient do
|
|
39
39
|
end
|
40
40
|
|
41
41
|
would 'not kill the thread if error was coming from the task' do
|
42
|
-
mock(
|
43
|
-
|
44
|
-
Muack.verify
|
45
|
-
end
|
46
|
-
|
47
|
-
would 'cancel the task if timing out' do
|
48
|
-
timer = Object.new.instance_eval do
|
49
|
-
def on_timeout; yield ; end
|
50
|
-
def error ; 'boom'; end
|
51
|
-
def cancel ; ; end
|
52
|
-
self
|
42
|
+
mock(any_instance_of(RC::Promise)).warn(is_a(String)) do |msg|
|
43
|
+
msg.should.include?('boom')
|
53
44
|
end
|
54
|
-
|
55
|
-
|
56
|
-
mock(RC::ThreadPool::Task).new.with_any_args.
|
57
|
-
peek_return{ |t| mock(t).cancel; t } # the task should be cancelled
|
58
|
-
c.request(RC::RESPONSE_KEY => RC::FAIL, RC::TIMER => timer).
|
59
|
-
first.message.should.eq 'boom'
|
45
|
+
mock(HTTPClient).new{ raise 'boom' }.with_any_args
|
46
|
+
c.request(RC::RESPONSE_KEY => RC::FAIL).first.message.should.eq 'boom'
|
60
47
|
Muack.verify
|
61
48
|
end
|
62
49
|
end
|
data/test/test_json_request.rb
CHANGED
@@ -3,7 +3,7 @@ require 'rest-core/test'
|
|
3
3
|
|
4
4
|
describe RC::JsonRequest do
|
5
5
|
app = RC::JsonRequest.new(RC::Dry.new, true)
|
6
|
-
env = {RC::REQUEST_HEADERS => {}}
|
6
|
+
env = {RC::REQUEST_HEADERS => {}, RC::REQUEST_METHOD => :post}
|
7
7
|
request_params = {
|
8
8
|
'key' => 'value',
|
9
9
|
'array' => [1, 2, 3],
|
@@ -21,9 +21,21 @@ describe RC::JsonRequest do
|
|
21
21
|
RC::REQUEST_PAYLOAD => RC::Json.encode(request_params))}
|
22
22
|
end
|
23
23
|
|
24
|
-
would '
|
25
|
-
|
26
|
-
|
24
|
+
would 'encode false and nil' do
|
25
|
+
[[nil, 'null'], [false, 'false'], [true, 'true']].each do |(value, exp)|
|
26
|
+
[:post, :put, :patch].each do |meth|
|
27
|
+
e = env.merge(RC::REQUEST_METHOD => meth,
|
28
|
+
RC::REQUEST_PAYLOAD => value)
|
29
|
+
app.call(e){ |res| res[RC::REQUEST_PAYLOAD].should.eq(exp) }
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
would 'do nothing for get, delete, head, options' do
|
35
|
+
[:get, :delete, :head, :options].each do |meth|
|
36
|
+
e = env.merge(RC::REQUEST_PAYLOAD => {}, RC::REQUEST_METHOD => meth)
|
37
|
+
app.call(e){ |res| res.should.eq e }
|
38
|
+
end
|
27
39
|
end
|
28
40
|
|
29
41
|
would 'do nothing if json_request is false' do
|
data/test/test_timeout.rb
CHANGED
@@ -1,5 +1,6 @@
|
|
1
1
|
|
2
2
|
require 'rest-core/test'
|
3
|
+
require 'rest-core/engine'
|
3
4
|
|
4
5
|
describe RC::Timeout do
|
5
6
|
app = RC::Timeout.new(RC::Dry.new, 0)
|
@@ -26,4 +27,57 @@ describe RC::Timeout do
|
|
26
27
|
lambda{ app.call(env){} }.should .raise(RuntimeError)
|
27
28
|
lambda{ sleep 0.01 }.should.not.raise(Timeout::Error)
|
28
29
|
end
|
30
|
+
|
31
|
+
would 'cancel the task if timing out' do
|
32
|
+
timer = Object.new.instance_eval do
|
33
|
+
def on_timeout; yield ; end
|
34
|
+
def error ; 'boom'; end
|
35
|
+
def cancel ; ; end
|
36
|
+
self
|
37
|
+
end
|
38
|
+
app = RC::Builder.client do
|
39
|
+
run Class.new(RC::Engine){
|
40
|
+
def request _, _
|
41
|
+
sleep
|
42
|
+
end
|
43
|
+
}
|
44
|
+
end
|
45
|
+
app.pool_size = 1
|
46
|
+
app.new.request(RC::RESPONSE_KEY => RC::FAIL, RC::TIMER => timer).
|
47
|
+
first.message.should.eq 'boom'
|
48
|
+
Muack.verify
|
49
|
+
end
|
50
|
+
|
51
|
+
would 'interrupt the task if timing out' do
|
52
|
+
rd, wr = IO.pipe
|
53
|
+
timer = Object.new.instance_eval do
|
54
|
+
define_singleton_method :on_timeout do |&block|
|
55
|
+
Thread.new do
|
56
|
+
rd.gets
|
57
|
+
block.call
|
58
|
+
end
|
59
|
+
end
|
60
|
+
def error ; 'boom'; end
|
61
|
+
def cancel ; ; end
|
62
|
+
self
|
63
|
+
end
|
64
|
+
app = RC::Builder.client do
|
65
|
+
run Class.new(RC::Engine){
|
66
|
+
def request _, env
|
67
|
+
env['pipe'].puts
|
68
|
+
sleep
|
69
|
+
end
|
70
|
+
}
|
71
|
+
end
|
72
|
+
(-1..1).each do |size|
|
73
|
+
mock(any_instance_of(RC::Promise)).warn(is_a(String)) do |msg|
|
74
|
+
msg.should.include?('boom')
|
75
|
+
end
|
76
|
+
app.pool_size = size
|
77
|
+
app.new.request(RC::RESPONSE_KEY => RC::FAIL, RC::TIMER => timer,
|
78
|
+
'pipe' => wr).
|
79
|
+
first.message.should.eq 'boom'
|
80
|
+
Muack.verify
|
81
|
+
end
|
82
|
+
end
|
29
83
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rest-core
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 3.
|
4
|
+
version: 3.4.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Lin Jen-Shin (godfat)
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2014-11-
|
11
|
+
date: 2014-11-26 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: httpclient
|
@@ -90,8 +90,6 @@ files:
|
|
90
90
|
- lib/rest-core/engine.rb
|
91
91
|
- lib/rest-core/engine/dry.rb
|
92
92
|
- lib/rest-core/engine/http-client.rb
|
93
|
-
- lib/rest-core/engine/net-http-persistent.rb
|
94
|
-
- lib/rest-core/engine/rest-client.rb
|
95
93
|
- lib/rest-core/error.rb
|
96
94
|
- lib/rest-core/event.rb
|
97
95
|
- lib/rest-core/event_source.rb
|
@@ -118,8 +116,6 @@ files:
|
|
118
116
|
- lib/rest-core/middleware/query_response.rb
|
119
117
|
- lib/rest-core/middleware/smash_response.rb
|
120
118
|
- lib/rest-core/middleware/timeout.rb
|
121
|
-
- lib/rest-core/patch/multi_json.rb
|
122
|
-
- lib/rest-core/patch/rest-client.rb
|
123
119
|
- lib/rest-core/promise.rb
|
124
120
|
- lib/rest-core/test.rb
|
125
121
|
- lib/rest-core/thread_pool.rb
|
@@ -155,6 +151,7 @@ files:
|
|
155
151
|
- test/test_event_source.rb
|
156
152
|
- test/test_follow_redirect.rb
|
157
153
|
- test/test_future.rb
|
154
|
+
- test/test_httpclient.rb
|
158
155
|
- test/test_json_request.rb
|
159
156
|
- test/test_json_response.rb
|
160
157
|
- test/test_oauth1_header.rb
|
@@ -163,7 +160,6 @@ files:
|
|
163
160
|
- test/test_payload.rb
|
164
161
|
- test/test_promise.rb
|
165
162
|
- test/test_query_response.rb
|
166
|
-
- test/test_rest-client.rb
|
167
163
|
- test/test_simple.rb
|
168
164
|
- test/test_smash.rb
|
169
165
|
- test/test_smash_response.rb
|
@@ -190,7 +186,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
190
186
|
version: '0'
|
191
187
|
requirements: []
|
192
188
|
rubyforge_project:
|
193
|
-
rubygems_version: 2.4.
|
189
|
+
rubygems_version: 2.4.4
|
194
190
|
signing_key:
|
195
191
|
specification_version: 4
|
196
192
|
summary: Modular Ruby clients interface for REST APIs.
|
@@ -213,6 +209,7 @@ test_files:
|
|
213
209
|
- test/test_event_source.rb
|
214
210
|
- test/test_follow_redirect.rb
|
215
211
|
- test/test_future.rb
|
212
|
+
- test/test_httpclient.rb
|
216
213
|
- test/test_json_request.rb
|
217
214
|
- test/test_json_response.rb
|
218
215
|
- test/test_oauth1_header.rb
|
@@ -221,7 +218,6 @@ test_files:
|
|
221
218
|
- test/test_payload.rb
|
222
219
|
- test/test_promise.rb
|
223
220
|
- test/test_query_response.rb
|
224
|
-
- test/test_rest-client.rb
|
225
221
|
- test/test_simple.rb
|
226
222
|
- test/test_smash.rb
|
227
223
|
- test/test_smash_response.rb
|
@@ -1,21 +0,0 @@
|
|
1
|
-
|
2
|
-
require 'net/http/persistent'
|
3
|
-
require 'rest-core/engine'
|
4
|
-
|
5
|
-
class RestCore::NetHttpPersistent < RestCore::Engine
|
6
|
-
def request promise, env
|
7
|
-
http = ::Net::HTTP::Persistent.new
|
8
|
-
http.open_timeout, http.read_timeout = calculate_timeout(env[TIMER])
|
9
|
-
payload, headers = payload_and_headers(env)
|
10
|
-
|
11
|
-
uri = ::URI.parse(env[REQUEST_URI])
|
12
|
-
req = ::Net::HTTP.const_get(env[REQUEST_METHOD].to_s.capitalize).
|
13
|
-
new(uri, headers)
|
14
|
-
req.body_stream = payload
|
15
|
-
res = http.request(uri, req)
|
16
|
-
|
17
|
-
promise.fulfill(res.body, res.code.to_i, normalize_headers(res.to_hash))
|
18
|
-
rescue Exception => e
|
19
|
-
promise.reject(e)
|
20
|
-
end
|
21
|
-
end
|
@@ -1,29 +0,0 @@
|
|
1
|
-
|
2
|
-
require 'restclient'
|
3
|
-
require 'rest-core/patch/rest-client'
|
4
|
-
require 'rest-core/engine'
|
5
|
-
|
6
|
-
class RestCore::RestClient < RestCore::Engine
|
7
|
-
def request promise, env
|
8
|
-
open_timeout, read_timeout = calculate_timeout(env[TIMER])
|
9
|
-
payload, headers = payload_and_headers(env)
|
10
|
-
res = ::RestClient::Request.execute(:method => env[REQUEST_METHOD],
|
11
|
-
:url => env[REQUEST_URI] ,
|
12
|
-
:payload => payload ,
|
13
|
-
:headers => headers ,
|
14
|
-
:max_redirects => 0 ,
|
15
|
-
:open_timeout => open_timeout ,
|
16
|
-
:timeout => read_timeout )
|
17
|
-
promise.fulfill(res.body, res.code, normalize_headers(res.raw_headers))
|
18
|
-
rescue ::RestClient::Exception => e
|
19
|
-
if res = e.response
|
20
|
-
# we don't want to raise an exception for 404 requests
|
21
|
-
promise.fulfill(res.body, res.code, normalize_headers(res.raw_headers))
|
22
|
-
else
|
23
|
-
promise.reject(e)
|
24
|
-
end
|
25
|
-
|
26
|
-
rescue Exception => e
|
27
|
-
promise.reject(e)
|
28
|
-
end
|
29
|
-
end
|
@@ -1,35 +0,0 @@
|
|
1
|
-
|
2
|
-
module RestClient
|
3
|
-
module AbstractResponse
|
4
|
-
# begin patch
|
5
|
-
# https://github.com/archiloque/rest-client/pull/103
|
6
|
-
remove_method :to_i if method_defined?(:to_i)
|
7
|
-
# end patch
|
8
|
-
|
9
|
-
# Follow a redirection
|
10
|
-
def follow_redirection request = nil, result = nil, & block
|
11
|
-
url = headers[:location]
|
12
|
-
if url !~ /^http/u
|
13
|
-
url = URI.parse(args[:url]).merge(url).to_s
|
14
|
-
end
|
15
|
-
args[:url] = url
|
16
|
-
if request
|
17
|
-
if request.max_redirects == 0
|
18
|
-
# begin patch
|
19
|
-
# https://github.com/archiloque/rest-client/pull/118
|
20
|
-
raise MaxRedirectsReached.new(self, code)
|
21
|
-
# end patch
|
22
|
-
end
|
23
|
-
args[:password] = request.password
|
24
|
-
args[:user] = request.user
|
25
|
-
args[:headers] = request.headers
|
26
|
-
args[:max_redirects] = request.max_redirects - 1
|
27
|
-
# pass any cookie set in the result
|
28
|
-
if result && result['set-cookie']
|
29
|
-
args[:headers][:cookies] = (args[:headers][:cookies] || {}).merge(parse_cookie(result['set-cookie']))
|
30
|
-
end
|
31
|
-
end
|
32
|
-
Request.execute args, &block
|
33
|
-
end
|
34
|
-
end
|
35
|
-
end
|