rest-core 3.6.0 → 4.0.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|