faraday_middleware 0.8.7 → 0.8.8

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