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 +4 -4
- data/CHANGELOG.md +5 -0
- data/CONTRIBUTING.md +3 -3
- data/Gemfile +2 -6
- data/README.md +12 -8
- data/lib/faraday.rb +1 -1
- data/lib/faraday/adapter/net_http.rb +24 -18
- data/lib/faraday/adapter/net_http_persistent.rb +3 -2
- data/lib/faraday/adapter/patron.rb +5 -1
- data/lib/faraday/autoload.rb +0 -1
- data/lib/faraday/parameters.rb +8 -20
- data/lib/faraday/request/retry.rb +33 -3
- data/lib/faraday/response.rb +1 -1
- data/lib/faraday/response/logger.rb +26 -1
- data/script/cached-bundle +46 -0
- data/script/s3-put +71 -0
- data/test/adapters/logger_test.rb +51 -6
- data/test/env_test.rb +8 -0
- data/test/helper.rb +10 -10
- data/test/middleware/retry_test.rb +79 -11
- data/test/parameters_test.rb +64 -0
- metadata +7 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 1c31dbb021fc6a43b4f0b102a9a3ccf52a72303a
|
4
|
+
data.tar.gz: 54da868027777adb5a21145bd6433b0154af2297
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 22c1c286687ca596bd1d6b7d9a6a3749731f6d8962a5bbbe7e1e39cf22e364b92010ae44446cf1804ba10567a2e6409cc2be537375d9f47ace9bca909196dcd3
|
7
|
+
data.tar.gz: 7e8116cdeea918b8e7de661ec6d49d839960e26f136903e53db62e8cc353f89b3ac053d5efe6401995129418ae4dfce8fda9c8a471093223dca08002615d10e1
|
data/CHANGELOG.md
CHANGED
@@ -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)
|
data/CONTRIBUTING.md
CHANGED
@@ -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
|
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/
|
36
|
-
[faraday_middleware]: https://github.com/
|
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.
|
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
|
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(
|
110
|
+
def call(request_env)
|
110
111
|
# do something with the request
|
112
|
+
# request_env[:request_headers].merge!(...)
|
111
113
|
|
112
|
-
@app.call(
|
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
|
data/lib/faraday.rb
CHANGED
@@ -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
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
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
|
-
|
49
|
-
|
50
|
-
|
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
|
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
|
-
|
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
|
-
|
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 "}
|
data/lib/faraday/autoload.rb
CHANGED
@@ -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',
|
data/lib/faraday/parameters.rb
CHANGED
@@ -1,15 +1,10 @@
|
|
1
|
+
require "forwardable"
|
2
|
+
|
1
3
|
module Faraday
|
2
4
|
module NestedParamsEncoder
|
3
|
-
|
4
|
-
|
5
|
-
|
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
|
-
|
121
|
-
|
122
|
-
|
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
|
-
|
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
|
data/lib/faraday/response.rb
CHANGED
@@ -4,12 +4,15 @@ module Faraday
|
|
4
4
|
class Response::Logger < Response::Middleware
|
5
5
|
extend Forwardable
|
6
6
|
|
7
|
-
|
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
|
data/script/s3-put
ADDED
@@ -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
|
8
|
-
|
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
|
-
|
13
|
-
b.response :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
|
data/test/env_test.rb
CHANGED
@@ -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
|
data/test/helper.rb
CHANGED
@@ -1,14 +1,14 @@
|
|
1
|
-
|
2
|
-
require '
|
3
|
-
require '
|
4
|
-
require 'coveralls'
|
1
|
+
if RUBY_VERSION >= '1.9'
|
2
|
+
require 'simplecov'
|
3
|
+
require 'coveralls'
|
5
4
|
|
6
|
-
SimpleCov.
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
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
|
-
|
14
|
-
|
15
|
-
|
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.
|
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.
|
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).
|
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).
|
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).
|
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).
|
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.
|
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:
|
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.
|
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
|