faraday 0.9.0 → 0.9.1

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