saddle 0.0.5 → 0.0.6

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 CHANGED
@@ -1,15 +1,15 @@
1
1
  ---
2
2
  !binary "U0hBMQ==":
3
3
  metadata.gz: !binary |-
4
- NjNmZmY5MTg1ZjdlOWQ0MGExNTU5ODU1OWE2NmEyZDhlNjEzNjUxNg==
4
+ NDdlNWQ0MWNlODhhYTQ2NTMwZWQ2MDhkMjRlOGQ1YTQ1MTBhMjNjMA==
5
5
  data.tar.gz: !binary |-
6
- Yjg5MmI0MGZmYTExYmM2YjNmZTgxNGU3OGYzN2Y1ZTVmN2E0NWIwNw==
6
+ YmE2MmYxZjQyNjhmYTJhNzhkZjk3MDcwMjdhNjgxNTI5ZWJlZDAyZA==
7
7
  !binary "U0hBNTEy":
8
8
  metadata.gz: !binary |-
9
- ZWYyYmI5Njc3NmYxYmRhMWVjN2QzYWI3YjQ1ZGNkZjUxNjBiNjhhM2JiYTAz
10
- YmM0ZjYwMWQwZDA0ZDVlYWU0N2ZlMjNhZWYxMWM1NzQwNmE4ZDdjNjE2M2Uw
11
- OTlmODFjZjg0ZGY0NGM4NmJiYjljZmNmZDkyOTA0MDQ3MjNhNGM=
9
+ MWQ4Y2ZiOThmMGIwNjNiMDQ5M2EwMTNkZjdkMmIyMjFhOGFiNmU3NTNjMjQy
10
+ NGI4MmQyNWNmOTY5M2Y5MjJmMTg5ZGRjMThjYWUwZTRlZWQ3MDhkZDdiODIw
11
+ NWQwMWM4YTZmNjVmNmZjZjc3NjIwZDlhMGRlMDYzOWM3M2Y0ZTQ=
12
12
  data.tar.gz: !binary |-
13
- YWY0OGE2NTdhN2EzZTQ4MmE3ZmRjYjYyZjhmNDJlNTQxZDJhNGMwYWE3OGYz
14
- NzM3YjQ2YzJjZTM5ODg1MjJhYTAxY2Q0MWQxZWRiOWVlZTAwZjVkMjI2NzRj
15
- MzI4MjQ4MzI0NzE2NzA1ODVkNzQ3NzBiYmYzYWE0Y2U5OWRiZDk=
13
+ ODM4ZGM4ZTdlYTM3OGY3NzNkYTZlOTQ3ZWY0N2Y2MzViZjgzZWFiZjA2Njg4
14
+ Mjc4Y2NiNGVkYmZiZDhjYTliMzZmYmE0NjhkNDQ3YmY4MTQ0NjIzMzk0ZTkx
15
+ ZTczYmRkYTViOWIzODY0NWI0MGY3YWVmNDIzMDYxYTE2MDIwMmU=
@@ -0,0 +1,35 @@
1
+ require 'airbrake'
2
+ require 'faraday'
3
+
4
+
5
+
6
+ module Saddle::Middleware
7
+ module Logging
8
+
9
+ # Public: Reports exceptions to Airbrake
10
+ #
11
+ class AirbrakeLogger < Faraday::Middleware
12
+
13
+ def initialize(app, airbrake_api_key=nil)
14
+ super(app)
15
+ @airbrake_api_key = airbrake_api_key
16
+ end
17
+
18
+ def call(env)
19
+ begin
20
+ @app.call(env)
21
+ rescue => e
22
+ # If we don't have an api key, use the default config
23
+ if @airbrake_api_key
24
+ ::Airbrake.notify(e, {:api_key => @airbrake_api_key} )
25
+ else
26
+ ::Airbrake.notify(e)
27
+ end
28
+ # Re-raise the error
29
+ raise
30
+ end
31
+ end
32
+
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,49 @@
1
+ require 'statsd'
2
+ require 'faraday'
3
+
4
+
5
+
6
+
7
+ module Saddle::Middleware
8
+ module Logging
9
+
10
+ # Public: Wraps request with statsd logging
11
+ # Expects statsd_path in request options. However, if using saddle and no statsd_path is specified
12
+ # will read call_chain and action and use them to construct a statsd_path
13
+ class StatsdLogger < Faraday::Middleware
14
+ attr_accessor :graphite_host, :graphite_port, :namespace
15
+
16
+ def initialize(app, graphite_host, graphite_port=nil, namespace=nil)
17
+ super(app)
18
+ @graphite_host = graphite_host
19
+ @graphite_port = graphite_port
20
+ @namespace = namespace
21
+ end
22
+
23
+ def statsd
24
+ @statsd ||= begin
25
+ client = ::Statsd.new(@graphite_host, @graphite_port)
26
+ client.namespace = @namespace if @namespace
27
+ end
28
+ end
29
+
30
+ def call(env)
31
+ statsd_path = nil
32
+ if env[:request][:statsd_path]
33
+ statsd_path = env[:request][:statsd_path]
34
+ elsif env[:request][:saddle] && env[:request][:saddle][:call_chain] && env[:request][:saddle][:action]
35
+ statsd_path = (env[:request][:saddle][:call_chain] + [env[:request][:saddle][:action]]).join('.')
36
+ end
37
+
38
+ if statsd_path
39
+ self.statsd.time statsd_path do
40
+ @app.call(env)
41
+ end
42
+ else
43
+ @app.call(env)
44
+ end
45
+ end
46
+ end
47
+
48
+ end
49
+ end
@@ -0,0 +1,34 @@
1
+ require 'faraday'
2
+
3
+
4
+
5
+ module Saddle::Middleware
6
+ module Request
7
+
8
+ # Request middleware that encodes the body as JSON.
9
+ #
10
+ # Make sure you set request[:request_style] = :json
11
+ # for it to be activated.
12
+
13
+ class JsonEncoded < Faraday::Middleware
14
+ CONTENT_TYPE = 'Content-Type'.freeze
15
+ MIME_TYPE = 'application/json'.freeze
16
+
17
+ dependency do
18
+ require 'json' unless defined?(::JSON)
19
+ end
20
+
21
+ def call(env)
22
+ if env[:request][:request_style] == :json
23
+ # Make sure we're working with a valid body that's not a String
24
+ if env[:body] and !env[:body].respond_to?(:to_str)
25
+ env[:request_headers][CONTENT_TYPE] ||= MIME_TYPE
26
+ env[:body] = ::JSON.dump(env[:body])
27
+ end
28
+ end
29
+ @app.call env
30
+ end
31
+ end
32
+
33
+ end
34
+ end
@@ -0,0 +1,55 @@
1
+ require 'faraday'
2
+
3
+
4
+
5
+ module Saddle::Middleware
6
+ module Request
7
+
8
+ # Catches exceptions and retries each request a limited number of times.
9
+ #
10
+ # By default, it retries 2 times and performs exponential backoff, starting
11
+ # at 50ms
12
+ class Retry < Faraday::Middleware
13
+ def initialize(app, ignored_exceptions=[])
14
+ super(app)
15
+ @ignored_exceptions = ignored_exceptions
16
+ end
17
+
18
+ def call(env)
19
+ retries = env[:request][:num_retries] || 2
20
+ backoff = env[:request][:retry_backoff] || 0.050 # ms
21
+ begin
22
+ @app.call(self.class.deep_copy(env))
23
+ rescue => e
24
+ unless @ignored_exceptions.include?(e.class)
25
+ # Retry a limited number of times
26
+ if retries > 0
27
+ retries -= 1
28
+ sleep(backoff) if backoff > 0.0
29
+ backoff *= 2
30
+ retry
31
+ end
32
+ end
33
+ # Re-raise if we're out of retries or it's not handled
34
+ raise
35
+ end
36
+ end
37
+
38
+ def self.deep_copy(value)
39
+ if value.is_a?(Hash)
40
+ result = value.clone
41
+ value.each{|k, v| result[k] = deep_copy(v)}
42
+ result
43
+ elsif value.is_a?(Array)
44
+ result = value.clone
45
+ result.clear
46
+ value.each{|v| result << deep_copy(v)}
47
+ result
48
+ else
49
+ value
50
+ end
51
+ end
52
+ end
53
+
54
+ end
55
+ end
@@ -0,0 +1,86 @@
1
+ require 'faraday'
2
+
3
+
4
+
5
+ module Saddle::Middleware
6
+ module Request
7
+
8
+ # This magically handles converting your body from a hash
9
+ # into an url-encoded (or multipart if needed) request
10
+
11
+ # Make sure you set request[:request_style] = :urlencoded
12
+ # for it to be activated.
13
+
14
+ class UrlEncoded < Faraday::Middleware
15
+ CONTENT_TYPE = 'Content-Type'.freeze unless defined? CONTENT_TYPE
16
+
17
+ URL_ENCODED_MIME_TYPE = 'application/x-www-form-urlencoded'.freeze
18
+ MULTIPART_MIME_TYPE = 'multipart/form-data'.freeze
19
+
20
+ VALID_MIME_TYPES = [URL_ENCODED_MIME_TYPE, MULTIPART_MIME_TYPE]
21
+
22
+ DEFAULT_MULTIPART_BOUNDARY = "-^---_---^-".freeze
23
+
24
+
25
+ def call(env)
26
+ if env[:request][:request_style] == :urlencoded
27
+ # Make sure we're working with a valid body that's not a String
28
+ if env[:body] and !env[:body].respond_to?(:to_str)
29
+ if has_multipart?(env[:body])
30
+ env[:request][:boundary] ||= DEFAULT_MULTIPART_BOUNDARY
31
+ env[:request_headers][CONTENT_TYPE] ||= MULTIPART_MIME_TYPE
32
+ env[:request_headers][CONTENT_TYPE] += ";boundary=#{env[:request][:boundary]}"
33
+ env[:body] = create_multipart(env, env[:body])
34
+ else
35
+ env[:request_headers][CONTENT_TYPE] ||= URL_ENCODED_MIME_TYPE
36
+ env[:body] = Faraday::Utils::ParamsHash[env[:body]].to_query
37
+ end
38
+ end
39
+ end
40
+ @app.call env
41
+ end
42
+
43
+
44
+ private
45
+
46
+ def has_multipart?(obj)
47
+ # string is an enum in 1.8, returning list of itself
48
+ if obj.respond_to?(:each) && !obj.is_a?(String)
49
+ (obj.respond_to?(:values) ? obj.values : obj).each do |val|
50
+ return true if (val.respond_to?(:content_type) || has_multipart?(val))
51
+ end
52
+ end
53
+ false
54
+ end
55
+
56
+ def create_multipart(env, params)
57
+ boundary = env[:request][:boundary]
58
+ parts = process_params(params) do |key, value|
59
+ Faraday::Parts::Part.new(boundary, key, value)
60
+ end
61
+ parts << Faraday::Parts::EpiloguePart.new(boundary)
62
+
63
+ body = Faraday::CompositeReadIO.new(parts)
64
+ env[:request_headers][Faraday::Env::ContentLength] = body.length.to_s
65
+ body
66
+ end
67
+
68
+ def process_params(params, prefix = nil, pieces = nil, &block)
69
+ params.inject(pieces || []) do |all, (key, value)|
70
+ key = "#{prefix}[#{key}]" if prefix
71
+
72
+ case value
73
+ when Array
74
+ values = value.inject([]) { |a,v| a << [nil, v] }
75
+ process_params(values, key, all, &block)
76
+ when Hash
77
+ process_params(value, key, all, &block)
78
+ else
79
+ all << block.call(key, value)
80
+ end
81
+ end
82
+ end
83
+ end
84
+
85
+ end
86
+ end
@@ -0,0 +1,24 @@
1
+ require 'faraday'
2
+
3
+
4
+ module Saddle::Middleware
5
+ module Response
6
+
7
+ # Public: Returns a default response in the case of an exception
8
+ # Expects default_response to be defined in the request of connection options, otherwise rethrows exception
9
+ class DefaultResponse < Faraday::Middleware
10
+ def call(env)
11
+ begin
12
+ @app.call(env)
13
+ rescue Faraday::Error
14
+ if res = env[:request][:default_response]
15
+ return ::Faraday::Response.new(:body => res)
16
+ else
17
+ raise
18
+ end
19
+ end
20
+ end
21
+ end
22
+
23
+ end
24
+ end
@@ -0,0 +1,45 @@
1
+ require 'faraday'
2
+
3
+
4
+
5
+ module Saddle::Middleware
6
+ module Response
7
+
8
+ # Public: Parse response bodies as JSON.
9
+ class ParseJson < Faraday::Middleware
10
+ CONTENT_TYPE = 'Content-Type'.freeze
11
+ MIME_TYPE = 'application/json'.freeze
12
+
13
+ dependency do
14
+ require 'json' unless defined?(::JSON)
15
+ end
16
+
17
+ def call(env)
18
+ if parse_response?(env)
19
+ # Make sure we're working with a valid body that's not a String
20
+ if env.body and !env.body.respond_to?(:to_str)
21
+ env[:request_headers][CONTENT_TYPE] ||= MIME_TYPE
22
+ env.body = ::JSON.dump env.body
23
+ end
24
+ end
25
+ @app.call env
26
+ end
27
+
28
+ def parse_response?(env)
29
+ has_body?(env) and (response_type(env) == MIME_TYPE)
30
+ end
31
+
32
+ def has_body?(env)
33
+ body = env[:body] and !(body.respond_to?(:to_str) and body.empty?)
34
+ end
35
+
36
+ def response_type(env)
37
+ return nil unless env[:response_headers]
38
+ type = env[:response_headers][CONTENT_TYPE].to_s
39
+ type = type.split(';', 2).first if type.index(';')
40
+ type
41
+ end
42
+ end
43
+
44
+ end
45
+ end
@@ -13,11 +13,10 @@ module Saddle::Options
13
13
  :host => host,
14
14
  :port => port,
15
15
  :use_ssl => use_ssl,
16
- :post_style => post_style,
17
- :response_style => response_style,
16
+ :request_style => request_style,
18
17
  :num_retries => num_retries,
19
18
  :timeout => timeout,
20
- :additional_middlewares => additional_middlewares,
19
+ :additional_middlewares => @@additional_middlewares,
21
20
  :stubs => stubs,
22
21
  }
23
22
  end
@@ -39,13 +38,7 @@ module Saddle::Options
39
38
 
40
39
  # The POST/PUT style for this client
41
40
  # options are [:json, :urlencoded]
42
- def post_style
43
- :json
44
- end
45
-
46
- # How to parse results
47
- # options are [:json, :urlencoded]
48
- def response_style
41
+ def request_style
49
42
  :json
50
43
  end
51
44
 
@@ -59,17 +52,18 @@ module Saddle::Options
59
52
  30
60
53
  end
61
54
 
62
- # Override this to add additional middleware to the request stack
55
+ # Use this to add additional middleware to the request stack
63
56
  # ex:
64
- #
65
- # require 'my_middleware'
66
- # def self.default_middleware
67
- # [MyMiddleware]
57
+ # add_middleware({
58
+ # :klass => MyMiddleware,
59
+ # :args => [arg1, arg2],
60
+ # })
68
61
  # end
69
62
  #
70
63
  ###
71
- def additional_middlewares
72
- []
64
+ @@additional_middlewares = []
65
+ def add_middleware m
66
+ @@additional_middlewares << m
73
67
  end
74
68
 
75
69
  # If the Typhoeus adapter is being used, pass stubs to it for testing.
@@ -1,8 +1,11 @@
1
1
  require 'faraday'
2
2
  require 'faraday_middleware'
3
3
 
4
- require 'saddle/middleware/default_response'
5
- require 'saddle/middleware/parse_json'
4
+ require 'saddle/middleware/request/encode_json'
5
+ require 'saddle/middleware/request/retry'
6
+ require 'saddle/middleware/request/url_encoded'
7
+ require 'saddle/middleware/response/default_response'
8
+ require 'saddle/middleware/response/parse_json'
6
9
  require 'saddle/middleware/ruby_timeout'
7
10
 
8
11
 
@@ -21,8 +24,7 @@ module Saddle
21
24
  ## host - host to connect to (default: localhost)
22
25
  ## port - port to connect on (default: 80)
23
26
  ## use_ssl - true if we should use https (default: false)
24
- ## post_style - :json or :urlencoded (default: :json)
25
- ## response_style - :json or :urlencoded (default: :json)
27
+ ## request_style - :json or :urlencoded (default: :json)
26
28
  ## num_retries - number of times to retry each request (default: 3)
27
29
  ## timeout - timeout in seconds
28
30
  ## additional_middleware - an Array of more middlewares to apply to the top of the stack
@@ -35,10 +37,8 @@ module Saddle
35
37
  raise ':port must be an integer' unless @port.is_a?(Fixnum)
36
38
  @use_ssl = opt[:use_ssl] || false
37
39
  raise ':use_ssl must be true or false' unless (@use_ssl.is_a?(TrueClass) || @use_ssl.is_a?(FalseClass))
38
- @post_style = opt[:post_style] || :json
39
- raise ":post_style must be in: #{VALID_BODY_STYLES.join(',')}" unless VALID_BODY_STYLES.include?(@post_style)
40
- @response_style = opt[:response_style] || :json
41
- raise ":response_style must be in: #{VALID_BODY_STYLES.join(',')}" unless VALID_BODY_STYLES.include?(@response_style)
40
+ @request_style = opt[:request_style] || :json
41
+ raise ":request_style must be in: #{VALID_BODY_STYLES.join(',')}" unless VALID_BODY_STYLES.include?(@request_style)
42
42
  @num_retries = opt[:num_retries] || 3
43
43
  raise ':num_retries must be an integer' unless @num_retries.is_a?(Fixnum)
44
44
  @timeout = opt[:timeout]
@@ -65,33 +65,24 @@ module Saddle
65
65
  response.body
66
66
  end
67
67
 
68
- # Handle request logic for PUT or POST
69
- def post_or_put(f, url, params={}, options={})
70
- response = connection.send(f) do |req|
68
+ # Make a POST request
69
+ def post(url, data={}, options={})
70
+ response = connection.post do |req|
71
71
  req.options.merge! options
72
72
  req.url url
73
- # Handle different supported post styles
74
- case @post_style
75
- when :json
76
- req.headers['Content-Type'] = 'application/json'
77
- req.body = params.to_json
78
- when :urlencoded
79
- req.params = params
80
- else
81
- raise RuntimeError(":post_style must be one of: #{VALID_POST_STYLES.join(',')}")
82
- end
73
+ req.body = data
83
74
  end
84
75
  response.body
85
76
  end
86
77
 
87
- # Make a POST request
88
- def post(url, params={}, options={})
89
- post_or_put(:post, url, params, options)
90
- end
91
-
92
78
  # Make a PUT request
93
- def put(url, params={}, options={})
94
- post_or_put(:put, url, params, options)
79
+ def put(url, data={}, options={})
80
+ response = connection.put do |req|
81
+ req.options.merge! options
82
+ req.url url
83
+ req.body = data
84
+ end
85
+ response.body
95
86
  end
96
87
 
97
88
  # Make a DELETE request
@@ -118,10 +109,12 @@ module Saddle
118
109
  # Config options
119
110
  unless @timeout.nil?
120
111
  builder.options[:timeout] = @timeout
112
+ builder.options[:request_style] = @request_style
113
+ builder.options[:num_retries] = @num_retries
121
114
  end
122
115
 
123
116
  # Support default return values upon exception
124
- builder.use Saddle::Middleware::DefaultResponse
117
+ builder.use Saddle::Middleware::Response::DefaultResponse
125
118
 
126
119
  # Apply additional implementation-specific middlewares
127
120
  @additional_middlewares.each do |m|
@@ -131,12 +124,18 @@ module Saddle
131
124
  # Hard timeout on the entire request
132
125
  builder.use Saddle::Middleware::RubyTimeout
133
126
 
134
- # Support multi-part encoding if there is a file attached
135
- builder.request :multipart
136
- # Handle retries
137
- if @num_retries
138
- builder.request :retry, @num_retries
139
- end
127
+ # Request encoding
128
+ builder.use Saddle::Middleware::Request::JsonEncoded
129
+ builder.use Saddle::Middleware::Request::UrlEncoded
130
+
131
+ # Automatic retries
132
+ builder.use Saddle::Middleware::Request::Retry
133
+
134
+ # Handle parsing out the response if it's JSON
135
+ builder.use Saddle::Middleware::Response::ParseJson
136
+
137
+ # Raise exceptions on 4xx and 5xx errors
138
+ builder.use Faraday::Response::RaiseError
140
139
 
141
140
  # Set up our adapter
142
141
  if @stubs.nil?
@@ -146,11 +145,6 @@ module Saddle
146
145
  # Use the test adapter
147
146
  builder.adapter :test, @stubs
148
147
  end
149
-
150
- # Raise exceptions on 4xx and 5xx errors
151
- builder.response :raise_error
152
- # Handle parsing out the response if it's JSON
153
- builder.use Saddle::Middleware::ParseJson
154
148
  end
155
149
  end
156
150
 
@@ -1,3 +1,3 @@
1
1
  module Saddle
2
- VERSION = '0.0.5'
2
+ VERSION = '0.0.6'
3
3
  end
@@ -0,0 +1,40 @@
1
+ require 'saddle'
2
+
3
+ describe Saddle::Client do
4
+
5
+ context "GET requests" do
6
+ context "using the default client" do
7
+
8
+ before :each do
9
+ @stubs = Faraday::Adapter::Test::Stubs.new
10
+ @default_client = Saddle::Client.create(:stubs => @stubs)
11
+ end
12
+
13
+ it "should request properly with params" do
14
+ @stubs.get('/test?name=mike&party=true') {
15
+ [
16
+ 200,
17
+ {},
18
+ 'Party on!',
19
+ ]
20
+ }
21
+ @default_client.requester.get(
22
+ '/test',
23
+ {'name' => 'mike', 'party' => true}
24
+ ).should == 'Party on!'
25
+ end
26
+
27
+ it "should parse JSON encoded responses" do
28
+ @stubs.get('/test.json') {
29
+ [
30
+ 200,
31
+ {'Content-Type' => 'application/json'},
32
+ {'success' => true},
33
+ ]
34
+ }
35
+ @default_client.requester.get('/test.json')['success'].should == true
36
+ end
37
+
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,56 @@
1
+ require 'saddle'
2
+
3
+ describe Saddle::Client do
4
+
5
+ context "POST requests" do
6
+ context "using the default client" do
7
+
8
+ before :each do
9
+ @stubs = Faraday::Adapter::Test::Stubs.new
10
+ @default_client = Saddle::Client.create(:stubs => @stubs)
11
+ end
12
+
13
+ it "should post empty" do
14
+ @stubs.post('/test') {
15
+ [
16
+ 200,
17
+ {},
18
+ 'Party on!',
19
+ ]
20
+ }
21
+ @default_client.requester.post('/test').should == 'Party on!'
22
+ end
23
+
24
+ it "should post url encoded" do
25
+ @stubs.post('/test', 'a=0&b=true&c=Wingdings') {
26
+ [
27
+ 200,
28
+ {},
29
+ 'Party on!',
30
+ ]
31
+ }
32
+ @default_client.requester.post(
33
+ '/test',
34
+ {'a' => 0, 'b' => true, 'c' => 'Wingdings'},
35
+ {:request_style => :urlencoded}
36
+ ).should == 'Party on!'
37
+ end
38
+
39
+ it "should post JSON encoded" do
40
+ @stubs.post('/test', '{"a":0,"b":true,"c":"Wingdings"}') {
41
+ [
42
+ 200,
43
+ {},
44
+ 'Party on!',
45
+ ]
46
+ }
47
+ @default_client.requester.post(
48
+ '/test',
49
+ {'a' => 0, 'b' => true, 'c' => 'Wingdings'},
50
+ {:request_style => :json}
51
+ ).should == 'Party on!'
52
+ end
53
+
54
+ end
55
+ end
56
+ end
@@ -0,0 +1,54 @@
1
+ require 'saddle'
2
+
3
+ describe Saddle::Client do
4
+
5
+ context "retry requests" do
6
+ context "using the default client" do
7
+
8
+ before :each do
9
+ @stubs = Faraday::Adapter::Test::Stubs.new
10
+ @default_client = Saddle::Client.create(:stubs => @stubs)
11
+ end
12
+
13
+ it "should retry properly with no params" do
14
+ @stubs.get('/test') {
15
+ [
16
+ 500,
17
+ {},
18
+ 'Failure',
19
+ ]
20
+ }
21
+ @stubs.get('/test') {
22
+ [
23
+ 200,
24
+ {},
25
+ 'Party!',
26
+ ]
27
+ }
28
+ @default_client.requester.get('/test').should == 'Party!'
29
+ end
30
+
31
+ it "should retry properly when posting params urlencoded" do
32
+ @stubs.post('/test', '{"a":"b","c":"d"}') {
33
+ [
34
+ 500,
35
+ {},
36
+ 'Failure',
37
+ ]
38
+ }
39
+ @stubs.post('/test', '{"a":"b","c":"d"}') {
40
+ [
41
+ 200,
42
+ {},
43
+ 'Party!',
44
+ ]
45
+ }
46
+ @default_client.requester.post(
47
+ '/test',
48
+ {'a' => 'b', 'c' => 'd'}
49
+ ).should == 'Party!'
50
+ end
51
+
52
+ end
53
+ end
54
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: saddle
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.5
4
+ version: 0.0.6
5
5
  platform: ruby
6
6
  authors:
7
7
  - Mike Lewis
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2013-04-10 00:00:00.000000000 Z
12
+ date: 2013-04-11 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: activesupport
@@ -68,16 +68,21 @@ files:
68
68
  - lib/saddle.rb
69
69
  - lib/saddle/endpoint.rb
70
70
  - lib/saddle/method_tree_builder.rb
71
- - lib/saddle/middleware/airbrake_logging.rb
72
- - lib/saddle/middleware/default_response.rb
73
- - lib/saddle/middleware/parse_json.rb
71
+ - lib/saddle/middleware/logging/airbrake.rb
72
+ - lib/saddle/middleware/logging/statsd.rb
73
+ - lib/saddle/middleware/request/encode_json.rb
74
+ - lib/saddle/middleware/request/retry.rb
75
+ - lib/saddle/middleware/request/url_encoded.rb
76
+ - lib/saddle/middleware/response/default_response.rb
77
+ - lib/saddle/middleware/response/parse_json.rb
74
78
  - lib/saddle/middleware/ruby_timeout.rb
75
- - lib/saddle/middleware/statsd_logging.rb
76
79
  - lib/saddle/options.rb
77
80
  - lib/saddle/requester.rb
78
81
  - lib/saddle/version.rb
79
82
  - saddle.gemspec
80
- - spec/saddle_client_spec.rb
83
+ - spec/requester/get_spec.rb
84
+ - spec/requester/post_spec.rb
85
+ - spec/requester/retry_spec.rb
81
86
  homepage: https://github.com/mLewisLogic/saddle
82
87
  licenses:
83
88
  - MIT
@@ -104,4 +109,6 @@ specification_version: 4
104
109
  summary: A generic client wrapper for building service-specific wrappers. Base functionality,
105
110
  meant to be extended to concrete implementations.
106
111
  test_files:
107
- - spec/saddle_client_spec.rb
112
+ - spec/requester/get_spec.rb
113
+ - spec/requester/post_spec.rb
114
+ - spec/requester/retry_spec.rb
@@ -1,31 +0,0 @@
1
- require 'faraday'
2
-
3
-
4
- module Saddle::Middleware
5
-
6
- # Public: Reports exceptions to airbrake
7
- #
8
- class AirbrakeLogging < Faraday::Middleware
9
-
10
- def initialize(app, airbrake_api_key)
11
- @airbrake_api_key = airbrake_api_key
12
- super(app)
13
- end
14
-
15
- def call(env)
16
- begin
17
- @app.call(env)
18
- rescue => e
19
- ::Airbrake.notify(
20
- e,
21
- {
22
- :api_key => @airbrake_api_key,
23
- }
24
- )
25
- raise
26
- end
27
- end
28
-
29
- end
30
-
31
- end
@@ -1,24 +0,0 @@
1
- require 'faraday'
2
-
3
-
4
- module Saddle::Middleware
5
-
6
- # Public: Returns a default response in the case of an exception
7
- # Expects default_response to be defined in the request of connection options, otherwise rethrows exception
8
- class DefaultResponse < Faraday::Middleware
9
-
10
- def call(env)
11
- begin
12
- @app.call(env)
13
- rescue => e
14
- if res = env[:request][:default_response]
15
- return ::Faraday::Response.new(:body => res)
16
- else
17
- raise
18
- end
19
- end
20
- end
21
-
22
- end
23
-
24
- end
@@ -1,36 +0,0 @@
1
- require 'faraday_middleware/response_middleware'
2
-
3
-
4
- module Saddle::Middleware
5
-
6
- # Public: Parse response bodies as JSON.
7
- class ParseJson < FaradayMiddleware::ResponseMiddleware
8
- MIME_TYPE = 'application/json'.freeze
9
-
10
- dependency do
11
- require 'json' unless defined?(::JSON)
12
- end
13
-
14
- define_parser do |body|
15
- ::JSON.parse body unless body.strip.empty?
16
- end
17
-
18
-
19
- def parse_response?(env)
20
- type = response_type(env)
21
- super and has_body?(env) and (type.empty? or type == MIME_TYPE)
22
- end
23
-
24
- def has_body?(env)
25
- body = env[:body] and !(body.respond_to?(:to_str) and body.empty?)
26
- end
27
-
28
- def response_type(env)
29
- type = env[:response_headers][CONTENT_TYPE].to_s
30
- type = type.split(';', 2).first if type.index(';')
31
- type
32
- end
33
-
34
- end
35
-
36
- end
@@ -1,45 +0,0 @@
1
- require 'statsd'
2
-
3
- module Saddle::Middleware
4
-
5
- # Public: Wraps request with statsd logging
6
- # Expects statsd_path in request options. However, if using saddle and no statsd_path is specified
7
- # will read call_chain and action and use them to construct a statsd_path
8
- class StatsdLogging < Faraday::Middleware
9
- attr_accessor :graphite_host, :graphite_port, :namespace
10
-
11
- def initialize(app, graphite_host, graphite_port=nil, namespace=nil)
12
- super(app)
13
- @graphite_host = graphite_host
14
- @graphite_port = graphite_port
15
- @namespace = namespace
16
- self.statsd
17
- end
18
-
19
- def statsd
20
- if(@statsd.nil?)
21
- @statsd = Statsd.new(@graphite_host, @graphite_port)
22
- @statsd.namespace = @namespace if @namespace
23
- end
24
- return @statsd
25
- end
26
-
27
- def call(env)
28
- if env[:request][:statsd_path]
29
- statsd_path = env[:request][:statsd_path]
30
- elsif env[:request][:saddle] && env[:request][:saddle][:call_chain] && env[:request][:saddle][:action]
31
- statsd_path = (env[:request][:saddle][:call_chain] + [env[:request][:saddle][:action]]).join(".")
32
- end
33
-
34
- if statsd_path
35
- self.statsd.time statsd_path do
36
- @app.call(env)
37
- end
38
- else
39
- @app.call(env)
40
- end
41
- end
42
-
43
- end
44
-
45
- end
@@ -1,34 +0,0 @@
1
- require 'saddle'
2
-
3
- describe Saddle::Client do
4
-
5
- context "instance" do
6
- before :each do
7
- stubs = Faraday::Adapter::Test::Stubs.new do |stub|
8
- stub.get('/test') {
9
- [
10
- 200,
11
- {'Content-Type' => 'application/x-www-form-urlencoded'},
12
- 'success'
13
- ]
14
- }
15
- stub.get('/test.json') {
16
- [
17
- 200,
18
- {'Content-Type' => 'application/json'},
19
- {'success' => true}.to_json
20
- ]
21
- }
22
- end
23
- @client = Saddle::Client.create(:stubs => stubs)
24
- end
25
-
26
- it "should be able to request urlencoded" do
27
- @client.requester.get('/test').should == 'success'
28
- end
29
-
30
- it "should be able to request JSON encoded" do
31
- @client.requester.get('/test.json')['success'].should == true
32
- end
33
- end
34
- end