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.
Files changed (74) hide show
  1. checksums.yaml +4 -4
  2. data/.gitmodules +3 -0
  3. data/.travis.yml +0 -1
  4. data/CHANGES.md +28 -0
  5. data/Gemfile +0 -2
  6. data/README.md +14 -95
  7. data/Rakefile +16 -3
  8. data/example/simple.rb +1 -0
  9. data/example/use-cases.rb +15 -3
  10. data/lib/rest-core.rb +38 -75
  11. data/lib/rest-core/client/universal.rb +3 -1
  12. data/lib/rest-core/client_oauth1.rb +64 -59
  13. data/lib/rest-core/event.rb +9 -11
  14. data/lib/rest-core/middleware/auth_basic.rb +21 -21
  15. data/lib/rest-core/middleware/bypass.rb +8 -8
  16. data/lib/rest-core/middleware/cache.rb +94 -90
  17. data/lib/rest-core/middleware/clash_response.rb +15 -14
  18. data/lib/rest-core/middleware/common_logger.rb +27 -26
  19. data/lib/rest-core/middleware/default_headers.rb +8 -8
  20. data/lib/rest-core/middleware/default_payload.rb +8 -8
  21. data/lib/rest-core/middleware/default_query.rb +8 -8
  22. data/lib/rest-core/middleware/default_site.rb +12 -12
  23. data/lib/rest-core/middleware/defaults.rb +38 -38
  24. data/lib/rest-core/middleware/error_detector.rb +10 -10
  25. data/lib/rest-core/middleware/error_detector_http.rb +6 -4
  26. data/lib/rest-core/middleware/error_handler.rb +14 -14
  27. data/lib/rest-core/middleware/follow_redirect.rb +28 -27
  28. data/lib/rest-core/middleware/json_request.rb +13 -11
  29. data/lib/rest-core/middleware/json_response.rb +29 -28
  30. data/lib/rest-core/middleware/oauth1_header.rb +84 -83
  31. data/lib/rest-core/middleware/oauth2_header.rb +27 -25
  32. data/lib/rest-core/middleware/oauth2_query.rb +15 -15
  33. data/lib/rest-core/middleware/query_response.rb +14 -14
  34. data/lib/rest-core/middleware/retry.rb +25 -23
  35. data/lib/rest-core/middleware/smash_response.rb +15 -14
  36. data/lib/rest-core/middleware/timeout.rb +18 -19
  37. data/lib/rest-core/test.rb +1 -18
  38. data/lib/rest-core/util/clash.rb +38 -37
  39. data/lib/rest-core/util/config.rb +40 -39
  40. data/lib/rest-core/util/dalli_extension.rb +11 -10
  41. data/lib/rest-core/util/hmac.rb +9 -8
  42. data/lib/rest-core/util/json.rb +55 -54
  43. data/lib/rest-core/util/parse_link.rb +13 -12
  44. data/lib/rest-core/util/parse_query.rb +24 -22
  45. data/lib/rest-core/version.rb +1 -1
  46. data/rest-core.gemspec +121 -158
  47. data/test/test_cache.rb +2 -0
  48. data/test/test_default_payload.rb +1 -1
  49. data/test/test_error_handler.rb +5 -4
  50. data/test/test_timeout.rb +9 -8
  51. data/test/test_universal.rb +8 -0
  52. metadata +9 -73
  53. data/lib/rest-core/builder.rb +0 -162
  54. data/lib/rest-core/client.rb +0 -277
  55. data/lib/rest-core/client/simple.rb +0 -2
  56. data/lib/rest-core/engine.rb +0 -36
  57. data/lib/rest-core/engine/dry.rb +0 -9
  58. data/lib/rest-core/engine/http-client.rb +0 -41
  59. data/lib/rest-core/error.rb +0 -5
  60. data/lib/rest-core/event_source.rb +0 -137
  61. data/lib/rest-core/middleware.rb +0 -151
  62. data/lib/rest-core/promise.rb +0 -249
  63. data/lib/rest-core/thread_pool.rb +0 -131
  64. data/lib/rest-core/timer.rb +0 -58
  65. data/lib/rest-core/util/payload.rb +0 -173
  66. data/test/test_builder.rb +0 -40
  67. data/test/test_client.rb +0 -177
  68. data/test/test_event_source.rb +0 -159
  69. data/test/test_future.rb +0 -16
  70. data/test/test_httpclient.rb +0 -118
  71. data/test/test_payload.rb +0 -204
  72. data/test/test_promise.rb +0 -146
  73. data/test/test_simple.rb +0 -38
  74. data/test/test_thread_pool.rb +0 -10
@@ -1,75 +1,80 @@
1
1
 
2
- require 'rest-core'
2
+ require 'digest/md5'
3
3
 
4
- module RestCore::ClientOauth1
5
- include RestCore
4
+ require 'rest-core/util/parse_query'
5
+ require 'rest-core/util/json'
6
6
 
7
- def authorize_url! opts={}
8
- self.data = ParseQuery.parse_query(
9
- post(request_token_path, {}, {}, {:json_response => false}.merge(opts)))
7
+ module RestCore
8
+ module ClientOauth1
9
+ def authorize_url! opts={}
10
+ self.data = ParseQuery.parse_query(
11
+ post(request_token_path, {}, {},
12
+ {:json_response => false}.merge(opts)))
10
13
 
11
- authorize_url
12
- end
14
+ authorize_url
15
+ end
13
16
 
14
- def authorize_url
15
- url(authorize_path, :oauth_token => oauth_token)
16
- end
17
+ def authorize_url
18
+ url(authorize_path, :oauth_token => oauth_token)
19
+ end
17
20
 
18
- def authorize! opts={}
19
- self.data = ParseQuery.parse_query(
20
- post(access_token_path, {}, {}, {:json_response => false}.merge(opts)))
21
+ def authorize! opts={}
22
+ self.data = ParseQuery.parse_query(
23
+ post(access_token_path, {}, {},
24
+ {:json_response => false}.merge(opts)))
21
25
 
22
- data['authorized'] = 'true'
23
- data
24
- end
26
+ data['authorized'] = 'true'
27
+ data
28
+ end
25
29
 
26
- def authorized?
27
- !!(oauth_token && oauth_token_secret && data['authorized'])
28
- end
30
+ def authorized?
31
+ !!(oauth_token && oauth_token_secret && data['authorized'])
32
+ end
29
33
 
30
- def data_json
31
- Json.encode(data.merge('sig' => calculate_sig))
32
- end
34
+ def data_json
35
+ Json.encode(data.merge('sig' => calculate_sig))
36
+ end
33
37
 
34
- def data_json= json
35
- self.data = check_sig_and_return_data(Json.decode(json))
36
- rescue Json.const_get(:ParseError)
37
- self.data = nil
38
- end
38
+ def data_json= json
39
+ self.data = check_sig_and_return_data(Json.decode(json))
40
+ rescue Json.const_get(:ParseError)
41
+ self.data = nil
42
+ end
39
43
 
40
- def oauth_token
41
- data['oauth_token'] if data.kind_of?(Hash)
42
- end
43
- def oauth_token= token
44
- data['oauth_token'] = token if data.kind_of?(Hash)
45
- end
46
- def oauth_token_secret
47
- data['oauth_token_secret'] if data.kind_of?(Hash)
48
- end
49
- def oauth_token_secret= secret
50
- data['oauth_token_secret'] = secret if data.kind_of?(Hash)
51
- end
52
- def oauth_callback
53
- data['oauth_callback'] if data.kind_of?(Hash)
54
- end
55
- def oauth_callback= uri
56
- data['oauth_callback'] = uri if data.kind_of?(Hash)
57
- end
44
+ def oauth_token
45
+ data['oauth_token'] if data.kind_of?(Hash)
46
+ end
47
+ def oauth_token= token
48
+ data['oauth_token'] = token if data.kind_of?(Hash)
49
+ end
50
+ def oauth_token_secret
51
+ data['oauth_token_secret'] if data.kind_of?(Hash)
52
+ end
53
+ def oauth_token_secret= secret
54
+ data['oauth_token_secret'] = secret if data.kind_of?(Hash)
55
+ end
56
+ def oauth_callback
57
+ data['oauth_callback'] if data.kind_of?(Hash)
58
+ end
59
+ def oauth_callback= uri
60
+ data['oauth_callback'] = uri if data.kind_of?(Hash)
61
+ end
58
62
 
59
- private
60
- def default_data
61
- {}
62
- end
63
+ private
64
+ def default_data
65
+ {}
66
+ end
63
67
 
64
- def check_sig_and_return_data hash
65
- hash if consumer_secret && hash.kind_of?(Hash) &&
66
- calculate_sig(hash) == hash['sig']
67
- end
68
+ def check_sig_and_return_data hash
69
+ hash if consumer_secret && hash.kind_of?(Hash) &&
70
+ calculate_sig(hash) == hash['sig']
71
+ end
68
72
 
69
- def calculate_sig hash=data
70
- base = hash.reject{ |(k, _)| k == 'sig' }.sort.map{ |(k, v)|
71
- "#{Middleware.escape(k.to_s)}=#{Middleware.escape(v.to_s)}"
72
- }.join('&')
73
- Digest::MD5.hexdigest("#{Middleware.escape(consumer_secret)}&#{base}")
73
+ def calculate_sig hash=data
74
+ base = hash.reject{ |(k, _)| k == 'sig' }.sort.map{ |(k, v)|
75
+ "#{Middleware.escape(k.to_s)}=#{Middleware.escape(v.to_s)}"
76
+ }.join('&')
77
+ Digest::MD5.hexdigest("#{Middleware.escape(consumer_secret)}&#{base}")
78
+ end
74
79
  end
75
80
  end
@@ -1,9 +1,6 @@
1
1
 
2
2
  module RestCore
3
- EventStruct = Struct.new(:duration, :message) unless
4
- RestCore.const_defined?(:EventStruct)
5
-
6
- class Event < EventStruct
3
+ class Event < Struct.new(:duration, :message)
7
4
  def name; self.class.name[/(?<=::)\w+$/]; end
8
5
  def to_s
9
6
  if duration
@@ -13,11 +10,12 @@ module RestCore
13
10
  end
14
11
  end
15
12
  end
16
- class Event::MultiDone < Event; end
17
- class Event::Requested < Event; end
18
- class Event::CacheHit < Event; end
19
- class Event::CacheCleared < Event; end
20
- class Event::Failed < Event; end
21
- class Event::WithHeader < Event; end
22
- class Event::Retrying < Event; end
13
+
14
+ Event::MultiDone = Class.new(Event)
15
+ Event::Requested = Class.new(Event)
16
+ Event::CacheHit = Class.new(Event)
17
+ Event::CacheCleared = Class.new(Event)
18
+ Event::Failed = Class.new(Event)
19
+ Event::WithHeader = Class.new(Event)
20
+ Event::Retrying = Class.new(Event)
23
21
  end
@@ -1,29 +1,29 @@
1
1
 
2
- require 'rest-core/middleware'
2
+ module RestCore
3
+ class AuthBasic
4
+ def self.members; [:username, :password]; end
5
+ include Middleware
3
6
 
4
- class RestCore::AuthBasic
5
- def self.members; [:username, :password]; end
6
- include RestCore::Middleware
7
-
8
- def call env, &k
9
- if username(env)
10
- if password(env)
11
- app.call(env.merge(REQUEST_HEADERS =>
12
- auth_basic_header(env).merge(env[REQUEST_HEADERS])), &k)
7
+ def call env, &k
8
+ if username(env)
9
+ if password(env)
10
+ app.call(env.merge(REQUEST_HEADERS =>
11
+ auth_basic_header(env).merge(env[REQUEST_HEADERS])), &k)
12
+ else
13
+ app.call(log(env, "AuthBasic: username provided: #{username(env)},"\
14
+ " but password is missing."), &k)
15
+ end
16
+ elsif password(env)
17
+ app.call(log(env, "AuthBasic: password provided: #{password(env)}," \
18
+ " but username is missing."), &k)
13
19
  else
14
- app.call(log(env, "AuthBasic: username provided: #{username(env)}," \
15
- " but password is missing."), &k)
20
+ app.call(env, &k)
16
21
  end
17
- elsif password(env)
18
- app.call(log(env, "AuthBasic: password provided: #{password(env)}," \
19
- " but username is missing."), &k)
20
- else
21
- app.call(env, &k)
22
22
  end
23
- end
24
23
 
25
- def auth_basic_header env
26
- {'Authorization' =>
27
- "Basic #{["#{username(env)}:#{password(env)}"].pack('m0')}"}
24
+ def auth_basic_header env
25
+ {'Authorization' =>
26
+ "Basic #{["#{username(env)}:#{password(env)}"].pack('m0')}"}
27
+ end
28
28
  end
29
29
  end
@@ -1,13 +1,13 @@
1
1
 
2
- module RestCore; end
3
-
4
2
  # the simplest middleware
5
- class RestCore::Bypass
6
- def initialize app
7
- @app = app
8
- end
3
+ module RestCore
4
+ class Bypass
5
+ def initialize app
6
+ @app = app
7
+ end
9
8
 
10
- def call env, &k
11
- @app.call(env, &k)
9
+ def call env, &k
10
+ @app.call(env, &k)
11
+ end
12
12
  end
13
13
  end
@@ -1,117 +1,121 @@
1
1
 
2
- require 'rest-core/event'
3
- require 'rest-core/middleware'
4
-
5
2
  require 'digest/md5'
3
+ require 'rest-core/event'
6
4
 
7
- class RestCore::Cache
8
- def self.members; [:cache, :expires_in]; end
9
- include RestCore::Middleware
5
+ module RestCore
6
+ class Cache
7
+ def self.members; [:cache, :expires_in]; end
8
+ include Middleware
10
9
 
11
- def initialize app, cache, expires_in, &block
12
- super(&block)
13
- @app, @cache, @expires_in = app, cache, expires_in
14
- end
10
+ def initialize app, cache, expires_in, &block
11
+ super(&block)
12
+ @app, @cache, @expires_in = app, cache, expires_in
13
+ end
15
14
 
16
- def call env, &k
17
- e = if env['cache.update']
18
- cache_clear(env)
19
- else
20
- env
21
- end
22
-
23
- cache_get(e){ |cached|
24
- e[TIMER].cancel if e[TIMER]
25
- k.call(cached)
26
- } || app_call(e, &k)
27
- end
15
+ def call env, &k
16
+ e = if env['cache.update']
17
+ cache_clear(env)
18
+ else
19
+ env
20
+ end
21
+
22
+ cache_get(e){ |cached|
23
+ e[TIMER].cancel if e[TIMER]
24
+ k.call(cached)
25
+ } || app_call(e, &k)
26
+ end
28
27
 
29
- def app_call env
30
- app.call(env) do |res|
31
- yield(if (res[FAIL] || []).empty?
32
- cache_for(res)
33
- else
34
- res
35
- end)
28
+ def app_call env
29
+ app.call(env) do |res|
30
+ yield(if (res[FAIL] || []).empty?
31
+ cache_for(res)
32
+ else
33
+ res
34
+ end)
35
+ end
36
36
  end
37
- end
38
37
 
39
- def cache_key env
40
- "rest-core:cache:#{Digest::MD5.hexdigest(env['cache.key'] ||
41
- cache_key_raw(env))}"
42
- end
38
+ def cache_key env
39
+ "rest-core:cache:#{Digest::MD5.hexdigest(env['cache.key'] ||
40
+ cache_key_raw(env))}"
41
+ end
43
42
 
44
- def cache_get env, &k
45
- return unless cache(env)
46
- return unless cache_for?(env)
43
+ def cache_get env, &k
44
+ return unless cache(env)
45
+ return unless cache_for?(env)
47
46
 
48
- uri = request_uri(env)
49
- start_time = Time.now
50
- return unless data = cache(env)[cache_key(env)]
51
- res = log(env.merge(REQUEST_URI => uri),
52
- Event::CacheHit.new(Time.now - start_time, uri))
53
- data_extract(data, res, k)
54
- end
47
+ uri = request_uri(env)
48
+ start_time = Time.now
49
+ return unless data = cache(env)[cache_key(env)]
50
+ res = log(env.merge(REQUEST_URI => uri),
51
+ Event::CacheHit.new(Time.now - start_time, uri))
52
+ data_extract(data, res, k)
53
+ end
55
54
 
56
- private
57
- def cache_key_raw env
58
- "#{env[REQUEST_METHOD]}:#{request_uri(env)}:#{header_cache_key(env)}"
59
- end
55
+ private
56
+ def cache_key_raw env
57
+ "#{env[REQUEST_METHOD]}:#{request_uri(env)}:#{header_cache_key(env)}"
58
+ end
60
59
 
61
- def cache_clear env
62
- return env unless cache(env)
63
- return env unless cache_for?(env)
60
+ def cache_clear env
61
+ return env unless cache(env)
62
+ return env unless cache_for?(env)
64
63
 
65
- cache_store(env, :[]=, nil)
66
- end
64
+ cache_store(env, :[]=, nil)
65
+ end
67
66
 
68
- def cache_for res
69
- return res unless cache(res)
70
- return res unless cache_for?(res)
67
+ def cache_for res
68
+ return res unless cache(res)
69
+ return res unless cache_for?(res)
71
70
 
72
- if expires_in(res).kind_of?(Fixnum) &&
73
- cache(res).respond_to?(:store) &&
74
- cache(res).method(:store).arity == -3
71
+ if expires_in(res).kind_of?(Fixnum) &&
72
+ cache(res).respond_to?(:store) &&
73
+ cache(res).method(:store).arity == -3
75
74
 
76
- cache_store(res, :store, data_construct(res),
77
- :expires_in => expires_in(res))
78
- else
79
- cache_store(res, :[]= , data_construct(res))
75
+ cache_store(res, :store, data_construct(res),
76
+ :expires_in => expires_in(res))
77
+ else
78
+ cache_store(res, :[]= , data_construct(res))
79
+ end
80
80
  end
81
- end
82
81
 
83
- def cache_store res, msg, value, *args
84
- start_time = Time.now
85
- cache(res).send(msg, cache_key(res), value, *args)
82
+ def cache_store res, msg, value, *args
83
+ start_time = Time.now
84
+ cache(res).send(msg, cache_key(res), value, *args)
86
85
 
87
- if value
88
- res
89
- else
90
- log(res,
91
- Event::CacheCleared.new(Time.now - start_time, request_uri(res)))
86
+ if value
87
+ res
88
+ else
89
+ log(res,
90
+ Event::CacheCleared.new(Time.now - start_time, request_uri(res)))
91
+ end
92
92
  end
93
- end
94
93
 
95
- def data_construct res
96
- "#{ res[RESPONSE_STATUS]}\n" \
97
- "#{(res[RESPONSE_HEADERS]||{}).map{|k,v|"#{k}: #{v}\n"}.join}\n\n" \
98
- "#{ res[RESPONSE_BODY]}"
99
- end
94
+ def data_construct res
95
+ "#{ res[RESPONSE_STATUS]}\n" \
96
+ "#{(res[RESPONSE_HEADERS]||{}).map{|k,v|"#{k}: #{v}\n"}.join}\n\n" \
97
+ "#{ res[RESPONSE_BODY]}"
98
+ end
100
99
 
101
- def data_extract data, res, k
102
- _, status, headers, body =
103
- data.match(/\A(\d*)\n((?:[^\n]+\n)*)\n\n(.*)\Z/m).to_a
100
+ def data_extract data, res, k
101
+ _, status, headers, body =
102
+ data.match(/\A(\d*)\n((?:[^\n]+\n)*)\n\n(.*)\Z/m).to_a
104
103
 
105
- Promise.claim(res, k, body, status.to_i,
106
- Hash[(headers||'').scan(/([^:]+): ([^\n]+)\n/)]).future_response
107
- end
104
+ result = res.merge(RESPONSE_STATUS => status.to_i,
105
+ RESPONSE_HEADERS =>
106
+ Hash[(headers||'').scan(/([^:]+): ([^\n]+)\n/)],
107
+ RESPONSE_BODY => body)
108
108
 
109
- def cache_for? env
110
- [:get, :head, :otpions].include?(env[REQUEST_METHOD]) &&
111
- !env[DRY] && !env[HIJACK]
112
- end
109
+ result.merge(Promise.claim(result, &k).future_response)
110
+ end
113
111
 
114
- def header_cache_key env
115
- env[REQUEST_HEADERS].sort.map{|(k,v)|"#{k}=#{v}"}.join('&')
112
+ def cache_for? env
113
+ [:get, :head, :otpions].include?(env[REQUEST_METHOD]) &&
114
+ !env[DRY] && !env[HIJACK]
115
+ end
116
+
117
+ def header_cache_key env
118
+ env[REQUEST_HEADERS].sort.map{|(k,v)|"#{k}=#{v}"}.join('&')
119
+ end
116
120
  end
117
121
  end