rest-core 3.3.3 → 3.4.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 -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 [![Build Status](https://secure.travis-ci.org/godfat/rest-core.png?branch=master)](http://travis-ci.org/godfat/rest-core)
|
1
|
+
# rest-core [![Build Status](https://secure.travis-ci.org/godfat/rest-core.png?branch=master)](http://travis-ci.org/godfat/rest-core) [![Coverage Status](https://coveralls.io/repos/godfat/rest-core/badge.png)](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
|