rest-core 3.6.0 → 4.0.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/.gitmodules +3 -0
- data/.travis.yml +0 -1
- data/CHANGES.md +28 -0
- data/Gemfile +0 -2
- data/README.md +14 -95
- data/Rakefile +16 -3
- data/example/simple.rb +1 -0
- data/example/use-cases.rb +15 -3
- data/lib/rest-core.rb +38 -75
- data/lib/rest-core/client/universal.rb +3 -1
- data/lib/rest-core/client_oauth1.rb +64 -59
- data/lib/rest-core/event.rb +9 -11
- data/lib/rest-core/middleware/auth_basic.rb +21 -21
- data/lib/rest-core/middleware/bypass.rb +8 -8
- data/lib/rest-core/middleware/cache.rb +94 -90
- data/lib/rest-core/middleware/clash_response.rb +15 -14
- data/lib/rest-core/middleware/common_logger.rb +27 -26
- data/lib/rest-core/middleware/default_headers.rb +8 -8
- data/lib/rest-core/middleware/default_payload.rb +8 -8
- data/lib/rest-core/middleware/default_query.rb +8 -8
- data/lib/rest-core/middleware/default_site.rb +12 -12
- data/lib/rest-core/middleware/defaults.rb +38 -38
- data/lib/rest-core/middleware/error_detector.rb +10 -10
- data/lib/rest-core/middleware/error_detector_http.rb +6 -4
- data/lib/rest-core/middleware/error_handler.rb +14 -14
- data/lib/rest-core/middleware/follow_redirect.rb +28 -27
- data/lib/rest-core/middleware/json_request.rb +13 -11
- data/lib/rest-core/middleware/json_response.rb +29 -28
- data/lib/rest-core/middleware/oauth1_header.rb +84 -83
- data/lib/rest-core/middleware/oauth2_header.rb +27 -25
- data/lib/rest-core/middleware/oauth2_query.rb +15 -15
- data/lib/rest-core/middleware/query_response.rb +14 -14
- data/lib/rest-core/middleware/retry.rb +25 -23
- data/lib/rest-core/middleware/smash_response.rb +15 -14
- data/lib/rest-core/middleware/timeout.rb +18 -19
- data/lib/rest-core/test.rb +1 -18
- data/lib/rest-core/util/clash.rb +38 -37
- data/lib/rest-core/util/config.rb +40 -39
- data/lib/rest-core/util/dalli_extension.rb +11 -10
- data/lib/rest-core/util/hmac.rb +9 -8
- data/lib/rest-core/util/json.rb +55 -54
- data/lib/rest-core/util/parse_link.rb +13 -12
- data/lib/rest-core/util/parse_query.rb +24 -22
- data/lib/rest-core/version.rb +1 -1
- data/rest-core.gemspec +121 -158
- data/test/test_cache.rb +2 -0
- data/test/test_default_payload.rb +1 -1
- data/test/test_error_handler.rb +5 -4
- data/test/test_timeout.rb +9 -8
- data/test/test_universal.rb +8 -0
- metadata +9 -73
- data/lib/rest-core/builder.rb +0 -162
- data/lib/rest-core/client.rb +0 -277
- data/lib/rest-core/client/simple.rb +0 -2
- data/lib/rest-core/engine.rb +0 -36
- data/lib/rest-core/engine/dry.rb +0 -9
- data/lib/rest-core/engine/http-client.rb +0 -41
- data/lib/rest-core/error.rb +0 -5
- data/lib/rest-core/event_source.rb +0 -137
- data/lib/rest-core/middleware.rb +0 -151
- data/lib/rest-core/promise.rb +0 -249
- data/lib/rest-core/thread_pool.rb +0 -131
- data/lib/rest-core/timer.rb +0 -58
- data/lib/rest-core/util/payload.rb +0 -173
- data/test/test_builder.rb +0 -40
- data/test/test_client.rb +0 -177
- data/test/test_event_source.rb +0 -159
- data/test/test_future.rb +0 -16
- data/test/test_httpclient.rb +0 -118
- data/test/test_payload.rb +0 -204
- data/test/test_promise.rb +0 -146
- data/test/test_simple.rb +0 -38
- data/test/test_thread_pool.rb +0 -10
@@ -1,21 +1,22 @@
|
|
1
1
|
|
2
|
-
require 'rest-core/middleware'
|
3
2
|
require 'rest-core/util/clash'
|
4
3
|
|
5
|
-
|
6
|
-
|
7
|
-
|
4
|
+
module RestCore
|
5
|
+
class ClashResponse
|
6
|
+
def self.members; [:clash_response]; end
|
7
|
+
include Middleware
|
8
8
|
|
9
|
-
|
10
|
-
|
11
|
-
|
9
|
+
def call env, &k
|
10
|
+
return app.call(env, &k) if env[DRY]
|
11
|
+
return app.call(env, &k) unless clash_response(env)
|
12
12
|
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
13
|
+
app.call(env){ |res|
|
14
|
+
if res[RESPONSE_BODY].kind_of?(Hash)
|
15
|
+
yield(res.merge(RESPONSE_BODY => Clash.new(res[RESPONSE_BODY])))
|
16
|
+
else
|
17
|
+
yield(res)
|
18
|
+
end
|
19
|
+
}
|
20
|
+
end
|
20
21
|
end
|
21
22
|
end
|
@@ -1,35 +1,36 @@
|
|
1
1
|
|
2
2
|
require 'rest-core/event'
|
3
|
-
require 'rest-core/middleware'
|
4
3
|
|
5
|
-
|
6
|
-
|
7
|
-
|
4
|
+
module RestCore
|
5
|
+
class CommonLogger
|
6
|
+
def self.members; [:log_method]; end
|
7
|
+
include Middleware
|
8
8
|
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
9
|
+
def call env
|
10
|
+
start_time = Time.now
|
11
|
+
flushed = flush(env)
|
12
|
+
app.call(flushed){ |response|
|
13
|
+
yield(process(response, start_time))
|
14
|
+
}
|
15
|
+
rescue
|
16
|
+
process(flushed, start_time)
|
17
|
+
raise
|
18
|
+
end
|
19
19
|
|
20
|
-
|
21
|
-
|
22
|
-
|
20
|
+
def process response, start_time
|
21
|
+
flush(log(response, log_request(start_time, response)))
|
22
|
+
end
|
23
23
|
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
24
|
+
def flush env
|
25
|
+
return env if !log_method(env) || env[DRY]
|
26
|
+
(env[LOG] || []).compact.
|
27
|
+
each{ |obj| log_method(env).call("RestCore: #{obj}") }
|
28
|
+
env.merge(LOG => [])
|
29
|
+
end
|
30
30
|
|
31
|
-
|
32
|
-
|
33
|
-
|
31
|
+
def log_request start_time, response
|
32
|
+
Event::Requested.new(Time.now - start_time,
|
33
|
+
"#{response[REQUEST_METHOD].to_s.upcase} #{request_uri(response)}")
|
34
|
+
end
|
34
35
|
end
|
35
36
|
end
|
@@ -1,11 +1,11 @@
|
|
1
1
|
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
2
|
+
module RestCore
|
3
|
+
class DefaultHeaders
|
4
|
+
def self.members; [:headers]; end
|
5
|
+
include Middleware
|
6
|
+
def call env, &k
|
7
|
+
h = merge_hash(@headers, headers(env), env[REQUEST_HEADERS])
|
8
|
+
app.call(env.merge(REQUEST_HEADERS => h), &k)
|
9
|
+
end
|
10
10
|
end
|
11
11
|
end
|
@@ -1,11 +1,11 @@
|
|
1
1
|
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
2
|
+
module RestCore
|
3
|
+
class DefaultPayload
|
4
|
+
def self.members; [:payload]; end
|
5
|
+
include Middleware
|
6
|
+
def call env, &k
|
7
|
+
p = merge_hash(@payload, payload(env), env[REQUEST_PAYLOAD])
|
8
|
+
app.call(env.merge(REQUEST_PAYLOAD => p), &k)
|
9
|
+
end
|
10
10
|
end
|
11
11
|
end
|
@@ -1,11 +1,11 @@
|
|
1
1
|
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
2
|
+
module RestCore
|
3
|
+
class DefaultQuery
|
4
|
+
def self.members; [:query]; end
|
5
|
+
include Middleware
|
6
|
+
def call env, &k
|
7
|
+
q = merge_hash(@query, query(env), env[REQUEST_QUERY])
|
8
|
+
app.call(env.merge(REQUEST_QUERY => q), &k)
|
9
|
+
end
|
10
10
|
end
|
11
11
|
end
|
@@ -1,17 +1,17 @@
|
|
1
1
|
|
2
|
-
|
2
|
+
module RestCore
|
3
|
+
class DefaultSite
|
4
|
+
def self.members; [:site]; end
|
5
|
+
include Middleware
|
3
6
|
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
+
def call env, &k
|
8
|
+
path = if env[REQUEST_PATH].to_s.include?('://')
|
9
|
+
env[REQUEST_PATH]
|
10
|
+
else
|
11
|
+
File.join(site(env).to_s, env[REQUEST_PATH].to_s)
|
12
|
+
end
|
7
13
|
|
8
|
-
|
9
|
-
|
10
|
-
env[REQUEST_PATH]
|
11
|
-
else
|
12
|
-
File.join(site(env).to_s, env[REQUEST_PATH].to_s)
|
13
|
-
end
|
14
|
-
|
15
|
-
app.call(env.merge(REQUEST_PATH => path), &k)
|
14
|
+
app.call(env.merge(REQUEST_PATH => path), &k)
|
15
|
+
end
|
16
16
|
end
|
17
17
|
end
|
@@ -1,46 +1,46 @@
|
|
1
1
|
|
2
|
-
|
2
|
+
module RestCore
|
3
|
+
class Defaults
|
4
|
+
def self.members; [:defaults]; end
|
5
|
+
include Middleware
|
3
6
|
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
+
# the use of singleton_class is making serialization hard!
|
8
|
+
# def initialize app, defaults
|
9
|
+
# super
|
10
|
+
# singleton_class.module_eval do
|
11
|
+
# defaults.each{ |(key, value)|
|
12
|
+
# define_method(key) do |env|
|
13
|
+
# if value.respond_to?(:call)
|
14
|
+
# value.call
|
15
|
+
# else
|
16
|
+
# value
|
17
|
+
# end
|
18
|
+
# end
|
19
|
+
# }
|
20
|
+
# end
|
21
|
+
# end
|
7
22
|
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
# value.call
|
16
|
-
# else
|
17
|
-
# value
|
18
|
-
# end
|
19
|
-
# end
|
20
|
-
# }
|
21
|
-
# end
|
22
|
-
# end
|
23
|
-
|
24
|
-
def method_missing msg, *args, &block
|
25
|
-
env = args.first
|
26
|
-
if env.kind_of?(Hash) && (d = defaults(env)) && d.key?(msg)
|
27
|
-
defaults(env)[msg]
|
28
|
-
else
|
29
|
-
super
|
23
|
+
def method_missing msg, *args, &block
|
24
|
+
env = args.first
|
25
|
+
if env.kind_of?(Hash) && (d = defaults(env)) && d.key?(msg)
|
26
|
+
defaults(env)[msg]
|
27
|
+
else
|
28
|
+
super
|
29
|
+
end
|
30
30
|
end
|
31
|
-
end
|
32
31
|
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
32
|
+
def respond_to_missing? msg, include_private=false
|
33
|
+
# since psych would call respond_to? before setting up
|
34
|
+
# instance variables when restoring ruby objects, we might
|
35
|
+
# be accessing undefined ivars in that case even all ivars are
|
36
|
+
# defined in initialize. we can't avoid this because we can't
|
37
|
+
# use singleton_class (otherwise we can't serialize this)
|
38
|
+
return super unless instance_variable_defined?(:@defaults)
|
39
|
+
if (d = defaults({})) && d.key?(msg)
|
40
|
+
true
|
41
|
+
else
|
42
|
+
super
|
43
|
+
end
|
44
44
|
end
|
45
45
|
end
|
46
46
|
end
|
@@ -1,14 +1,14 @@
|
|
1
1
|
|
2
|
-
|
2
|
+
module RestCore
|
3
|
+
class ErrorDetector
|
4
|
+
def self.members; [:error_detector]; end
|
5
|
+
include Middleware
|
3
6
|
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
detector = error_detector(env)
|
11
|
-
yield(fail(response, detector && detector.call(response)))
|
12
|
-
}
|
7
|
+
def call env
|
8
|
+
app.call(env){ |response|
|
9
|
+
detector = error_detector(env)
|
10
|
+
yield(fail(response, detector && detector.call(response)))
|
11
|
+
}
|
12
|
+
end
|
13
13
|
end
|
14
14
|
end
|
@@ -1,9 +1,11 @@
|
|
1
1
|
|
2
2
|
require 'rest-core/middleware/error_detector'
|
3
3
|
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
4
|
+
module RestCore
|
5
|
+
class ErrorDetectorHttp < RestCore::ErrorDetector
|
6
|
+
def initialize app, detector=nil
|
7
|
+
super(app, detector ||
|
8
|
+
lambda{ |env| (env[RESPONSE_STATUS] || 200) / 100 >= 4 })
|
9
|
+
end
|
8
10
|
end
|
9
11
|
end
|
@@ -1,18 +1,18 @@
|
|
1
1
|
|
2
|
-
|
2
|
+
module RestCore
|
3
|
+
class ErrorHandler
|
4
|
+
def self.members; [:error_handler]; end
|
5
|
+
include Middleware
|
3
6
|
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
else
|
15
|
-
fail(res, h.call(res))
|
16
|
-
end)}
|
7
|
+
def call env
|
8
|
+
app.call(env){ |res|
|
9
|
+
h = error_handler(res)
|
10
|
+
f = res[FAIL] || []
|
11
|
+
yield(if f.empty? || f.find{ |ff| ff.kind_of?(Exception) } || !h
|
12
|
+
res
|
13
|
+
else
|
14
|
+
fail(res, h.call(res))
|
15
|
+
end)}
|
16
|
+
end
|
17
17
|
end
|
18
18
|
end
|
@@ -1,35 +1,36 @@
|
|
1
1
|
|
2
|
-
|
2
|
+
module RestCore
|
3
|
+
class FollowRedirect
|
4
|
+
def self.members; [:max_redirects]; end
|
5
|
+
include Middleware
|
3
6
|
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
app.call(env, &k)
|
11
|
-
else
|
12
|
-
app.call(env){ |res| process(res, k) }
|
7
|
+
def call env, &k
|
8
|
+
if env[DRY]
|
9
|
+
app.call(env, &k)
|
10
|
+
else
|
11
|
+
app.call(env){ |res| process(res, k) }
|
12
|
+
end
|
13
13
|
end
|
14
|
-
end
|
15
14
|
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
15
|
+
def process res, k
|
16
|
+
return k.call(res) if max_redirects(res) <= 0
|
17
|
+
status = res[RESPONSE_STATUS]
|
18
|
+
return k.call(res) if ![301,302,303,307].include?(status)
|
19
|
+
return k.call(res) if [301,302 ,307].include?(status) &&
|
20
|
+
![:get, :head ].include?(res[REQUEST_METHOD])
|
21
21
|
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
22
|
+
location = [res[RESPONSE_HEADERS]['LOCATION']].flatten.first
|
23
|
+
meth = if status == 303
|
24
|
+
:get
|
25
|
+
else
|
26
|
+
res[REQUEST_METHOD]
|
27
|
+
end
|
28
28
|
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
29
|
+
give_promise(call(res.merge(
|
30
|
+
REQUEST_METHOD => meth ,
|
31
|
+
REQUEST_PATH => location,
|
32
|
+
REQUEST_QUERY => {} ,
|
33
|
+
'max_redirects' => max_redirects(res) - 1), &k))
|
34
|
+
end
|
34
35
|
end
|
35
36
|
end
|
@@ -1,19 +1,21 @@
|
|
1
1
|
|
2
|
-
require 'rest-core/middleware'
|
3
2
|
require 'rest-core/util/json'
|
4
3
|
|
5
|
-
|
6
|
-
|
7
|
-
|
4
|
+
module RestCore
|
5
|
+
class JsonRequest
|
6
|
+
def self.members; [:json_request]; end
|
7
|
+
include Middleware
|
8
8
|
|
9
|
-
|
9
|
+
JSON_REQUEST_HEADER = {'Content-Type' => 'application/json'}.freeze
|
10
10
|
|
11
|
-
|
12
|
-
|
13
|
-
|
11
|
+
def call env, &k
|
12
|
+
return app.call(env, &k) unless json_request(env)
|
13
|
+
return app.call(env, &k) unless has_payload?(env)
|
14
14
|
|
15
|
-
|
16
|
-
|
17
|
-
|
15
|
+
headers = env[REQUEST_HEADERS] || {}
|
16
|
+
app.call(env.merge(
|
17
|
+
REQUEST_HEADERS => JSON_REQUEST_HEADER.merge(headers),
|
18
|
+
REQUEST_PAYLOAD => Json.encode(env[REQUEST_PAYLOAD])), &k)
|
19
|
+
end
|
18
20
|
end
|
19
21
|
end
|