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.
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