faraday 0.9.0 → 0.9.1

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,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 0e442daff424089e143751d7cb1d684c169bf4fc
4
- data.tar.gz: ba1dd50171576d5064350e48b8869364c0710a26
3
+ metadata.gz: 1c31dbb021fc6a43b4f0b102a9a3ccf52a72303a
4
+ data.tar.gz: 54da868027777adb5a21145bd6433b0154af2297
5
5
  SHA512:
6
- metadata.gz: 80c7a955f7d0a2217fcde0be2760649b9e5fc2d950929b118383ba61ea7282410b224315e289b40fec12be13898b0b00551e441704462ac39269368a8f9d5931
7
- data.tar.gz: cdef47ebdb9519d0e45e7511326ed1368fa520ad314a4055ea154187193c967f8821573705161e3bbca5d3cbbf40f219071223ba8d24821c5dd89e37ddd16a9e
6
+ metadata.gz: 22c1c286687ca596bd1d6b7d9a6a3749731f6d8962a5bbbe7e1e39cf22e364b92010ae44446cf1804ba10567a2e6409cc2be537375d9f47ace9bca909196dcd3
7
+ data.tar.gz: 7e8116cdeea918b8e7de661ec6d49d839960e26f136903e53db62e8cc353f89b3ac053d5efe6401995129418ae4dfce8fda9c8a471093223dca08002615d10e1
@@ -1,5 +1,10 @@
1
1
  # Faraday Changelog
2
2
 
3
+ ## v0.9.1
4
+
5
+ * Refactor Net:HTTP adapter so that with_net_http_connection can be overridden to allow pooled connections. (@Ben-M)
6
+ * Add configurable methods that bypass `retry_if` in the Retry request middleware. (@mike-bourgeous)
7
+
3
8
  ## v0.9.0
4
9
 
5
10
  * Add HTTPClient adapter (@hakanensari)
@@ -28,9 +28,9 @@ We will accept adapters that:
28
28
  2. if they have features not present in included adapters.
29
29
 
30
30
  We are pushing towards a 1.0 release, when we will have to follow [Semantic
31
- Versioning][semver]. If your patch includes changes to break compatiblitity,
31
+ Versioning][semver]. If your patch includes changes to break compatibility,
32
32
  note that so we can add it to the [Changelog][].
33
33
 
34
34
  [semver]: http://semver.org/
35
- [changelog]: https://github.com/technoweenie/faraday/wiki/Changelog
36
- [faraday_middleware]: https://github.com/pengwynn/faraday_middleware/wiki
35
+ [changelog]: https://github.com/lostisland/faraday/wiki/Changelog
36
+ [faraday_middleware]: https://github.com/lostisland/faraday_middleware/wiki
data/Gemfile CHANGED
@@ -13,17 +13,13 @@ group :test do
13
13
  gem 'leftright', '>= 0.9', :require => false
14
14
  gem 'mime-types', '~> 1.25', :platforms => [:jruby, :ruby_18]
15
15
  gem 'minitest', '>= 5.0.5'
16
- gem 'net-http-persistent', '>= 2.5', :require => false
16
+ gem 'net-http-persistent', '>= 2.9.4'
17
17
  gem 'patron', '>= 0.4.2', :platforms => :ruby
18
18
  gem 'rack-test', '>= 0.6', :require => 'rack/test'
19
+ gem 'rest-client', '~> 1.6.0', :platforms => [:jruby, :ruby_18]
19
20
  gem 'simplecov'
20
21
  gem 'sinatra', '~> 1.3'
21
22
  gem 'typhoeus', '~> 0.3.3', :platforms => :ruby
22
23
  end
23
24
 
24
- platforms :rbx do
25
- gem 'rubinius-coverage'
26
- gem 'rubysl'
27
- end
28
-
29
25
  gemspec
data/README.md CHANGED
@@ -11,6 +11,7 @@ Faraday supports these adapters:
11
11
  * [Typhoeus][]
12
12
  * [Patron][]
13
13
  * [EventMachine][]
14
+ * [HTTPClient][]
14
15
 
15
16
  It also includes a Rack adapter for hitting loaded Rack applications through
16
17
  Rack::Test, and a Test adapter for stubbing requests by hand.
@@ -29,7 +30,7 @@ end
29
30
  response = conn.get '/nigiri/sake.json' # GET http://sushi.com/nigiri/sake.json
30
31
  response.body
31
32
 
32
- conn.get '/nigiri', { :name => 'Maguro' } # GET /nigiri?name=Maguro
33
+ conn.get '/nigiri', { :name => 'Maguro' } # GET http://sushi.com/nigiri?name=Maguro
33
34
 
34
35
  conn.get do |req| # GET http://sushi.com/search?page=2&limit=100
35
36
  req.url '/search', :page => 2
@@ -56,10 +57,10 @@ conn.get do |req|
56
57
  end
57
58
  ```
58
59
 
59
- If you don't need to set up anything, you can roll with just the bare minimum:
60
+ If you don't need to set up anything, you can roll with just the default middleware
61
+ stack and default adapter (see [Faraday::RackBuilder#initialize](https://github.com/lostisland/faraday/blob/master/lib/faraday/rack_builder.rb)):
60
62
 
61
63
  ```ruby
62
- # using the default stack:
63
64
  response = Faraday.get 'http://sushi.com/nigiri/sake.json'
64
65
  ```
65
66
 
@@ -106,11 +107,13 @@ Middleware are classes that implement a `call` instance method. They hook into
106
107
  the request/response cycle.
107
108
 
108
109
  ```ruby
109
- def call(env)
110
+ def call(request_env)
110
111
  # do something with the request
112
+ # request_env[:request_headers].merge!(...)
111
113
 
112
- @app.call(env).on_complete do
114
+ @app.call(request_env).on_complete do |response_env|
113
115
  # do something with the response
116
+ # response_env[:response_headers].merge!(...)
114
117
  end
115
118
  end
116
119
  ```
@@ -140,20 +143,20 @@ later, response. Some keys are:
140
143
  ```ruby
141
144
  # It's possible to define stubbed request outside a test adapter block.
142
145
  stubs = Faraday::Adapter::Test::Stubs.new do |stub|
143
- stub.get('/tamago') { [200, {}, 'egg'] }
146
+ stub.get('/tamago') { |env| [200, {}, 'egg'] }
144
147
  end
145
148
 
146
149
  # You can pass stubbed request to the test adapter or define them in a block
147
150
  # or a combination of the two.
148
151
  test = Faraday.new do |builder|
149
152
  builder.adapter :test, stubs do |stub|
150
- stub.get('/ebi') {[ 200, {}, 'shrimp' ]}
153
+ stub.get('/ebi') { |env| [ 200, {}, 'shrimp' ]}
151
154
  end
152
155
  end
153
156
 
154
157
  # It's also possible to stub additional requests after the connection has
155
158
  # been initialized. This is useful for testing.
156
- stubs.get('/uni') {[ 200, {}, 'urchin' ]}
159
+ stubs.get('/uni') { |env| [ 200, {}, 'urchin' ]}
157
160
 
158
161
  resp = test.get '/tamago'
159
162
  resp.body # => 'egg'
@@ -211,6 +214,7 @@ See [LICENSE][] for details.
211
214
  [typhoeus]: https://github.com/typhoeus/typhoeus#readme
212
215
  [patron]: http://toland.github.com/patron/
213
216
  [eventmachine]: https://github.com/igrigorik/em-http-request#readme
217
+ [httpclient]: https://github.com/nahi/httpclient
214
218
  [jruby]: http://jruby.org/
215
219
  [rubinius]: http://rubini.us/
216
220
  [license]: LICENSE.md
@@ -14,7 +14,7 @@ require 'forwardable'
14
14
  # conn.get '/'
15
15
  #
16
16
  module Faraday
17
- VERSION = "0.9.0"
17
+ VERSION = "0.9.1"
18
18
 
19
19
  class << self
20
20
  # Public: Gets or sets the root path that Faraday is being loaded from.
@@ -25,29 +25,31 @@ module Faraday
25
25
  ]
26
26
 
27
27
  NET_HTTP_EXCEPTIONS << OpenSSL::SSL::SSLError if defined?(OpenSSL)
28
+ NET_HTTP_EXCEPTIONS << Net::OpenTimeout if defined?(Net::OpenTimeout)
28
29
 
29
30
  def call(env)
30
31
  super
31
- http = net_http_connection(env)
32
- configure_ssl(http, env[:ssl]) if env[:url].scheme == 'https' and env[:ssl]
33
-
34
- req = env[:request]
35
- http.read_timeout = http.open_timeout = req[:timeout] if req[:timeout]
36
- http.open_timeout = req[:open_timeout] if req[:open_timeout]
37
-
38
- begin
39
- http_response = perform_request(http, env)
40
- rescue *NET_HTTP_EXCEPTIONS => err
41
- if defined?(OpenSSL) && OpenSSL::SSL::SSLError === err
42
- raise Faraday::SSLError, err
43
- else
44
- raise Error::ConnectionFailed, err
32
+ with_net_http_connection(env) do |http|
33
+ configure_ssl(http, env[:ssl]) if env[:url].scheme == 'https' and env[:ssl]
34
+
35
+ req = env[:request]
36
+ http.read_timeout = http.open_timeout = req[:timeout] if req[:timeout]
37
+ http.open_timeout = req[:open_timeout] if req[:open_timeout]
38
+
39
+ begin
40
+ http_response = perform_request(http, env)
41
+ rescue *NET_HTTP_EXCEPTIONS => err
42
+ if defined?(OpenSSL) && OpenSSL::SSL::SSLError === err
43
+ raise Faraday::SSLError, err
44
+ else
45
+ raise Error::ConnectionFailed, err
46
+ end
45
47
  end
46
- end
47
48
 
48
- save_response(env, http_response.code.to_i, http_response.body || '') do |response_headers|
49
- http_response.each_header do |key, value|
50
- response_headers[key] = value
49
+ save_response(env, http_response.code.to_i, http_response.body || '') do |response_headers|
50
+ http_response.each_header do |key, value|
51
+ response_headers[key] = value
52
+ end
51
53
  end
52
54
  end
53
55
 
@@ -81,6 +83,10 @@ module Faraday
81
83
  end
82
84
  end
83
85
 
86
+ def with_net_http_connection(env)
87
+ yield net_http_connection(env)
88
+ end
89
+
84
90
  def net_http_connection(env)
85
91
  if proxy = env[:request][:proxy]
86
92
  Net::HTTP::Proxy(proxy[:uri].host, proxy[:uri].port, proxy[:user], proxy[:password])
@@ -8,7 +8,7 @@ module Faraday
8
8
  class NetHttpPersistent < NetHttp
9
9
  dependency 'net/http/persistent'
10
10
 
11
- def net_http_connection(env)
11
+ def with_net_http_connection(env)
12
12
  if proxy = env[:request][:proxy]
13
13
  proxy_uri = ::URI::HTTP === proxy[:uri] ? proxy[:uri].dup : ::URI.parse(proxy[:uri].to_s)
14
14
  proxy_uri.user = proxy_uri.password = nil
@@ -18,7 +18,8 @@ module Faraday
18
18
  define_method(:password) { proxy[:password] }
19
19
  end if proxy[:user]
20
20
  end
21
- Net::HTTP::Persistent.new 'Faraday', proxy_uri
21
+
22
+ yield Net::HTTP::Persistent.new 'Faraday', proxy_uri
22
23
  end
23
24
 
24
25
  def perform_request(http, env)
@@ -39,7 +39,11 @@ module Faraday
39
39
 
40
40
  @app.call env
41
41
  rescue ::Patron::TimeoutError => err
42
- raise Faraday::Error::TimeoutError, err
42
+ if err.message == "Connection time-out"
43
+ raise Faraday::Error::ConnectionFailed, err
44
+ else
45
+ raise Faraday::Error::TimeoutError, err
46
+ end
43
47
  rescue ::Patron::Error => err
44
48
  if err.message.include?("code 407")
45
49
  raise Error::ConnectionFailed, %{407 "Proxy Authentication Required "}
@@ -69,7 +69,6 @@ module Faraday
69
69
  :UrlEncoded => 'url_encoded',
70
70
  :Multipart => 'multipart',
71
71
  :Retry => 'retry',
72
- :Timeout => 'timeout',
73
72
  :Authorization => 'authorization',
74
73
  :BasicAuthentication => 'basic_authentication',
75
74
  :TokenAuthentication => 'token_authentication',
@@ -1,15 +1,10 @@
1
+ require "forwardable"
2
+
1
3
  module Faraday
2
4
  module NestedParamsEncoder
3
- ESCAPE_RE = /[^a-zA-Z0-9 .~_-]/
4
-
5
- def self.escape(s)
6
- return s.to_s.gsub(ESCAPE_RE) {
7
- '%' + $&.unpack('H2' * $&.bytesize).join('%').upcase
8
- }.tr(' ', '+')
9
- end
10
-
11
- def self.unescape(s)
12
- CGI.unescape(s.to_s)
5
+ class << self
6
+ extend Forwardable
7
+ def_delegators :'Faraday::Utils', :escape, :unescape
13
8
  end
14
9
 
15
10
  def self.encode(params)
@@ -117,16 +112,9 @@ module Faraday
117
112
  end
118
113
 
119
114
  module FlatParamsEncoder
120
- ESCAPE_RE = /[^a-zA-Z0-9 .~_-]/
121
-
122
- def self.escape(s)
123
- return s.to_s.gsub(ESCAPE_RE) {
124
- '%' + $&.unpack('H2' * $&.bytesize).join('%').upcase
125
- }.tr(' ', '+')
126
- end
127
-
128
- def self.unescape(s)
129
- CGI.unescape(s.to_s)
115
+ class << self
116
+ extend Forwardable
117
+ def_delegators :'Faraday::Utils', :escape, :unescape
130
118
  end
131
119
 
132
120
  def self.encode(params)
@@ -19,7 +19,13 @@ module Faraday
19
19
  # interval that is random between 0.1 and 0.15
20
20
  #
21
21
  class Request::Retry < Faraday::Middleware
22
- class Options < Faraday::Options.new(:max, :interval, :interval_randomness, :backoff_factor, :exceptions)
22
+
23
+ IDEMPOTENT_METHODS = [:delete, :get, :head, :options, :put]
24
+
25
+ class Options < Faraday::Options.new(:max, :interval, :interval_randomness, :backoff_factor,
26
+ :exceptions, :methods, :retry_if)
27
+ DEFAULT_CHECK = lambda { |env,exception| false }
28
+
23
29
  def self.from(value)
24
30
  if Fixnum === value
25
31
  new(value)
@@ -49,6 +55,14 @@ module Faraday
49
55
  Error::TimeoutError])
50
56
  end
51
57
 
58
+ def methods
59
+ Array(self[:methods] ||= IDEMPOTENT_METHODS)
60
+ end
61
+
62
+ def retry_if
63
+ self[:retry_if] ||= DEFAULT_CHECK
64
+ end
65
+
52
66
  end
53
67
 
54
68
  # Public: Initialize middleware
@@ -66,6 +80,15 @@ module Faraday
66
80
  # given as Class, Module, or String. (default:
67
81
  # [Errno::ETIMEDOUT, Timeout::Error,
68
82
  # Error::TimeoutError])
83
+ # methods - A list of HTTP methods to retry without calling retry_if. Pass
84
+ # an empty Array to call retry_if for all exceptions.
85
+ # (defaults to the idempotent HTTP methods in IDEMPOTENT_METHODS)
86
+ # retry_if - block that will receive the env object and the exception raised
87
+ # and should decide if the code should retry still the action or
88
+ # not independent of the retry count. This would be useful
89
+ # if the exception produced is non-recoverable or if the
90
+ # the HTTP method called is not idempotent.
91
+ # (defaults to return false)
69
92
  def initialize(app, options = nil)
70
93
  super(app)
71
94
  @options = Options.from(options)
@@ -85,8 +108,8 @@ module Faraday
85
108
  begin
86
109
  env[:body] = request_body # after failure env[:body] is set to the response body
87
110
  @app.call(env)
88
- rescue @errmatch
89
- if retries > 0
111
+ rescue @errmatch => exception
112
+ if retries > 0 && retry_request?(env, exception)
90
113
  retries -= 1
91
114
  sleep sleep_amount(retries + 1)
92
115
  retry
@@ -114,5 +137,12 @@ module Faraday
114
137
  end
115
138
  matcher
116
139
  end
140
+
141
+ private
142
+
143
+ def retry_request?(env, exception)
144
+ @options.methods.include?(env[:method]) || @options.retry_if.call(env, exception)
145
+ end
146
+
117
147
  end
118
148
  end
@@ -61,8 +61,8 @@ module Faraday
61
61
 
62
62
  def finish(env)
63
63
  raise "response already finished" if finished?
64
- @env = Env.from(env)
65
64
  @on_complete_callbacks.each { |callback| callback.call(env) }
65
+ @env = Env.from(env)
66
66
  return self
67
67
  end
68
68
 
@@ -4,12 +4,15 @@ module Faraday
4
4
  class Response::Logger < Response::Middleware
5
5
  extend Forwardable
6
6
 
7
- def initialize(app, logger = nil)
7
+ DEFAULT_OPTIONS = { :bodies => false }
8
+
9
+ def initialize(app, logger = nil, options = {})
8
10
  super(app)
9
11
  @logger = logger || begin
10
12
  require 'logger'
11
13
  ::Logger.new(STDOUT)
12
14
  end
15
+ @options = DEFAULT_OPTIONS.merge(options)
13
16
  end
14
17
 
15
18
  def_delegators :@logger, :debug, :info, :warn, :error, :fatal
@@ -17,12 +20,14 @@ module Faraday
17
20
  def call(env)
18
21
  info "#{env.method} #{env.url.to_s}"
19
22
  debug('request') { dump_headers env.request_headers }
23
+ debug('request') { dump_body(env[:body]) } if env[:body] && log_body?(:request)
20
24
  super
21
25
  end
22
26
 
23
27
  def on_complete(env)
24
28
  info('Status') { env.status.to_s }
25
29
  debug('response') { dump_headers env.response_headers }
30
+ debug('response') { dump_body env[:body] } if env[:body] && log_body?(:response)
26
31
  end
27
32
 
28
33
  private
@@ -30,5 +35,25 @@ module Faraday
30
35
  def dump_headers(headers)
31
36
  headers.map { |k, v| "#{k}: #{v.inspect}" }.join("\n")
32
37
  end
38
+
39
+ def dump_body(body)
40
+ if body.respond_to?(:to_str)
41
+ body.to_str
42
+ else
43
+ pretty_inspect(body)
44
+ end
45
+ end
46
+
47
+ def pretty_inspect(body)
48
+ require 'pp' unless body.respond_to?(:pretty_inspect)
49
+ body.pretty_inspect
50
+ end
51
+
52
+ def log_body?(type)
53
+ case @options[:bodies]
54
+ when Hash then @options[:bodies][type]
55
+ else @options[:bodies]
56
+ end
57
+ end
33
58
  end
34
59
  end
@@ -0,0 +1,46 @@
1
+ #!/usr/bin/env bash
2
+ # Usage: cached-bundle install --deployment
3
+ #
4
+ # After running `bundle`, caches the `./bundle` directory to S3.
5
+ # On the next run, restores the cached directory before running `bundle`.
6
+ # When `Gemfile` changes, the cache gets rebuilt.
7
+ #
8
+ # Requirements:
9
+ # - Gemfile
10
+ # - TRAVIS_REPO_SLUG
11
+ # - TRAVIS_RUBY_VERSION
12
+ # - AMAZON_S3_BUCKET
13
+ # - script/s3-put
14
+ # - bundle
15
+ # - curl
16
+ #
17
+ # Author: Mislav Marohnić
18
+
19
+ set -e
20
+
21
+ compute_md5() {
22
+ local output="$(openssl md5)"
23
+ echo "${output##* }"
24
+ }
25
+
26
+ download() {
27
+ curl --tcp-nodelay -qsfL "$1" -o "$2"
28
+ }
29
+
30
+ bundle_path="bundle"
31
+ gemfile_hash="$(compute_md5 <"${BUNDLE_GEMFILE:-Gemfile}")"
32
+ cache_name="${TRAVIS_RUBY_VERSION}-${gemfile_hash}.tgz"
33
+ fetch_url="http://${AMAZON_S3_BUCKET}.s3.amazonaws.com/${TRAVIS_REPO_SLUG}/${cache_name}"
34
+
35
+ if download "$fetch_url" "$cache_name"; then
36
+ echo "Reusing cached bundle ${cache_name}"
37
+ tar xzf "$cache_name"
38
+ fi
39
+
40
+ bundle "$@"
41
+
42
+ if [ ! -f "$cache_name" ] && [ -n "$AMAZON_SECRET_ACCESS_KEY" ]; then
43
+ echo "Caching \`${bundle_path}' to S3"
44
+ tar czf "$cache_name" "$bundle_path"
45
+ script/s3-put "$cache_name" "${AMAZON_S3_BUCKET}:${TRAVIS_REPO_SLUG}/${cache_name}"
46
+ fi
@@ -0,0 +1,71 @@
1
+ #!/usr/bin/env bash
2
+ # Usage: s3-put <FILE> <S3_BUCKET>[:<PATH>] [<CONTENT_TYPE>]
3
+ #
4
+ # Uploads a file to the Amazon S3 service.
5
+ # Outputs the URL for the newly uploaded file.
6
+ #
7
+ # Requirements:
8
+ # - AMAZON_ACCESS_KEY_ID
9
+ # - AMAZON_SECRET_ACCESS_KEY
10
+ # - openssl
11
+ # - curl
12
+ #
13
+ # Author: Mislav Marohnić
14
+
15
+ set -e
16
+
17
+ authorization() {
18
+ local signature="$(string_to_sign | hmac_sha1 | base64)"
19
+ echo "AWS ${AMAZON_ACCESS_KEY_ID?}:${signature}"
20
+ }
21
+
22
+ hmac_sha1() {
23
+ openssl dgst -binary -sha1 -hmac "${AMAZON_SECRET_ACCESS_KEY?}"
24
+ }
25
+
26
+ base64() {
27
+ openssl enc -base64
28
+ }
29
+
30
+ bin_md5() {
31
+ openssl dgst -binary -md5
32
+ }
33
+
34
+ string_to_sign() {
35
+ echo "$http_method"
36
+ echo "$content_md5"
37
+ echo "$content_type"
38
+ echo "$date"
39
+ echo "x-amz-acl:$acl"
40
+ printf "/$bucket/$remote_path"
41
+ }
42
+
43
+ date_string() {
44
+ LC_TIME=C date "+%a, %d %h %Y %T %z"
45
+ }
46
+
47
+ file="$1"
48
+ bucket="${2%%:*}"
49
+ remote_path="${2#*:}"
50
+ content_type="$3"
51
+
52
+ if [ -z "$remote_path" ] || [ "$remote_path" = "$bucket" ]; then
53
+ remote_path="${file##*/}"
54
+ fi
55
+
56
+ http_method=PUT
57
+ acl="public-read"
58
+ content_md5="$(bin_md5 < "$file" | base64)"
59
+ date="$(date_string)"
60
+
61
+ url="https://$bucket.s3.amazonaws.com/$remote_path"
62
+
63
+ curl -qsSf -T "$file" \
64
+ -H "Authorization: $(authorization)" \
65
+ -H "x-amz-acl: $acl" \
66
+ -H "Date: $date" \
67
+ -H "Content-MD5: $content_md5" \
68
+ -H "Content-Type: $content_type" \
69
+ "$url"
70
+
71
+ echo "$url"
@@ -4,17 +4,27 @@ require 'logger'
4
4
 
5
5
  module Adapters
6
6
  class LoggerTest < Faraday::TestCase
7
- def setup
8
- @io = StringIO.new
9
- @logger = Logger.new(@io)
10
- @logger.level = Logger::DEBUG
7
+ def conn(logger, logger_options={})
8
+ rubbles = ['Barney', 'Betty', 'Bam Bam']
11
9
 
12
- @conn = Faraday.new do |b|
13
- b.response :logger, @logger
10
+ Faraday.new do |b|
11
+ b.response :logger, logger, logger_options
14
12
  b.adapter :test do |stubs|
15
13
  stubs.get('/hello') { [200, {'Content-Type' => 'text/html'}, 'hello'] }
14
+ stubs.post('/ohai') { [200, {'Content-Type' => 'text/html'}, 'fred'] }
15
+ stubs.get('/ohno') { [200, {'Content-Type' => 'text/html'}, 'wilma'] }
16
+ stubs.post('/ohyes') { [200, {'Content-Type' => 'text/html'}, 'pebbles'] }
17
+ stubs.get('/rubbles') { [200, {'Content-Type' => 'application/json'}, rubbles] }
16
18
  end
17
19
  end
20
+ end
21
+
22
+ def setup
23
+ @io = StringIO.new
24
+ @logger = Logger.new(@io)
25
+ @logger.level = Logger::DEBUG
26
+
27
+ @conn = conn(@logger)
18
28
  @resp = @conn.get '/hello', nil, :accept => 'text/html'
19
29
  end
20
30
 
@@ -33,5 +43,40 @@ module Adapters
33
43
  def test_logs_response_headers
34
44
  assert_match %(Content-Type: "text/html), @io.string
35
45
  end
46
+
47
+ def test_does_not_log_request_body_by_default
48
+ @conn.post '/ohai', 'name=Unagi', :accept => 'text/html'
49
+ refute_match %(name=Unagi), @io.string
50
+ end
51
+
52
+ def test_does_not_log_response_body_by_default
53
+ @conn.post '/ohai', 'name=Toro', :accept => 'text/html'
54
+ refute_match %(fred), @io.string
55
+ end
56
+
57
+ def test_log_request_body
58
+ app = conn(@logger, :bodies => { :request => true })
59
+ app.post '/ohyes', 'name=Tamago', :accept => 'text/html'
60
+ assert_match %(name=Tamago), @io.string
61
+ end
62
+
63
+ def test_log_response_body
64
+ app = conn(@logger, :bodies => { :response => true })
65
+ app.get '/ohno', :accept => 'text/html'
66
+ assert_match %(wilma), @io.string
67
+ end
68
+
69
+ def test_log_request_and_response_body
70
+ app = conn(@logger, :bodies => true)
71
+ app.post '/ohyes', 'name=Ebi', :accept => 'text/html'
72
+ assert_match %(name=Ebi), @io.string
73
+ assert_match %(pebbles), @io.string
74
+ end
75
+
76
+ def test_log_response_body_object
77
+ app = conn(@logger, :bodies => true)
78
+ app.get '/rubbles', nil, :accept => 'text/html'
79
+ assert_match %([\"Barney\", \"Betty\", \"Bam Bam\"]\n), @io.string
80
+ end
36
81
  end
37
82
  end
@@ -166,6 +166,14 @@ class ResponseTest < Faraday::TestCase
166
166
  end
167
167
  end
168
168
 
169
+ def test_body_is_parsed_on_finish
170
+ response = Faraday::Response.new
171
+ response.on_complete { |env| env[:body] = env[:body].upcase }
172
+ response.finish(@env)
173
+
174
+ assert_equal "YIKES", response.body
175
+ end
176
+
169
177
  def test_not_success
170
178
  assert !@response.success?
171
179
  end
@@ -1,14 +1,14 @@
1
- require 'rubygems' # rubygems/version doesn't work by itself
2
- require 'rubygems/version' # for simplecov-html
3
- require 'simplecov'
4
- require 'coveralls'
1
+ if RUBY_VERSION >= '1.9'
2
+ require 'simplecov'
3
+ require 'coveralls'
5
4
 
6
- SimpleCov.formatter = SimpleCov::Formatter::MultiFormatter[
7
- SimpleCov::Formatter::HTMLFormatter,
8
- Coveralls::SimpleCov::Formatter
9
- ]
10
- SimpleCov.start do
11
- add_filter '/bundle/'
5
+ SimpleCov.formatters = [SimpleCov::Formatter::HTMLFormatter, Coveralls::SimpleCov::Formatter]
6
+
7
+ SimpleCov.start do
8
+ add_filter '/bundle/'
9
+ add_filter '/test/'
10
+ minimum_coverage(87.27)
11
+ end
12
12
  end
13
13
 
14
14
  gem 'minitest' if defined? Bundler
@@ -10,43 +10,57 @@ module Middleware
10
10
  Faraday.new do |b|
11
11
  b.request :retry, *retry_args
12
12
  b.adapter :test do |stub|
13
- stub.post('/unstable') {
14
- @times_called += 1
15
- @explode.call @times_called
16
- }
13
+ ['get', 'post'].each do |method|
14
+ stub.send(method, '/unstable') {
15
+ @times_called += 1
16
+ @explode.call @times_called
17
+ }
18
+ end
17
19
  end
18
20
  end
19
21
  end
20
22
 
21
23
  def test_unhandled_error
22
24
  @explode = lambda {|n| raise "boom!" }
23
- assert_raises(RuntimeError) { conn.post("/unstable") }
25
+ assert_raises(RuntimeError) { conn.get("/unstable") }
24
26
  assert_equal 1, @times_called
25
27
  end
26
28
 
27
29
  def test_handled_error
28
30
  @explode = lambda {|n| raise Errno::ETIMEDOUT }
29
- assert_raises(Errno::ETIMEDOUT) { conn.post("/unstable") }
31
+ assert_raises(Errno::ETIMEDOUT) { conn.get("/unstable") }
30
32
  assert_equal 3, @times_called
31
33
  end
32
34
 
33
35
  def test_legacy_max_retries
34
36
  @explode = lambda {|n| raise Errno::ETIMEDOUT }
35
- assert_raises(Errno::ETIMEDOUT) { conn(1).post("/unstable") }
37
+ assert_raises(Errno::ETIMEDOUT) { conn(1).get("/unstable") }
36
38
  assert_equal 2, @times_called
37
39
  end
38
40
 
41
+ def test_legacy_max_negative_retries
42
+ @explode = lambda {|n| raise Errno::ETIMEDOUT }
43
+ assert_raises(Errno::ETIMEDOUT) { conn(-9).get("/unstable") }
44
+ assert_equal 1, @times_called
45
+ end
46
+
39
47
  def test_new_max_retries
40
48
  @explode = lambda {|n| raise Errno::ETIMEDOUT }
41
- assert_raises(Errno::ETIMEDOUT) { conn(:max => 3).post("/unstable") }
49
+ assert_raises(Errno::ETIMEDOUT) { conn(:max => 3).get("/unstable") }
42
50
  assert_equal 4, @times_called
43
51
  end
44
52
 
53
+ def test_new_max_negative_retries
54
+ @explode = lambda { |n| raise Errno::ETIMEDOUT }
55
+ assert_raises(Errno::ETIMEDOUT) { conn(:max => -9).get("/unstable") }
56
+ assert_equal 1, @times_called
57
+ end
58
+
45
59
  def test_interval
46
60
  @explode = lambda {|n| raise Errno::ETIMEDOUT }
47
61
  started = Time.now
48
62
  assert_raises(Errno::ETIMEDOUT) {
49
- conn(:max => 2, :interval => 0.1).post("/unstable")
63
+ conn(:max => 2, :interval => 0.1).get("/unstable")
50
64
  }
51
65
  assert_in_delta 0.2, Time.now - started, 0.04
52
66
  end
@@ -70,7 +84,7 @@ module Middleware
70
84
  retry_middleware.sleep_amount_retries = [2, 1]
71
85
 
72
86
  assert_raises(Errno::ETIMEDOUT) {
73
- retry_middleware.call({})
87
+ retry_middleware.call({:method => :get})
74
88
  }
75
89
 
76
90
  assert_empty retry_middleware.sleep_amount_retries
@@ -101,9 +115,63 @@ module Middleware
101
115
  def test_custom_exceptions
102
116
  @explode = lambda {|n| raise "boom!" }
103
117
  assert_raises(RuntimeError) {
104
- conn(:exceptions => StandardError).post("/unstable")
118
+ conn(:exceptions => StandardError).get("/unstable")
119
+ }
120
+ assert_equal 3, @times_called
121
+ end
122
+
123
+ def test_should_stop_retrying_if_block_returns_false_checking_env
124
+ @explode = lambda {|n| raise Errno::ETIMEDOUT }
125
+ check = lambda { |env,exception| env[:method] != :post }
126
+ assert_raises(Errno::ETIMEDOUT) {
127
+ conn(:retry_if => check).post("/unstable")
128
+ }
129
+ assert_equal 1, @times_called
130
+ end
131
+
132
+ def test_should_stop_retrying_if_block_returns_false_checking_exception
133
+ @explode = lambda {|n| raise Errno::ETIMEDOUT }
134
+ check = lambda { |env,exception| !exception.kind_of?(Errno::ETIMEDOUT) }
135
+ assert_raises(Errno::ETIMEDOUT) {
136
+ conn(:retry_if => check).post("/unstable")
137
+ }
138
+ assert_equal 1, @times_called
139
+ end
140
+
141
+ def test_should_not_call_retry_if_for_idempotent_methods_if_methods_unspecified
142
+ @explode = lambda {|n| raise Errno::ETIMEDOUT }
143
+ check = lambda { |env,exception| raise "this should have never been called" }
144
+ assert_raises(Errno::ETIMEDOUT) {
145
+ conn(:retry_if => check).get("/unstable")
146
+ }
147
+ assert_equal 3, @times_called
148
+ end
149
+
150
+ def test_should_not_retry_for_non_idempotent_method_if_methods_unspecified
151
+ @explode = lambda {|n| raise Errno::ETIMEDOUT }
152
+ assert_raises(Errno::ETIMEDOUT) {
153
+ conn.post("/unstable")
154
+ }
155
+ assert_equal 1, @times_called
156
+ end
157
+
158
+ def test_should_not_call_retry_if_for_specified_methods
159
+ @explode = lambda {|n| raise Errno::ETIMEDOUT }
160
+ check = lambda { |env,exception| raise "this should have never been called" }
161
+ assert_raises(Errno::ETIMEDOUT) {
162
+ conn(:retry_if => check, :methods => [:post]).post("/unstable")
105
163
  }
106
164
  assert_equal 3, @times_called
107
165
  end
166
+
167
+ def test_should_call_retry_if_for_empty_method_list
168
+ @explode = lambda {|n| raise Errno::ETIMEDOUT }
169
+ check = lambda { |env,exception| @times_called < 2 }
170
+ assert_raises(Errno::ETIMEDOUT) {
171
+ conn(:retry_if => check, :methods => []).get("/unstable")
172
+ }
173
+ assert_equal 2, @times_called
174
+ end
175
+
108
176
  end
109
177
  end
@@ -0,0 +1,64 @@
1
+ require File.expand_path("../helper", __FILE__)
2
+
3
+ class TestParameters < Faraday::TestCase
4
+ # emulates ActiveSupport::SafeBuffer#gsub
5
+ FakeSafeBuffer = Struct.new(:string) do
6
+ def to_s() self end
7
+ def gsub(regex)
8
+ string.gsub(regex) {
9
+ match, = $&, '' =~ /a/
10
+ yield(match)
11
+ }
12
+ end
13
+ end
14
+
15
+ def test_escaping_safe_buffer_nested
16
+ monies = FakeSafeBuffer.new("$32,000.00")
17
+ assert_equal "a=%2432%2C000.00", Faraday::NestedParamsEncoder.encode("a" => monies)
18
+ end
19
+
20
+ def test_escaping_safe_buffer_flat
21
+ monies = FakeSafeBuffer.new("$32,000.00")
22
+ assert_equal "a=%2432%2C000.00", Faraday::FlatParamsEncoder.encode("a" => monies)
23
+ end
24
+
25
+ def test_raises_typeerror_nested
26
+ error = assert_raises TypeError do
27
+ Faraday::NestedParamsEncoder.encode("")
28
+ end
29
+ assert_equal "Can't convert String into Hash.", error.message
30
+ end
31
+
32
+ def test_raises_typeerror_flat
33
+ error = assert_raises TypeError do
34
+ Faraday::FlatParamsEncoder.encode("")
35
+ end
36
+ assert_equal "Can't convert String into Hash.", error.message
37
+ end
38
+
39
+ def test_decode_array_nested
40
+ query = "a[1]=one&a[2]=two&a[3]=three"
41
+ expected = {"a" => ["one", "two", "three"]}
42
+ assert_equal expected, Faraday::NestedParamsEncoder.decode(query)
43
+ end
44
+
45
+ def test_decode_array_flat
46
+ query = "a=one&a=two&a=three"
47
+ expected = {"a" => ["one", "two", "three"]}
48
+ assert_equal expected, Faraday::FlatParamsEncoder.decode(query)
49
+ end
50
+
51
+ def test_nested_decode_hash
52
+ query = "a[b1]=one&a[b2]=two&a[b][c]=foo"
53
+ expected = {"a" => {"b1" => "one", "b2" => "two", "b" => {"c" => "foo"}}}
54
+ assert_equal expected, Faraday::NestedParamsEncoder.decode(query)
55
+ end
56
+
57
+ def test_encode_nil_nested
58
+ assert_equal "a=", Faraday::NestedParamsEncoder.encode("a" => nil)
59
+ end
60
+
61
+ def test_encode_nil_flat
62
+ assert_equal "a", Faraday::FlatParamsEncoder.encode("a" => nil)
63
+ end
64
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: faraday
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.9.0
4
+ version: 0.9.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Rick Olson
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-01-16 00:00:00.000000000 Z
11
+ date: 2015-01-07 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: multipart-post
@@ -92,11 +92,13 @@ files:
92
92
  - lib/faraday/response/raise_error.rb
93
93
  - lib/faraday/upload_io.rb
94
94
  - lib/faraday/utils.rb
95
+ - script/cached-bundle
95
96
  - script/console
96
97
  - script/generate_certs
97
98
  - script/package
98
99
  - script/proxy-server
99
100
  - script/release
101
+ - script/s3-put
100
102
  - script/server
101
103
  - script/test
102
104
  - test/adapters/default_test.rb
@@ -123,6 +125,7 @@ files:
123
125
  - test/middleware_stack_test.rb
124
126
  - test/multibyte.txt
125
127
  - test/options_test.rb
128
+ - test/parameters_test.rb
126
129
  - test/request_middleware_test.rb
127
130
  - test/response_middleware_test.rb
128
131
  - test/strawberry.rb
@@ -147,7 +150,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
147
150
  version: 1.3.5
148
151
  requirements: []
149
152
  rubyforge_project:
150
- rubygems_version: 2.2.0
153
+ rubygems_version: 2.2.2
151
154
  signing_key:
152
155
  specification_version: 2
153
156
  summary: HTTP/REST API client library.
@@ -175,6 +178,7 @@ test_files:
175
178
  - test/middleware/retry_test.rb
176
179
  - test/middleware_stack_test.rb
177
180
  - test/options_test.rb
181
+ - test/parameters_test.rb
178
182
  - test/request_middleware_test.rb
179
183
  - test/response_middleware_test.rb
180
184
  - test/strawberry.rb