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.
@@ -1,9 +1,10 @@
1
1
  language: ruby
2
2
  rvm:
3
+ - rbx-18mode
4
+ - rbx-19mode
5
+ - jruby-18mode
6
+ - jruby-19mode
3
7
  - 1.8.7
4
8
  - 1.9.2
5
9
  - 1.9.3
6
- - jruby-18mode
7
- - jruby-19mode
8
- - rbx-18mode
9
- - rbx-19mode
10
+ - ruby-head
data/Gemfile CHANGED
@@ -1,8 +1,8 @@
1
1
  source 'http://rubygems.org'
2
2
 
3
- platforms :ruby_19 do
3
+ platforms :mri_19 do
4
4
  gem 'simplecov'
5
- gem 'cane'
5
+ gem 'cane', '>= 0.3'
6
6
  end
7
7
 
8
8
  gem 'json', :platforms => [:ruby_18, :jruby]
data/Rakefile CHANGED
@@ -1,6 +1,4 @@
1
- #!/usr/bin/env rake
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' # TODO: remove for cane > 1.0.0
26
+ '--max-violations=2'
28
27
  end
@@ -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 'json'
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
@@ -25,7 +25,7 @@ module FaradayMiddleware
25
25
  when Hash
26
26
  mash_class.new(body)
27
27
  when Array
28
- body.map { |item| item.is_a?(Hash) ? mash_class.new(item) : item }
28
+ body.map { |item| parse(item) }
29
29
  else
30
30
  body
31
31
  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 { |body|
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 { |body|
6
+ define_parser do |body|
7
7
  ::Marshal.load body unless body.empty?
8
- }
8
+ end
9
9
  end
10
10
  end
11
11
 
@@ -5,9 +5,9 @@ module FaradayMiddleware
5
5
  class ParseXml < ResponseMiddleware
6
6
  dependency 'multi_xml'
7
7
 
8
- define_parser { |body|
8
+ define_parser do |body|
9
9
  ::MultiXml.parse(body)
10
- }
10
+ end
11
11
  end
12
12
  end
13
13
 
@@ -5,7 +5,9 @@ module FaradayMiddleware
5
5
  class ParseYaml < ResponseMiddleware
6
6
  dependency 'yaml'
7
7
 
8
- define_parser { |body| ::YAML.load body }
8
+ define_parser do |body|
9
+ ::YAML.load body
10
+ end
9
11
  end
10
12
  end
11
13
 
@@ -1,3 +1,3 @@
1
1
  module FaradayMiddleware
2
- VERSION = "0.8.7"
2
+ VERSION = "0.8.8"
3
3
  end
@@ -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
@@ -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)
@@ -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.7
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-04-18 00:00:00.000000000 Z
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.22
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