saddle 0.0.5 → 0.0.6

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