saddle 0.0.19 → 0.0.21
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 +8 -8
- data/lib/saddle/endpoint.rb +64 -31
- data/lib/saddle/method_tree_builder.rb +4 -6
- data/lib/saddle/middleware/request/retry.rb +1 -1
- data/lib/saddle/options.rb +13 -7
- data/lib/saddle/requester.rb +14 -14
- data/lib/saddle/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,15 +1,15 @@
|
|
1
1
|
---
|
2
2
|
!binary "U0hBMQ==":
|
3
3
|
metadata.gz: !binary |-
|
4
|
-
|
4
|
+
OTdiMWYwODYzZTI0YzdiZGViNWU3MTJhMGFjZmIwMjcxYzcyNmFmMw==
|
5
5
|
data.tar.gz: !binary |-
|
6
|
-
|
6
|
+
MjBiMTU3YWY3YjE2OGYzYzVkN2JmNTQ5OWNmZDhiYTFmZWE4MDhkMA==
|
7
7
|
!binary "U0hBNTEy":
|
8
8
|
metadata.gz: !binary |-
|
9
|
-
|
10
|
-
|
11
|
-
|
9
|
+
MmUzMzE3Y2ExOGM2ZDc1OGQ4M2ZmYTU3ODUxMTE4MTJhNDY4NDY0ZDY2M2Yw
|
10
|
+
ZTM0MDk3YmJlMDYyYWI4ZTFiMDY4YzM5OTBiZWU4NGNiY2VkYzJiYzM3ODI5
|
11
|
+
MDUzYzUxZTNmYjk1Zjk0NDFhNmIzNzhmYWM4NGNkMzlmMTg2ZTA=
|
12
12
|
data.tar.gz: !binary |-
|
13
|
-
|
14
|
-
|
15
|
-
|
13
|
+
NjMxNjBiODUyNjNkZjZmNGMyYTU2MTg2MTVhOWUxOTFmMWRhOTdiNDM2NWY2
|
14
|
+
YjNmMDA5NzM3N2I2Nzc1M2ViNzZiMGQ0YjU0ZWFiNzk0YWQ2ODYzNmZkYjRm
|
15
|
+
ZDg4Mjc1ZWRlYzc2MDU2MjczMmZlMjU4YTFlZTE1OTg5ZWY1YjE=
|
data/lib/saddle/endpoint.rb
CHANGED
@@ -14,68 +14,94 @@ module Saddle
|
|
14
14
|
attr_reader :requester, :relative_path, :parent
|
15
15
|
|
16
16
|
# Each endpoint needs to have a requester in order to ... make ... uh ... requests.
|
17
|
-
def initialize(requester,
|
17
|
+
def initialize(requester, relative_path_override=nil, parent=nil)
|
18
18
|
@requester = requester
|
19
|
-
@relative_path = relative_path
|
20
19
|
@parent = parent
|
20
|
+
@relative_path = relative_path_override || _relative_path()
|
21
21
|
end
|
22
22
|
|
23
|
-
|
24
23
|
# Provide GET functionality for the implementer class
|
25
24
|
def get(action, params={}, options={})
|
26
|
-
|
25
|
+
_request(:get, action, params, options)
|
27
26
|
end
|
28
27
|
|
29
28
|
# Provide POST functionality for the implementer class
|
30
29
|
def post(action, params={}, options={})
|
31
|
-
|
30
|
+
_request(:post, action, params, options)
|
32
31
|
end
|
33
32
|
|
34
33
|
# Provide PUT functionality for the implementer class
|
35
34
|
def put(action, params={}, options={})
|
36
|
-
|
35
|
+
_request(:put, action, params, options)
|
37
36
|
end
|
38
37
|
|
39
38
|
# Provide DELETE functionality for the implementer class
|
40
39
|
def delete(action, params={}, options={})
|
41
|
-
|
40
|
+
_request(:delete, action, params, options)
|
41
|
+
end
|
42
|
+
|
43
|
+
|
44
|
+
# This will create a resource endpoint, based upon the parameters
|
45
|
+
# of this current node endpoint
|
46
|
+
def create_resource_endpoint(endpoint_class, resource_id)
|
47
|
+
endpoint_class.new(@requester, resource_id, self)
|
42
48
|
end
|
43
49
|
|
44
|
-
|
50
|
+
|
51
|
+
# Create an endpoint instance and foist it upon this node
|
52
|
+
# Not private, but not part of the public interface for an endpoint
|
53
|
+
def _build_and_attach_node(endpoint_class, method_name=nil)
|
54
|
+
# Create the new endpoint
|
55
|
+
endpoint_instance = endpoint_class.new(@requester, method_name, self)
|
56
|
+
# Attach the endpoint as an instance variable and method
|
57
|
+
method_name ||= ActiveSupport::Inflector.underscore(
|
58
|
+
ActiveSupport::Inflector.demodulize(
|
59
|
+
endpoint_class.name
|
60
|
+
)
|
61
|
+
)
|
62
|
+
self.instance_variable_set("@#{method_name}", endpoint_instance)
|
63
|
+
self.class.class_eval { define_method(method_name) { endpoint_instance } }
|
64
|
+
endpoint_instance
|
65
|
+
end
|
66
|
+
|
67
|
+
|
68
|
+
protected
|
69
|
+
|
70
|
+
def _request(method, action, params={}, options={})
|
45
71
|
# Augment in interesting options
|
46
72
|
options[:saddle] = {
|
47
|
-
:client_name =>
|
48
|
-
:call_chain =>
|
73
|
+
:client_name => _client_name(),
|
74
|
+
:call_chain => _path_array(),
|
49
75
|
:action => action,
|
50
76
|
}
|
51
|
-
@requester.send(method,
|
77
|
+
@requester.send(method, _path(action), params, options)
|
52
78
|
end
|
53
79
|
|
54
80
|
|
55
81
|
# Get the url path for this endpoint/action combo
|
56
|
-
def
|
57
|
-
paths =
|
82
|
+
def _path(action=nil)
|
83
|
+
paths = _path_array()
|
58
84
|
paths << action unless action.nil?
|
59
85
|
'/' + paths.join('/')
|
60
86
|
end
|
61
87
|
|
62
|
-
def
|
63
|
-
|
88
|
+
def _path_array
|
89
|
+
_endpoint_chain().map(&:relative_path).reject{|p| p.nil?}
|
64
90
|
end
|
65
91
|
|
66
92
|
# Get the parent chain that led to this endpoint
|
67
|
-
def
|
93
|
+
def _endpoint_chain
|
68
94
|
chain = []
|
69
95
|
node = self
|
70
96
|
while node.is_a?(BaseEndpoint)
|
71
97
|
chain << node
|
72
98
|
node = node.parent
|
73
99
|
end
|
74
|
-
chain.reverse
|
100
|
+
chain.reverse()
|
75
101
|
end
|
76
102
|
|
77
103
|
# Traverse back until we find the original client
|
78
|
-
def
|
104
|
+
def _client
|
79
105
|
node = self
|
80
106
|
while node.is_a?(BaseEndpoint)
|
81
107
|
node = node.parent
|
@@ -84,23 +110,30 @@ module Saddle
|
|
84
110
|
end
|
85
111
|
|
86
112
|
# Underscore name of the client
|
87
|
-
def
|
88
|
-
ActiveSupport::Inflector.underscore(self.
|
113
|
+
def _client_name
|
114
|
+
ActiveSupport::Inflector.underscore(self._client.name.split('::')[-2])
|
89
115
|
end
|
90
116
|
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
endpoint_instance = endpoint_class.new(@requester, method_name, self)
|
95
|
-
self.instance_variable_set("@#{method_name}", endpoint_instance)
|
96
|
-
self.class.class_eval { define_method(method_name) { endpoint_instance } }
|
97
|
-
endpoint_instance
|
117
|
+
# If the parent is not an endpoint, it is a root node
|
118
|
+
def _is_root?
|
119
|
+
!@parent.is_a?(BaseEndpoint)
|
98
120
|
end
|
99
121
|
|
100
|
-
#
|
101
|
-
#
|
102
|
-
|
103
|
-
|
122
|
+
# Build the default relative path for this endpoint node
|
123
|
+
# If this is a root node, use nil.
|
124
|
+
# Otherwise use the underscored version of the class name
|
125
|
+
#
|
126
|
+
# Override this if needed for specific endpoints
|
127
|
+
def _relative_path
|
128
|
+
if _is_root?
|
129
|
+
nil
|
130
|
+
else
|
131
|
+
ActiveSupport::Inflector.underscore(
|
132
|
+
ActiveSupport::Inflector.demodulize(
|
133
|
+
self.class.name
|
134
|
+
)
|
135
|
+
)
|
136
|
+
end
|
104
137
|
end
|
105
138
|
end
|
106
139
|
|
@@ -36,6 +36,7 @@ module Saddle
|
|
36
36
|
if File.file?(root_endpoint_file)
|
37
37
|
# Load it and create our base endpoint
|
38
38
|
load(root_endpoint_file)
|
39
|
+
# RootEndpoint is the special class name for a root endpoint
|
39
40
|
root_node_class = self.implementation_module::RootEndpoint
|
40
41
|
else
|
41
42
|
# 'root_endpoint.rb' doesn't exist, so create a dummy endpoint
|
@@ -57,7 +58,7 @@ module Saddle
|
|
57
58
|
if const.class == Module
|
58
59
|
# A module means that it's a branch
|
59
60
|
# Build the branch out with a base endpoint
|
60
|
-
branch_node = current_node.
|
61
|
+
branch_node = current_node._build_and_attach_node(
|
61
62
|
Saddle::BaseEndpoint,
|
62
63
|
ActiveSupport::Inflector.underscore(const_symbol)
|
63
64
|
)
|
@@ -68,10 +69,7 @@ module Saddle
|
|
68
69
|
if const < Saddle::TraversalEndpoint
|
69
70
|
# A class means that it's a node
|
70
71
|
# Build out this endpoint on the current node
|
71
|
-
current_node.
|
72
|
-
const,
|
73
|
-
ActiveSupport::Inflector.underscore(const_symbol)
|
74
|
-
)
|
72
|
+
current_node._build_and_attach_node(const)
|
75
73
|
end
|
76
74
|
end
|
77
75
|
end
|
@@ -98,7 +96,7 @@ module Saddle
|
|
98
96
|
end
|
99
97
|
|
100
98
|
# If this client was not fully constructed, it may not even have an
|
101
|
-
# implementation root. Allow that behavior
|
99
|
+
# implementation root. Allow that behavior to avoid filesystem searching.
|
102
100
|
def knows_root?
|
103
101
|
defined?(self.implementation_root)
|
104
102
|
end
|
@@ -18,7 +18,7 @@ module Saddle
|
|
18
18
|
|
19
19
|
def call(env)
|
20
20
|
retries = env[:request][:num_retries] || 2
|
21
|
-
backoff = env[:request][:retry_backoff] || 0.050 #
|
21
|
+
backoff = env[:request][:retry_backoff] || 0.050 # in seconds
|
22
22
|
begin
|
23
23
|
@app.call(self.class.deep_copy(env))
|
24
24
|
rescue => e
|
data/lib/saddle/options.rb
CHANGED
@@ -7,14 +7,15 @@ module Saddle
|
|
7
7
|
# Construct our default options, based upon the class methods
|
8
8
|
def default_options
|
9
9
|
{
|
10
|
-
:host => host,
|
11
|
-
:port => port,
|
12
|
-
:
|
13
|
-
:
|
14
|
-
:
|
15
|
-
:
|
10
|
+
:host => host(),
|
11
|
+
:port => port(),
|
12
|
+
:path_prefix => path_prefix(),
|
13
|
+
:use_ssl => use_ssl(),
|
14
|
+
:request_style => request_style(),
|
15
|
+
:num_retries => num_retries(),
|
16
|
+
:timeout => timeout(),
|
16
17
|
:additional_middlewares => self.additional_middlewares,
|
17
|
-
:stubs => stubs,
|
18
|
+
:stubs => stubs(),
|
18
19
|
}
|
19
20
|
end
|
20
21
|
|
@@ -28,6 +29,11 @@ module Saddle
|
|
28
29
|
80
|
29
30
|
end
|
30
31
|
|
32
|
+
# A string prefix to prepend to paths as they are build (ie, 'v1')
|
33
|
+
def path_prefix
|
34
|
+
''
|
35
|
+
end
|
36
|
+
|
31
37
|
# Should this client use SSL by default?
|
32
38
|
def use_ssl
|
33
39
|
false
|
data/lib/saddle/requester.rb
CHANGED
@@ -34,6 +34,8 @@ module Saddle
|
|
34
34
|
raise ':host must be a string' unless @host.is_a?(String)
|
35
35
|
@port = opt[:port] || 80
|
36
36
|
raise ':port must be an integer' unless @port.is_a?(Fixnum)
|
37
|
+
@path_prefix = opt[:path_prefix] || ''
|
38
|
+
raise ':path_prefix must be a string' unless @path_prefix.is_a?(String)
|
37
39
|
@use_ssl = opt[:use_ssl] || false
|
38
40
|
raise ':use_ssl must be true or false' unless (@use_ssl.is_a?(TrueClass) || @use_ssl.is_a?(FalseClass))
|
39
41
|
@request_style = opt[:request_style] || :json
|
@@ -41,9 +43,7 @@ module Saddle
|
|
41
43
|
@num_retries = opt[:num_retries] || 3
|
42
44
|
raise ':num_retries must be an integer' unless @num_retries.is_a?(Fixnum)
|
43
45
|
@timeout = opt[:timeout]
|
44
|
-
unless @timeout.nil?
|
45
|
-
raise ':timeout must be a number or nil' unless @timeout.is_a?(Numeric)
|
46
|
-
end
|
46
|
+
raise ':timeout must be nil or an integer' unless (@timeout.nil? || @timeout.is_a?(Numeric))
|
47
47
|
@additional_middlewares = opt[:additional_middlewares] || []
|
48
48
|
raise ':additional_middleware must be an Array' unless @additional_middlewares.is_a?(Array)
|
49
49
|
raise 'invalid middleware found' unless @additional_middlewares.all? { |m| m[:klass] < Faraday::Middleware }
|
@@ -99,7 +99,7 @@ module Saddle
|
|
99
99
|
|
100
100
|
# Construct a base url using this requester's settings
|
101
101
|
def base_url
|
102
|
-
"http#{'s' if @use_ssl}://#{@host}:#{@port}"
|
102
|
+
"http#{'s' if @use_ssl}://#{@host}:#{@port}/#{@path_prefix}"
|
103
103
|
end
|
104
104
|
|
105
105
|
# Build a connection instance, wrapped in the middleware that we want
|
@@ -113,36 +113,36 @@ module Saddle
|
|
113
113
|
end
|
114
114
|
|
115
115
|
# Support default return values upon exception
|
116
|
-
builder.use
|
116
|
+
builder.use(Saddle::Middleware::Response::DefaultResponse)
|
117
117
|
|
118
118
|
# Apply additional implementation-specific middlewares
|
119
119
|
@additional_middlewares.each do |m|
|
120
|
-
builder.use
|
120
|
+
builder.use(m[:klass], *m[:args])
|
121
121
|
end
|
122
122
|
|
123
123
|
# Hard timeout on the entire request
|
124
|
-
builder.use
|
124
|
+
builder.use(Saddle::Middleware::RubyTimeout)
|
125
125
|
|
126
126
|
# Request encoding
|
127
|
-
builder.use
|
128
|
-
builder.use
|
127
|
+
builder.use(Saddle::Middleware::Request::JsonEncoded)
|
128
|
+
builder.use(Saddle::Middleware::Request::UrlEncoded)
|
129
129
|
|
130
130
|
# Automatic retries
|
131
|
-
builder.use
|
131
|
+
builder.use(Saddle::Middleware::Request::Retry)
|
132
132
|
|
133
133
|
# Handle parsing out the response if it's JSON
|
134
|
-
builder.use
|
134
|
+
builder.use(Saddle::Middleware::Response::ParseJson)
|
135
135
|
|
136
136
|
# Raise exceptions on 4xx and 5xx errors
|
137
|
-
builder.use
|
137
|
+
builder.use(Faraday::Response::RaiseError)
|
138
138
|
|
139
139
|
# Set up our adapter
|
140
140
|
if @stubs.nil?
|
141
141
|
# Use the default adapter
|
142
|
-
builder.adapter
|
142
|
+
builder.adapter(:net_http)
|
143
143
|
else
|
144
144
|
# Use the test adapter
|
145
|
-
builder.adapter
|
145
|
+
builder.adapter(:test, @stubs)
|
146
146
|
end
|
147
147
|
end
|
148
148
|
end
|
data/lib/saddle/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: saddle
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.21
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Mike Lewis
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2013-05-
|
11
|
+
date: 2013-05-19 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activesupport
|