faraday_middleware 0.8.7 → 0.8.8
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.
- data/.travis.yml +5 -4
- data/Gemfile +2 -2
- data/Rakefile +3 -4
- data/lib/faraday_middleware.rb +3 -1
- data/lib/faraday_middleware/request/encode_json.rb +4 -2
- data/lib/faraday_middleware/response/chunked.rb +29 -0
- data/lib/faraday_middleware/response/follow_redirects.rb +23 -0
- data/lib/faraday_middleware/response/mashify.rb +1 -1
- data/lib/faraday_middleware/response/parse_dates.rb +39 -0
- data/lib/faraday_middleware/response/parse_json.rb +6 -6
- data/lib/faraday_middleware/response/parse_marshal.rb +2 -2
- data/lib/faraday_middleware/response/parse_xml.rb +2 -2
- data/lib/faraday_middleware/response/parse_yaml.rb +3 -1
- data/lib/faraday_middleware/version.rb +1 -1
- data/spec/chunked_spec.rb +78 -0
- data/spec/follow_redirects_spec.rb +23 -0
- data/spec/helper.rb +2 -1
- data/spec/mashify_spec.rb +7 -0
- data/spec/parse_dates_spec.rb +42 -0
- metadata +9 -3
data/.travis.yml
CHANGED
data/Gemfile
CHANGED
data/Rakefile
CHANGED
@@ -1,6 +1,4 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
if defined? RUBY_ENGINE and 'ruby' == RUBY_ENGINE and '1.9.3' == RUBY_VERSION
|
1
|
+
if defined? RUBY_ENGINE and 'ruby' == RUBY_ENGINE and RUBY_VERSION.index('1.9') == 0
|
4
2
|
task :default => [:enable_coverage, :spec, :test, :quality]
|
5
3
|
else
|
6
4
|
task :default => [:spec, :test]
|
@@ -22,7 +20,8 @@ end
|
|
22
20
|
|
23
21
|
task :quality do
|
24
22
|
sh 'cane',
|
23
|
+
'--abc-max=10',
|
25
24
|
'--style-measure=100',
|
26
25
|
'--gte=coverage/covered_percent,99',
|
27
|
-
'--max-violations=2'
|
26
|
+
'--max-violations=2'
|
28
27
|
end
|
data/lib/faraday_middleware.rb
CHANGED
@@ -11,6 +11,7 @@ module FaradayMiddleware
|
|
11
11
|
autoload :ParseMarshal, 'faraday_middleware/response/parse_marshal'
|
12
12
|
autoload :ParseYaml, 'faraday_middleware/response/parse_yaml'
|
13
13
|
autoload :Caching, 'faraday_middleware/response/caching'
|
14
|
+
autoload :Chunked, 'faraday_middleware/response/chunked'
|
14
15
|
autoload :RackCompatible, 'faraday_middleware/rack_compatible'
|
15
16
|
autoload :FollowRedirects, 'faraday_middleware/response/follow_redirects'
|
16
17
|
autoload :Instrumentation, 'faraday_middleware/instrumentation'
|
@@ -30,7 +31,8 @@ module FaradayMiddleware
|
|
30
31
|
:marshal => lambda { ParseMarshal },
|
31
32
|
:yaml => lambda { ParseYaml },
|
32
33
|
:caching => lambda { Caching },
|
33
|
-
:follow_redirects => lambda { FollowRedirects }
|
34
|
+
:follow_redirects => lambda { FollowRedirects },
|
35
|
+
:chunked => lambda { Chunked }
|
34
36
|
|
35
37
|
Faraday.register_middleware \
|
36
38
|
:instrumentation => lambda { Instrumentation }
|
@@ -12,7 +12,9 @@ module FaradayMiddleware
|
|
12
12
|
CONTENT_TYPE = 'Content-Type'.freeze
|
13
13
|
MIME_TYPE = 'application/json'.freeze
|
14
14
|
|
15
|
-
dependency
|
15
|
+
dependency do
|
16
|
+
require 'json' unless defined?(::JSON)
|
17
|
+
end
|
16
18
|
|
17
19
|
def call(env)
|
18
20
|
match_content_type(env) do |data|
|
@@ -22,7 +24,7 @@ module FaradayMiddleware
|
|
22
24
|
end
|
23
25
|
|
24
26
|
def encode(data)
|
25
|
-
JSON.dump data
|
27
|
+
::JSON.dump data
|
26
28
|
end
|
27
29
|
|
28
30
|
def match_content_type(env)
|
@@ -0,0 +1,29 @@
|
|
1
|
+
require 'faraday_middleware/response_middleware'
|
2
|
+
|
3
|
+
module FaradayMiddleware
|
4
|
+
# Public: Parse a Transfer-Encoding: Chunked response to just the original data
|
5
|
+
class Chunked < FaradayMiddleware::ResponseMiddleware
|
6
|
+
TRANSFER_ENCODING = 'transfer-encoding'.freeze
|
7
|
+
|
8
|
+
define_parser do |raw_body|
|
9
|
+
decoded_body = []
|
10
|
+
until raw_body.empty?
|
11
|
+
chunk_len, raw_body = raw_body.split("\r\n", 2)
|
12
|
+
chunk_len = chunk_len.split(';',2).first.hex
|
13
|
+
break if chunk_len == 0
|
14
|
+
decoded_body << raw_body[0, chunk_len]
|
15
|
+
# The 2 is to strip the extra CRLF at the end of the chunk
|
16
|
+
raw_body = raw_body[chunk_len + 2, raw_body.length - chunk_len - 2]
|
17
|
+
end
|
18
|
+
decoded_body.join('')
|
19
|
+
end
|
20
|
+
|
21
|
+
def parse_response?(env)
|
22
|
+
super and chunked_encoding?(env[:response_headers])
|
23
|
+
end
|
24
|
+
|
25
|
+
def chunked_encoding?(headers)
|
26
|
+
encoding = headers[TRANSFER_ENCODING] and encoding.split(',').include?('chunked')
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -50,6 +50,9 @@ module FaradayMiddleware
|
|
50
50
|
# standards_compliant - A Boolean indicating whether to respect
|
51
51
|
# the HTTP spec when following 302
|
52
52
|
# (default: false)
|
53
|
+
# cookie - Use either an array of strings
|
54
|
+
# (e.g. ['cookie1', 'cookie2']) to choose kept cookies
|
55
|
+
# or :all to keep all cookies.
|
53
56
|
def initialize(app, options = {})
|
54
57
|
super(app)
|
55
58
|
@options = options
|
@@ -84,6 +87,7 @@ module FaradayMiddleware
|
|
84
87
|
|
85
88
|
def update_env(env, request_body, response)
|
86
89
|
env[:url] += response['location']
|
90
|
+
env[:request_headers][:cookies] = keep_cookies(env) if @options[:cookies]
|
87
91
|
|
88
92
|
if transform_into_get?(response)
|
89
93
|
env[:method] = :get
|
@@ -106,6 +110,25 @@ module FaradayMiddleware
|
|
106
110
|
@options.fetch(:limit, FOLLOW_LIMIT)
|
107
111
|
end
|
108
112
|
|
113
|
+
def keep_cookies(env)
|
114
|
+
cookies = @options.fetch(:cookies, [])
|
115
|
+
response_cookies = env[:response_headers][:cookies]
|
116
|
+
cookies == :all ? response_cookies : selected_request_cookies(response_cookies)
|
117
|
+
end
|
118
|
+
|
119
|
+
def selected_request_cookies(cookies)
|
120
|
+
selected_cookies(cookies)[0...-1]
|
121
|
+
end
|
122
|
+
|
123
|
+
def selected_cookies(cookies)
|
124
|
+
"".tap do |cookie_string|
|
125
|
+
@options[:cookies].each do |cookie|
|
126
|
+
string = /#{cookie}=?[^;]*/.match(cookies)[0] + ';'
|
127
|
+
cookie_string << string
|
128
|
+
end
|
129
|
+
end
|
130
|
+
end
|
131
|
+
|
109
132
|
def standards_compliant?
|
110
133
|
@options.fetch(:standards_compliant, false)
|
111
134
|
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
require "time"
|
2
|
+
require "faraday"
|
3
|
+
|
4
|
+
module FaradayMiddleware
|
5
|
+
# Parse dates from response body
|
6
|
+
class ParseDates < ::Faraday::Response::Middleware
|
7
|
+
ISO_DATE_FORMAT = /\A\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}Z\Z/m
|
8
|
+
|
9
|
+
def initialize(app, options = {})
|
10
|
+
@regexp = options[:match] || ISO_DATE_FORMAT
|
11
|
+
super(app)
|
12
|
+
end
|
13
|
+
|
14
|
+
def call(env)
|
15
|
+
response = @app.call(env)
|
16
|
+
parse_dates! response.env[:body]
|
17
|
+
response
|
18
|
+
end
|
19
|
+
|
20
|
+
private
|
21
|
+
|
22
|
+
def parse_dates!(value)
|
23
|
+
case value
|
24
|
+
when Hash
|
25
|
+
value.each do |key, element|
|
26
|
+
value[key] = parse_dates!(element)
|
27
|
+
end
|
28
|
+
when Array
|
29
|
+
value.each_with_index do |element, index|
|
30
|
+
value[index] = parse_dates!(element)
|
31
|
+
end
|
32
|
+
when @regexp
|
33
|
+
Time.parse(value)
|
34
|
+
else
|
35
|
+
value
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
@@ -3,13 +3,13 @@ require 'faraday_middleware/response_middleware'
|
|
3
3
|
module FaradayMiddleware
|
4
4
|
# Public: Parse response bodies as JSON.
|
5
5
|
class ParseJson < ResponseMiddleware
|
6
|
-
dependency
|
7
|
-
require 'json' unless defined?(JSON)
|
8
|
-
|
6
|
+
dependency do
|
7
|
+
require 'json' unless defined?(::JSON)
|
8
|
+
end
|
9
9
|
|
10
|
-
define_parser
|
11
|
-
JSON.parse body unless body.strip.empty?
|
12
|
-
|
10
|
+
define_parser do |body|
|
11
|
+
::JSON.parse body unless body.strip.empty?
|
12
|
+
end
|
13
13
|
|
14
14
|
# Public: Override the content-type of the response with "application/json"
|
15
15
|
# if the response body looks like it might be JSON, i.e. starts with an
|
@@ -3,9 +3,9 @@ require 'faraday_middleware/response_middleware'
|
|
3
3
|
module FaradayMiddleware
|
4
4
|
# Public: Restore marshalled Ruby objects in response bodies.
|
5
5
|
class ParseMarshal < ResponseMiddleware
|
6
|
-
define_parser
|
6
|
+
define_parser do |body|
|
7
7
|
::Marshal.load body unless body.empty?
|
8
|
-
|
8
|
+
end
|
9
9
|
end
|
10
10
|
end
|
11
11
|
|
@@ -0,0 +1,78 @@
|
|
1
|
+
require 'helper'
|
2
|
+
require 'faraday_middleware/response/chunked'
|
3
|
+
|
4
|
+
describe FaradayMiddleware::Chunked, :type => :response do
|
5
|
+
context "no transfer-encoding" do
|
6
|
+
it "doesn't change nil body" do
|
7
|
+
process(nil).body.should be_nil
|
8
|
+
end
|
9
|
+
|
10
|
+
it "doesn't change an empty body" do
|
11
|
+
process('').body.should eql('')
|
12
|
+
end
|
13
|
+
|
14
|
+
it "doesn't change a normal body" do
|
15
|
+
process('asdf').body.should eql('asdf')
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
context "transfer-encoding gzip" do
|
20
|
+
let(:headers) { {"transfer-encoding" => "gzip"}}
|
21
|
+
|
22
|
+
it "doesn't change nil body" do
|
23
|
+
process(nil).body.should be_nil
|
24
|
+
end
|
25
|
+
|
26
|
+
it "doesn't change an empty body" do
|
27
|
+
process('').body.should eql('')
|
28
|
+
end
|
29
|
+
|
30
|
+
it "doesn't change a normal body" do
|
31
|
+
process('asdf').body.should eql('asdf')
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
context "transfer-encoding chunked" do
|
36
|
+
let(:headers) { {"transfer-encoding" => "chunked"}}
|
37
|
+
|
38
|
+
it "doesn't change nil body" do
|
39
|
+
process(nil).body.should be_nil
|
40
|
+
end
|
41
|
+
|
42
|
+
it "doesn't change an empty body" do
|
43
|
+
process('').body.should eql('')
|
44
|
+
end
|
45
|
+
|
46
|
+
it "parses a basic chunked body" do
|
47
|
+
process("10\r\nasdfghjklasdfghj\r\n0\r\n").body.should eql('asdfghjklasdfghj')
|
48
|
+
end
|
49
|
+
|
50
|
+
it "parses a chunked body with no ending chunk" do
|
51
|
+
process("10\r\nasdfghjklasdfghj\r\n").body.should eql('asdfghjklasdfghj')
|
52
|
+
end
|
53
|
+
|
54
|
+
it "parses a chunked body with no trailing CRLF on the data chunk" do
|
55
|
+
process("10\r\nasdfghjklasdfghj0\r\n").body.should eql('asdfghjklasdfghj')
|
56
|
+
end
|
57
|
+
|
58
|
+
it "parses a chunked body with an extension" do
|
59
|
+
process("10;foo=bar\r\nasdfghjklasdfghj\r\n0\r\n").body.should eql('asdfghjklasdfghj')
|
60
|
+
end
|
61
|
+
|
62
|
+
it "parses a chunked body with two extensions" do
|
63
|
+
process("10;foo=bar;bar=baz\r\nasdfghjklasdfghj\r\n0\r\n").body.should eql('asdfghjklasdfghj')
|
64
|
+
end
|
65
|
+
|
66
|
+
it "parses a chunked body with two chunks" do
|
67
|
+
process("8\r\nasdfghjk\r\n8\r\nlasdfghj\r\n0\r\n").body.should eql('asdfghjklasdfghj')
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
context "transfer-encoding chunked,chunked" do
|
72
|
+
let(:headers) { {"transfer-encoding" => "chunked,chunked"}}
|
73
|
+
|
74
|
+
it "parses a basic chunked body" do
|
75
|
+
process("10\r\nasdfghjklasdfghj\r\n0\r\n").body.should eql('asdfghjklasdfghj')
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
@@ -130,6 +130,29 @@ describe FaradayMiddleware::FollowRedirects do
|
|
130
130
|
expect { conn.get('/') }.to raise_error(FaradayMiddleware::RedirectLimitReached)
|
131
131
|
end
|
132
132
|
|
133
|
+
context 'when cookies option' do
|
134
|
+
|
135
|
+
let(:cookies) { 'cookie1=abcdefg; cookie2=1234567; cookie3=awesome' }
|
136
|
+
|
137
|
+
context "is :all" do
|
138
|
+
it "puts all cookies from the response into the next request" do
|
139
|
+
conn = connection(:cookies => :all) do |stub|
|
140
|
+
stub.get('/') { [301, {'Location' => '/found', 'Cookies' => cookies }, ''] }
|
141
|
+
stub.get('/found') { [200, {'Content-Type' => 'text/plain'}, ''] }
|
142
|
+
end.get('/').env[:request_headers][:cookies].should == cookies
|
143
|
+
end
|
144
|
+
end
|
145
|
+
|
146
|
+
context "is an array of cookie names" do
|
147
|
+
it "puts selected cookies from the response into the next request" do
|
148
|
+
conn = connection(:cookies => ['cookie2']) do |stub|
|
149
|
+
stub.get('/') { [301, {'Location' => '/found', 'Cookies' => cookies }, ''] }
|
150
|
+
stub.get('/found') { [200, {'Content-Type' => 'text/plain'}, ''] }
|
151
|
+
end.get('/').env[:request_headers][:cookies].should == 'cookie2=1234567'
|
152
|
+
end
|
153
|
+
end
|
154
|
+
end
|
155
|
+
|
133
156
|
context 'for an HTTP 301 response' do
|
134
157
|
it_should_behave_like 'a successful redirection', 301
|
135
158
|
it_should_behave_like 'a forced GET redirection', 301
|
data/spec/helper.rb
CHANGED
@@ -21,6 +21,7 @@ require 'rspec'
|
|
21
21
|
module ResponseMiddlewareExampleGroup
|
22
22
|
def self.included(base)
|
23
23
|
base.let(:options) { Hash.new }
|
24
|
+
base.let(:headers) { Hash.new }
|
24
25
|
base.let(:middleware) {
|
25
26
|
described_class.new(lambda {|env|
|
26
27
|
Faraday::Response.new(env)
|
@@ -31,7 +32,7 @@ module ResponseMiddlewareExampleGroup
|
|
31
32
|
def process(body, content_type = nil, options = {})
|
32
33
|
env = {
|
33
34
|
:body => body, :request => options,
|
34
|
-
:response_headers => Faraday::Utils::Headers.new
|
35
|
+
:response_headers => Faraday::Utils::Headers.new(headers)
|
35
36
|
}
|
36
37
|
env[:response_headers]['content-type'] = content_type if content_type
|
37
38
|
middleware.call(env)
|
data/spec/mashify_spec.rb
CHANGED
@@ -39,6 +39,13 @@ describe FaradayMiddleware::Mashify do
|
|
39
39
|
us.last.username.should == 'pengwynn'
|
40
40
|
end
|
41
41
|
|
42
|
+
it 'should handle nested arrays of hashes' do
|
43
|
+
env = { :body => [[{ "username" => "sferik" }, { "username" => "pengwynn" }]] }
|
44
|
+
us = mashify.on_complete(env)
|
45
|
+
us.first.first.username.should == 'sferik'
|
46
|
+
us.first.last.username.should == 'pengwynn'
|
47
|
+
end
|
48
|
+
|
42
49
|
it 'should handle mixed arrays' do
|
43
50
|
env = { :body => [123, { "username" => "sferik" }, 456] }
|
44
51
|
values = mashify.on_complete(env)
|
@@ -0,0 +1,42 @@
|
|
1
|
+
require 'helper'
|
2
|
+
require 'faraday_middleware/response/parse_dates'
|
3
|
+
require 'json'
|
4
|
+
|
5
|
+
describe FaradayMiddleware::ParseDates, :type => :response do
|
6
|
+
let(:parsed){
|
7
|
+
if RUBY_VERSION > "1.9"
|
8
|
+
"2012-02-01 13:14:15 UTC"
|
9
|
+
else
|
10
|
+
"Wed Feb 01 13:14:15 UTC 2012"
|
11
|
+
end
|
12
|
+
}
|
13
|
+
|
14
|
+
it "should parse dates" do
|
15
|
+
process({"x" => "2012-02-01T13:14:15Z"}).body["x"].to_s.should == parsed
|
16
|
+
end
|
17
|
+
|
18
|
+
it "should parse nested dates in hash" do
|
19
|
+
process({"x" => {"y" => "2012-02-01T13:14:15Z"}}).body["x"]["y"].to_s.should == parsed
|
20
|
+
end
|
21
|
+
|
22
|
+
it "should parse nested dates in arrays" do
|
23
|
+
process({"x" => [{"y" =>"2012-02-01T13:14:15Z"}]}).body["x"][0]["y"].to_s.should == parsed
|
24
|
+
end
|
25
|
+
|
26
|
+
it "should not blow up on empty body" do
|
27
|
+
process(nil).body.should == nil
|
28
|
+
end
|
29
|
+
|
30
|
+
it "should leave arrays with ids alone" do
|
31
|
+
process({"x" => [1,2,3]}).body.should == {"x" => [1,2,3]}
|
32
|
+
end
|
33
|
+
|
34
|
+
it "should not parse date-like things" do
|
35
|
+
process({"x" => "2012-02-01T13:14:15Z bla"}).body["x"].to_s.should ==
|
36
|
+
"2012-02-01T13:14:15Z bla"
|
37
|
+
process({"x" => "12012-02-01T13:14:15Z"}).body["x"].to_s.should ==
|
38
|
+
"12012-02-01T13:14:15Z"
|
39
|
+
process({"x" => "2012-02-01T13:14:15Z\nfoo"}).body["x"].to_s.should ==
|
40
|
+
"2012-02-01T13:14:15Z\nfoo"
|
41
|
+
end
|
42
|
+
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: faraday_middleware
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.8.
|
4
|
+
version: 0.8.8
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -10,7 +10,7 @@ authors:
|
|
10
10
|
autorequire:
|
11
11
|
bindir: bin
|
12
12
|
cert_chain: []
|
13
|
-
date: 2012-
|
13
|
+
date: 2012-06-24 00:00:00.000000000 Z
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
16
16
|
name: faraday
|
@@ -173,8 +173,10 @@ files:
|
|
173
173
|
- lib/faraday_middleware/request/oauth.rb
|
174
174
|
- lib/faraday_middleware/request/oauth2.rb
|
175
175
|
- lib/faraday_middleware/response/caching.rb
|
176
|
+
- lib/faraday_middleware/response/chunked.rb
|
176
177
|
- lib/faraday_middleware/response/follow_redirects.rb
|
177
178
|
- lib/faraday_middleware/response/mashify.rb
|
179
|
+
- lib/faraday_middleware/response/parse_dates.rb
|
178
180
|
- lib/faraday_middleware/response/parse_json.rb
|
179
181
|
- lib/faraday_middleware/response/parse_marshal.rb
|
180
182
|
- lib/faraday_middleware/response/parse_xml.rb
|
@@ -183,12 +185,14 @@ files:
|
|
183
185
|
- lib/faraday_middleware/response_middleware.rb
|
184
186
|
- lib/faraday_middleware/version.rb
|
185
187
|
- spec/caching_test.rb
|
188
|
+
- spec/chunked_spec.rb
|
186
189
|
- spec/encode_json_spec.rb
|
187
190
|
- spec/follow_redirects_spec.rb
|
188
191
|
- spec/helper.rb
|
189
192
|
- spec/mashify_spec.rb
|
190
193
|
- spec/oauth2_spec.rb
|
191
194
|
- spec/oauth_spec.rb
|
195
|
+
- spec/parse_dates_spec.rb
|
192
196
|
- spec/parse_json_spec.rb
|
193
197
|
- spec/parse_marshal_spec.rb
|
194
198
|
- spec/parse_xml_spec.rb
|
@@ -214,18 +218,20 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
214
218
|
version: 1.3.6
|
215
219
|
requirements: []
|
216
220
|
rubyforge_project:
|
217
|
-
rubygems_version: 1.8.
|
221
|
+
rubygems_version: 1.8.23
|
218
222
|
signing_key:
|
219
223
|
specification_version: 3
|
220
224
|
summary: Various middleware for Faraday
|
221
225
|
test_files:
|
222
226
|
- spec/caching_test.rb
|
227
|
+
- spec/chunked_spec.rb
|
223
228
|
- spec/encode_json_spec.rb
|
224
229
|
- spec/follow_redirects_spec.rb
|
225
230
|
- spec/helper.rb
|
226
231
|
- spec/mashify_spec.rb
|
227
232
|
- spec/oauth2_spec.rb
|
228
233
|
- spec/oauth_spec.rb
|
234
|
+
- spec/parse_dates_spec.rb
|
229
235
|
- spec/parse_json_spec.rb
|
230
236
|
- spec/parse_marshal_spec.rb
|
231
237
|
- spec/parse_xml_spec.rb
|