faraday_middleware 0.8.4 → 0.8.5

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/Gemfile CHANGED
@@ -1,6 +1,10 @@
1
1
  source 'http://rubygems.org'
2
2
 
3
- gem 'simplecov' unless ENV['CI']
3
+ platforms :ruby_19 do
4
+ gem 'simplecov'
5
+ gem 'cane'
6
+ end
7
+
4
8
  gem 'json', :platforms => [:ruby_18, :jruby]
5
9
  gem 'jruby-openssl', '~> 0.7', :platforms => :jruby
6
10
 
data/Rakefile CHANGED
@@ -1,6 +1,10 @@
1
1
  #!/usr/bin/env rake
2
2
 
3
- task :default => [:enable_coverage, :spec, :test]
3
+ if defined? RUBY_ENGINE and 'ruby' == RUBY_ENGINE and '1.9.3' == RUBY_VERSION
4
+ task :default => [:enable_coverage, :spec, :test, :quality]
5
+ else
6
+ task :default => [:spec, :test]
7
+ end
4
8
 
5
9
  require 'bundler'
6
10
  Bundler::GemHelper.install_tasks
@@ -9,9 +13,16 @@ require 'rspec/core/rake_task'
9
13
  RSpec::Core::RakeTask.new(:spec)
10
14
 
11
15
  task :enable_coverage do
12
- ENV['COVERAGE'] = 'yes' unless ENV['CI']
16
+ ENV['COVERAGE'] = 'yes'
13
17
  end
14
18
 
15
19
  task :test do
16
20
  sh 'ruby', '-Ilib', 'spec/caching_test.rb'
17
21
  end
22
+
23
+ task :quality do
24
+ sh 'cane',
25
+ '--style-measure=100',
26
+ '--gte=coverage/covered_percent,99',
27
+ '--max-violations=2' # TODO: remove for cane > 1.0.0
28
+ end
@@ -7,10 +7,10 @@ module FaradayMiddleware
7
7
  #
8
8
  # Examples
9
9
  #
10
- # ActiveSupport::Notifications.subscribe('request.faraday') do |name, start_time, end_time, _, env|
10
+ # ActiveSupport::Notifications.subscribe('request.faraday') do |name, starts, ends, _, env|
11
11
  # url = env[:url]
12
12
  # http_method = env[:method].to_s.upcase
13
- # duration = end_time - start_time
13
+ # duration = ends - starts
14
14
  # $stderr.puts '[%s] %s %s (%.3f s)' % [url.host, http_method, url.request_uri, duration]
15
15
  # end
16
16
  class Instrumentation < Faraday::Middleware
@@ -26,11 +26,7 @@ module FaradayMiddleware
26
26
 
27
27
  # faraday to rack-compatible
28
28
  def prepare_env(env)
29
- env[:request_headers].each do |name, value|
30
- name = name.upcase.tr('-', '_')
31
- name = "HTTP_#{name}" unless NonPrefixedHeaders.include? name
32
- env[name] = value
33
- end
29
+ headers_to_rack(env)
34
30
 
35
31
  url = env[:url]
36
32
  env['rack.url_scheme'] = url.scheme
@@ -44,6 +40,14 @@ module FaradayMiddleware
44
40
  env
45
41
  end
46
42
 
43
+ def headers_to_rack(env)
44
+ env[:request_headers].each do |name, value|
45
+ name = name.upcase.tr('-', '_')
46
+ name = "HTTP_#{name}" unless NonPrefixedHeaders.include? name
47
+ env[name] = value
48
+ end
49
+ end
50
+
47
51
  # rack to faraday-compatible
48
52
  def restore_env(env)
49
53
  headers = env[:request_headers]
@@ -1,4 +1,5 @@
1
1
  require 'faraday'
2
+ require 'forwardable'
2
3
 
3
4
  module FaradayMiddleware
4
5
  # Public: Uses the simple_oauth library to sign requests according the
@@ -11,14 +12,25 @@ module FaradayMiddleware
11
12
  # The signature is added to the "Authorization" HTTP request header. If the
12
13
  # value for this header already exists, it is not overriden.
13
14
  #
14
- # For requests that have parameters in the body, such as POST, this
15
- # middleware expects them to be in Hash form, i.e. not encoded to string.
16
- # This means this middleware has to be positioned on the stack before any
17
- # encoding middleware such as UrlEncoded.
15
+ # If no Content-Type header is specified, this middleware assumes that
16
+ # request body parameters should be included while signing the request.
17
+ # Otherwise, it only includes them if the Content-Type is
18
+ # "application/x-www-form-urlencoded", as per OAuth 1.0.
19
+ #
20
+ # For better performance while signing requests, this middleware should be
21
+ # positioned before UrlEncoded middleware on the stack, but after any other
22
+ # body-encoding middleware (such as EncodeJson).
18
23
  class OAuth < Faraday::Middleware
19
24
  dependency 'simple_oauth'
20
25
 
21
26
  AUTH_HEADER = 'Authorization'.freeze
27
+ CONTENT_TYPE = 'Content-Type'.freeze
28
+ TYPE_URLENCODED = 'application/x-www-form-urlencoded'.freeze
29
+
30
+ extend Forwardable
31
+ parser_method = :parse_nested_query
32
+ parser_module = ::Faraday::Utils.respond_to?(parser_method) ? 'Faraday::Utils' : 'Rack::Utils'
33
+ def_delegator parser_module, parser_method
22
34
 
23
35
  def initialize(app, options)
24
36
  super(app)
@@ -50,7 +62,18 @@ module FaradayMiddleware
50
62
  end
51
63
 
52
64
  def body_params(env)
53
- env[:body] || {}
65
+ if include_body_params?(env)
66
+ if env[:body].respond_to?(:to_str)
67
+ parse_nested_query env[:body]
68
+ else
69
+ env[:body]
70
+ end
71
+ end || {}
72
+ end
73
+
74
+ def include_body_params?(env)
75
+ # see RFC 5489, section 3.4.1.3.1 for details
76
+ !(type = env[:request_headers][CONTENT_TYPE]) or type == TYPE_URLENCODED
54
77
  end
55
78
 
56
79
  def signature_params(params)
@@ -1,6 +1,8 @@
1
1
  require 'faraday'
2
+ require 'set'
2
3
 
3
4
  module FaradayMiddleware
5
+ # Public: Exception thrown when the maximum amount of requests is exceeded.
4
6
  class RedirectLimitReached < Faraday::Error::ClientError
5
7
  attr_reader :response
6
8
 
@@ -10,10 +12,34 @@ module FaradayMiddleware
10
12
  end
11
13
  end
12
14
 
13
- # Public: Follow HTTP 30x redirects.
15
+ # Public: Follow HTTP 301, 302, 303, and 307 redirects for GET, PATCH, POST,
16
+ # PUT, and DELETE requests.
17
+ #
18
+ # This middleware does not follow the HTTP specification for HTTP 302, by
19
+ # default, in that it follows the improper implementation used by most major
20
+ # web browsers which forces the redirected request to become a GET request
21
+ # regardless of the original request method.
22
+ #
23
+ # For HTTP 301, 302, and 303, the original request is transformed into a
24
+ # GET request to the response Location, by default. However, with standards
25
+ # compliance enabled, a 302 will instead act in accordance with the HTTP
26
+ # specification, which will replay the original request to the received
27
+ # Location, just as with a 307.
28
+ #
29
+ # For HTTP 307, the original request is replayed to the response Location,
30
+ # including original HTTP request method (GET, POST, PUT, DELETE, PATCH),
31
+ # original headers, and original body.
32
+ #
33
+ # This middleware currently only works with synchronous requests; in other
34
+ # words, it doesn't support parallelism.
14
35
  class FollowRedirects < Faraday::Middleware
15
- # TODO: 307 & standards-compliant 302
16
- REDIRECTS = [301, 302, 303]
36
+ # HTTP methods for which 30x redirects can be followed
37
+ ALLOWED_METHODS = Set.new [:get, :post, :put, :patch, :delete]
38
+ # HTTP redirect status codes that this middleware implements
39
+ REDIRECT_CODES = Set.new [301, 302, 303, 307]
40
+ # Keys in env hash which will get cleared between requests
41
+ ENV_TO_CLEAR = Set.new [:status, :response, :response_headers]
42
+
17
43
  # Default value for max redirects followed
18
44
  FOLLOW_LIMIT = 3
19
45
 
@@ -21,33 +47,67 @@ module FaradayMiddleware
21
47
  #
22
48
  # options - An options Hash (default: {}):
23
49
  # limit - A Numeric redirect limit (default: 3)
50
+ # standards_compliant - A Boolean indicating whether to respect
51
+ # the HTTP spec when following 302
52
+ # (default: false)
24
53
  def initialize(app, options = {})
25
54
  super(app)
26
55
  @options = options
56
+
57
+ @replay_request_codes = Set.new [307]
58
+ @replay_request_codes << 302 if standards_compliant?
27
59
  end
28
60
 
29
61
  def call(env)
30
- process_response(@app.call(env), follow_limit)
62
+ perform_with_redirection(env, follow_limit)
31
63
  end
32
64
 
33
- def process_response(response, follows)
65
+ private
66
+
67
+ def transform_into_get?(response)
68
+ !@replay_request_codes.include? response.status
69
+ end
70
+
71
+ def perform_with_redirection(env, follows)
72
+ request_body = env[:body]
73
+ response = @app.call(env)
74
+
34
75
  response.on_complete do |env|
35
- if redirect? response
76
+ if follow_redirect?(env, response)
36
77
  raise RedirectLimitReached, response if follows.zero?
37
- env[:url] += response['location']
38
- env[:method] = :get
39
- response = process_response(@app.call(env), follows - 1)
78
+ env = update_env(env, request_body, response)
79
+ response = perform_with_redirection(env, follows - 1)
40
80
  end
41
81
  end
42
82
  response
43
83
  end
44
84
 
45
- def redirect?(response)
46
- REDIRECTS.include? response.status
85
+ def update_env(env, request_body, response)
86
+ env[:url] += response['location']
87
+
88
+ if transform_into_get?(response)
89
+ env[:method] = :get
90
+ env[:body] = nil
91
+ else
92
+ env[:body] = request_body
93
+ end
94
+
95
+ ENV_TO_CLEAR.each {|key| env.delete key }
96
+
97
+ env
98
+ end
99
+
100
+ def follow_redirect?(env, response)
101
+ ALLOWED_METHODS.include? env[:method] and
102
+ REDIRECT_CODES.include? response.status
47
103
  end
48
104
 
49
105
  def follow_limit
50
106
  @options.fetch(:limit, FOLLOW_LIMIT)
51
107
  end
108
+
109
+ def standards_compliant?
110
+ @options.fetch(:standards_compliant, false)
111
+ end
52
112
  end
53
113
  end
@@ -1,6 +1,8 @@
1
1
  require 'faraday'
2
2
 
3
3
  module FaradayMiddleware
4
+ # Public: Converts parsed response bodies to a Hashie::Mash if they were of
5
+ # Hash or Array type.
4
6
  class Mashify < Faraday::Response::Middleware
5
7
  class << self
6
8
  attr_accessor :mash_class
@@ -26,9 +26,19 @@ module FaradayMiddleware
26
26
  end
27
27
 
28
28
  BRACKETS = %w- [ { -
29
+ WHITESPACE = [ " ", "\n", "\r", "\t" ]
29
30
 
30
31
  def parse_response?(env)
31
- super and BRACKETS.include? env[:body][0,1]
32
+ super and BRACKETS.include? first_char(env[:body])
33
+ end
34
+
35
+ def first_char(body)
36
+ idx = -1
37
+ begin
38
+ char = body[idx += 1]
39
+ char = char.chr if char
40
+ end while char and WHITESPACE.include? char
41
+ char
32
42
  end
33
43
  end
34
44
  end
@@ -1,6 +1,7 @@
1
1
  require 'faraday_middleware/response_middleware'
2
2
 
3
3
  module FaradayMiddleware
4
+ # Public: parses response bodies with MultiXml.
4
5
  class ParseXml < ResponseMiddleware
5
6
  dependency 'multi_xml'
6
7
 
@@ -1,6 +1,8 @@
1
1
  require 'faraday_middleware/response/mashify'
2
2
 
3
3
  module FaradayMiddleware
4
+ # Public: Converts parsed response bodies to a Hashie::Rash if they were of
5
+ # Hash or Array type.
4
6
  class Rashify < Mashify
5
7
  dependency do
6
8
  require 'rash'
@@ -1,3 +1,3 @@
1
1
  module FaradayMiddleware
2
- VERSION = "0.8.4"
2
+ VERSION = "0.8.5"
3
3
  end
@@ -1,33 +1,182 @@
1
1
  require 'helper'
2
2
  require 'faraday_middleware/response/follow_redirects'
3
3
  require 'faraday'
4
- require 'forwardable'
4
+
5
+ # expose a method in Test adapter that should have been public
6
+ Faraday::Adapter::Test::Stubs.class_eval { public :new_stub }
5
7
 
6
8
  describe FaradayMiddleware::FollowRedirects do
7
- let(:connection) {
8
- Faraday.new do |c|
9
- c.use described_class
10
- c.adapter :test do |stub|
11
- stub.get('/') { [301, {'Location' => '/found'}, ''] }
12
- stub.post('/create') { [302, {'Location' => '/'}, ''] }
13
- stub.get('/found') { [200, {'Content-Type' => 'text/plain'}, 'fin'] }
14
- stub.get('/loop') { [302, {'Location' => '/loop'}, ''] }
9
+ let(:middleware_options) { Hash.new }
10
+
11
+ shared_examples_for 'a successful redirection' do |status_code|
12
+ it "follows the redirection for a GET request" do
13
+ connection do |stub|
14
+ stub.get('/permanent') { [status_code, {'Location' => '/found'}, ''] }
15
+ stub.get('/found') { [200, {'Content-Type' => 'text/plain'}, 'fin'] }
16
+ end.get('/permanent').body.should eql 'fin'
17
+ end
18
+
19
+ [:head, :options].each do |method|
20
+ it "returning the response headers for a #{method.to_s.upcase} request" do
21
+ connection do |stub|
22
+ stub.new_stub(method, '/permanent') { [status_code, {'Location' => '/found'}, ''] }
23
+ end.run_request(method, '/permanent', nil, nil).headers['Location'].should eql('/found')
24
+ end
25
+ end
26
+ end
27
+
28
+ shared_examples_for 'a forced GET redirection' do |status_code|
29
+ [:put, :post, :delete, :patch].each do |method|
30
+ it "a #{method.to_s.upcase} request is converted to a GET" do
31
+ connection = connection do |stub|
32
+ stub.new_stub(method, '/redirect') {
33
+ [status_code, {'Location' => '/found'}, 'elsewhere']
34
+ }
35
+ stub.get('/found') { |env|
36
+ body = env[:body] and body.empty? && (body = nil)
37
+ [200, {'Content-Type' => 'text/plain'}, body.inspect]
38
+ }
39
+ end.run_request(method, '/redirect', 'request data', nil).body.should eql('nil')
40
+ end
41
+ end
42
+ end
43
+
44
+ shared_examples_for 'a replayed redirection' do |status_code|
45
+ it 'redirects with the original request headers' do
46
+ conn = connection do |stub|
47
+ stub.get('/redirect') {
48
+ [status_code, {'Location' => '/found'}, '']
49
+ }
50
+ stub.get('/found') { |env|
51
+ [200, {'Content-Type' => 'text/plain'}, env[:request_headers]['X-Test-Value']]
52
+ }
53
+ end
54
+
55
+ response = conn.get('/redirect') { |req|
56
+ req.headers['X-Test-Value'] = 'success'
57
+ }
58
+
59
+ response.body.should eql('success')
60
+ end
61
+
62
+ [:put, :post, :delete, :patch].each do |method|
63
+ it "replays a #{method.to_s.upcase} request" do
64
+ connection do |stub|
65
+ stub.new_stub(method, '/redirect') { [status_code, {'Location' => '/found'}, ''] }
66
+ stub.new_stub(method, '/found') { [200, {'Content-Type' => 'text/plain'}, 'fin'] }
67
+ end.run_request(method, '/redirect', nil, nil).body.should eql 'fin'
68
+ end
69
+ end
70
+
71
+ [:put, :post, :patch].each do |method|
72
+ it "forwards request body for a #{method.to_s.upcase} request" do
73
+ conn = connection do |stub|
74
+ stub.new_stub(method, '/redirect') {
75
+ [status_code, {'Location' => '/found'}, '']
76
+ }
77
+ stub.new_stub(method, '/found') { |env|
78
+ [200, {'Content-Type' => 'text/plain'}, env[:body]]
79
+ }
80
+ end
81
+
82
+ response = conn.run_request(method, '/redirect', 'original data', nil)
83
+ response.body.should eql('original data')
15
84
  end
16
85
  end
17
- }
86
+ end
18
87
 
19
- extend Forwardable
20
- def_delegators :connection, :get, :post
21
88
 
22
- it "follows redirect" do
23
- get('/').body.should eql('fin')
89
+ it "returns non-redirect response results" do
90
+ connection do |stub|
91
+ stub.get('/found') { [200, {'Content-Type' => 'text/plain'}, 'fin'] }
92
+ end.get('/found').body.should eql 'fin'
24
93
  end
25
94
 
26
- it "follows redirect twice" do
27
- post('/create').body.should eql('fin')
95
+ it "follows a single redirection" do
96
+ connection do |stub|
97
+ stub.get('/') { [301, {'Location' => '/found'}, ''] }
98
+ stub.get('/found') { [200, {'Content-Type' => 'text/plain'}, 'fin'] }
99
+ end.get('/').body.should eql 'fin'
28
100
  end
29
101
 
30
- it "raises exception on loop" do
31
- expect { get('/loop') }.to raise_error(FaradayMiddleware::RedirectLimitReached)
102
+ it "follows many redirections" do
103
+ connection do |stub|
104
+ stub.get('/') { [301, {'Location' => '/redirect1'}, ''] }
105
+ stub.get('/redirect1') { [301, {'Location' => '/redirect2'}, ''] }
106
+ stub.get('/redirect2') { [301, {'Location' => '/found'}, ''] }
107
+ stub.get('/found') { [200, {'Content-Type' => 'text/plain'}, 'fin'] }
108
+ end.get('/').body.should eql 'fin'
109
+ end
110
+
111
+ it "raises a FaradayMiddleware::RedirectLimitReached after 3 redirections (by default)" do
112
+ conn = connection do |stub|
113
+ stub.get('/') { [301, {'Location' => '/redirect1'}, ''] }
114
+ stub.get('/redirect1') { [301, {'Location' => '/redirect2'}, ''] }
115
+ stub.get('/redirect2') { [301, {'Location' => '/redirect3'}, ''] }
116
+ stub.get('/redirect3') { [301, {'Location' => '/found'}, ''] }
117
+ stub.get('/found') { [200, {'Content-Type' => 'text/plain'}, 'fin'] }
118
+ end
119
+
120
+ expect { conn.get('/') }.to raise_error(FaradayMiddleware::RedirectLimitReached)
121
+ end
122
+
123
+ it "raises a FaradayMiddleware::RedirectLimitReached after the initialized limit" do
124
+ conn = connection(:limit => 1) do |stub|
125
+ stub.get('/') { [301, {'Location' => '/redirect1'}, ''] }
126
+ stub.get('/redirect1') { [301, {'Location' => '/found'}, ''] }
127
+ stub.get('/found') { [200, {'Content-Type' => 'text/plain'}, 'fin'] }
128
+ end
129
+
130
+ expect { conn.get('/') }.to raise_error(FaradayMiddleware::RedirectLimitReached)
131
+ end
132
+
133
+ context 'for an HTTP 301 response' do
134
+ it_should_behave_like 'a successful redirection', 301
135
+ it_should_behave_like 'a forced GET redirection', 301
136
+ end
137
+
138
+ context 'for an HTTP 302 response' do
139
+ it_should_behave_like 'a successful redirection', 302
140
+
141
+ context 'by default' do
142
+ it_should_behave_like 'a forced GET redirection', 302
143
+ end
144
+
145
+ context 'with standards compliancy enabled' do
146
+ let(:middleware_options) { { :standards_compliant => true } }
147
+ it_should_behave_like 'a replayed redirection', 302
148
+ end
149
+ end
150
+
151
+ context 'for an HTTP 303 response' do
152
+ it_should_behave_like 'a successful redirection', 303
153
+ it_should_behave_like 'a forced GET redirection', 303
154
+ end
155
+
156
+ context 'for an HTTP 307 response' do
157
+ it_should_behave_like 'a successful redirection', 307
158
+ it_should_behave_like 'a replayed redirection', 307
159
+ end
160
+
161
+ # checks env hash in request phase for basic validity
162
+ class Lint < Struct.new(:app)
163
+ def call(env)
164
+ if env[:status] or env[:response] or env[:response_headers]
165
+ raise "invalid request: #{env.inspect}"
166
+ end
167
+ app.call(env)
168
+ end
169
+ end
170
+
171
+ private
172
+
173
+ def connection(options = middleware_options)
174
+ Faraday.new do |c|
175
+ c.use described_class, options
176
+ c.use Lint
177
+ c.adapter :test do |stub|
178
+ yield(stub) if block_given?
179
+ end
180
+ end
32
181
  end
33
182
  end
data/spec/helper.rb CHANGED
@@ -1,5 +1,16 @@
1
1
  if ENV['COVERAGE']
2
2
  require 'simplecov'
3
+
4
+ class SimpleCov::Formatter::QualityFormatter
5
+ def format(result)
6
+ SimpleCov::Formatter::HTMLFormatter.new.format(result)
7
+ File.open('coverage/covered_percent', 'w') do |f|
8
+ f.puts result.source_files.covered_percent.to_i
9
+ end
10
+ end
11
+ end
12
+ SimpleCov.formatter = SimpleCov::Formatter::QualityFormatter
13
+
3
14
  SimpleCov.start do
4
15
  # add_filter 'faraday_middleware.rb'
5
16
  add_filter 'backwards_compatibility.rb'
data/spec/mashify_spec.rb CHANGED
@@ -70,7 +70,10 @@ describe FaradayMiddleware::Mashify do
70
70
  # although it is not good practice to pass a hash as the body, if we add ParseJson
71
71
  # to the middleware stack we end up testing two middlewares instead of one
72
72
  it 'should create a Hash from the body' do
73
- stubs.get('/hash') {[200, {'content-type' => 'application/json; charset=utf-8'}, { "name" => "Erik Michaels-Ober", "username" => "sferik" }]}
73
+ stubs.get('/hash') {
74
+ data = { 'name' => 'Erik Michaels-Ober', 'username' => 'sferik' }
75
+ [200, {'content-type' => 'application/json; charset=utf-8'}, data]
76
+ }
74
77
  me = connection.get('/hash').body
75
78
  me.name.should == 'Erik Michaels-Ober'
76
79
  me.username.should == 'sferik'
data/spec/oauth_spec.rb CHANGED
@@ -1,6 +1,7 @@
1
1
  require 'helper'
2
2
  require 'faraday_middleware/request/oauth'
3
3
  require 'uri'
4
+ require 'forwardable'
4
5
 
5
6
  describe FaradayMiddleware::OAuth do
6
7
  def auth_header(env)
@@ -14,11 +15,12 @@ describe FaradayMiddleware::OAuth do
14
15
  end
15
16
  end
16
17
 
17
- def perform(oauth_options = {}, headers = {})
18
+ def perform(oauth_options = {}, headers = {}, params = {})
18
19
  env = {
19
20
  :url => URI('http://example.com/'),
20
21
  :request_headers => Faraday::Utils::Headers.new.update(headers),
21
- :request => {}
22
+ :request => {},
23
+ :body => params
22
24
  }
23
25
  unless oauth_options.is_a? Hash and oauth_options.empty?
24
26
  env[:request][:oauth] = oauth_options
@@ -98,4 +100,52 @@ describe FaradayMiddleware::OAuth do
98
100
  auth.should_not include('oauth_token')
99
101
  end
100
102
  end
103
+
104
+ context "handling body parameters" do
105
+ let(:options) { [{ :consumer_key => 'CKEY',
106
+ :consumer_secret => 'CSECRET',
107
+ :nonce => '547fed103e122eecf84c080843eedfe6',
108
+ :timestamp => '1286830180'}] }
109
+
110
+ let(:value) { {'foo' => 'bar'} }
111
+
112
+ let(:type_json) { {'Content-Type' => 'application/json'} }
113
+ let(:type_form) { {'Content-Type' => 'application/x-www-form-urlencoded'} }
114
+
115
+ extend Forwardable
116
+ query_method = :build_nested_query
117
+ query_module = ::Faraday::Utils.respond_to?(query_method) ? 'Faraday::Utils' : 'Rack::Utils'
118
+ def_delegator query_module, query_method
119
+
120
+ it "does not include the body for JSON" do
121
+ auth_header_with = auth_header(perform({}, type_json, '{"foo":"bar"}'))
122
+ auth_header_without = auth_header(perform({}, type_json, {}))
123
+
124
+ auth_header_with.should == auth_header_without
125
+ end
126
+
127
+ it "includes the body parameters with form Content-Type" do
128
+ auth_header_with = auth_header(perform({}, type_form, {}))
129
+ auth_header_without = auth_header(perform({}, type_form, value))
130
+
131
+ auth_header_with.should_not == auth_header_without
132
+ end
133
+
134
+ it "includes the body parameters with an unspecified Content-Type" do
135
+ auth_header_with = auth_header(perform({}, {}, value))
136
+ auth_header_without = auth_header(perform({}, type_form, value))
137
+
138
+ auth_header_with.should == auth_header_without
139
+ end
140
+
141
+ it "includes the body parameters for form type with string body" do
142
+ # simulates the behavior of Faraday::MiddleWare::UrlEncoded
143
+ value = { 'foo' => ['bar', 'baz', 'wat'] }
144
+ auth_header_hash = auth_header(perform({}, type_form, value))
145
+ auth_header_string = auth_header(perform({}, type_form, build_nested_query(value)))
146
+ auth_header_string.should == auth_header_hash
147
+ end
148
+
149
+ end
150
+
101
151
  end
@@ -90,5 +90,11 @@ describe FaradayMiddleware::ParseJson, :type => :response do
90
90
  response.body.should be_a(Hash)
91
91
  response['content-type'].should eql('application/json')
92
92
  end
93
+
94
+ it "corrects compatible type even when data starts with whitespace" do
95
+ response = process(%( \r\n\t{"a":1}), 'text/javascript')
96
+ response.body.should be_a(Hash)
97
+ response['content-type'].should eql('application/json')
98
+ end
93
99
  end
94
100
  end
data/spec/rashify_spec.rb CHANGED
@@ -60,7 +60,10 @@ describe FaradayMiddleware::Rashify do
60
60
  # although it is not good practice to pass a hash as the body, if we add ParseJson
61
61
  # to the middleware stack we end up testing two middlewares instead of one
62
62
  it 'should create a Hash from the body' do
63
- stubs.get('/hash') {[200, {'content-type' => 'application/json; charset=utf-8'}, { "name" => "Erik Michaels-Ober", "username" => "sferik" }]}
63
+ stubs.get('/hash') {
64
+ data = { 'name' => 'Erik Michaels-Ober', 'username' => 'sferik' }
65
+ [200, {'content-type' => 'application/json; charset=utf-8'}, data]
66
+ }
64
67
  me = connection.get('/hash').body
65
68
  me.name.should == 'Erik Michaels-Ober'
66
69
  me.username.should == 'sferik'
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
4
+ version: 0.8.5
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -10,11 +10,11 @@ authors:
10
10
  autorequire:
11
11
  bindir: bin
12
12
  cert_chain: []
13
- date: 2012-01-30 00:00:00.000000000 Z
13
+ date: 2012-03-11 00:00:00.000000000 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: faraday
17
- requirement: &70176520423440 !ruby/object:Gem::Requirement
17
+ requirement: &70319499815400 !ruby/object:Gem::Requirement
18
18
  none: false
19
19
  requirements:
20
20
  - - ! '>='
@@ -25,10 +25,10 @@ dependencies:
25
25
  version: '0.9'
26
26
  type: :runtime
27
27
  prerelease: false
28
- version_requirements: *70176520423440
28
+ version_requirements: *70319499815400
29
29
  - !ruby/object:Gem::Dependency
30
30
  name: multi_xml
31
- requirement: &70176520413280 !ruby/object:Gem::Requirement
31
+ requirement: &70319499836420 !ruby/object:Gem::Requirement
32
32
  none: false
33
33
  requirements:
34
34
  - - ~>
@@ -36,10 +36,10 @@ dependencies:
36
36
  version: '0.2'
37
37
  type: :development
38
38
  prerelease: false
39
- version_requirements: *70176520413280
39
+ version_requirements: *70319499836420
40
40
  - !ruby/object:Gem::Dependency
41
41
  name: rake
42
- requirement: &70176520410400 !ruby/object:Gem::Requirement
42
+ requirement: &70319499834040 !ruby/object:Gem::Requirement
43
43
  none: false
44
44
  requirements:
45
45
  - - ~>
@@ -47,10 +47,10 @@ dependencies:
47
47
  version: '0.9'
48
48
  type: :development
49
49
  prerelease: false
50
- version_requirements: *70176520410400
50
+ version_requirements: *70319499834040
51
51
  - !ruby/object:Gem::Dependency
52
52
  name: hashie
53
- requirement: &70176520395720 !ruby/object:Gem::Requirement
53
+ requirement: &70319499847520 !ruby/object:Gem::Requirement
54
54
  none: false
55
55
  requirements:
56
56
  - - ~>
@@ -58,10 +58,10 @@ dependencies:
58
58
  version: '1.2'
59
59
  type: :development
60
60
  prerelease: false
61
- version_requirements: *70176520395720
61
+ version_requirements: *70319499847520
62
62
  - !ruby/object:Gem::Dependency
63
63
  name: rash
64
- requirement: &70176520393980 !ruby/object:Gem::Requirement
64
+ requirement: &70319499843360 !ruby/object:Gem::Requirement
65
65
  none: false
66
66
  requirements:
67
67
  - - ~>
@@ -69,10 +69,10 @@ dependencies:
69
69
  version: '0.3'
70
70
  type: :development
71
71
  prerelease: false
72
- version_requirements: *70176520393980
72
+ version_requirements: *70319499843360
73
73
  - !ruby/object:Gem::Dependency
74
74
  name: rspec
75
- requirement: &70176520392900 !ruby/object:Gem::Requirement
75
+ requirement: &70319499841140 !ruby/object:Gem::Requirement
76
76
  none: false
77
77
  requirements:
78
78
  - - ~>
@@ -80,10 +80,10 @@ dependencies:
80
80
  version: '2.6'
81
81
  type: :development
82
82
  prerelease: false
83
- version_requirements: *70176520392900
83
+ version_requirements: *70319499841140
84
84
  - !ruby/object:Gem::Dependency
85
85
  name: simple_oauth
86
- requirement: &70176520391440 !ruby/object:Gem::Requirement
86
+ requirement: &70319499852100 !ruby/object:Gem::Requirement
87
87
  none: false
88
88
  requirements:
89
89
  - - ~>
@@ -91,10 +91,10 @@ dependencies:
91
91
  version: '0.1'
92
92
  type: :development
93
93
  prerelease: false
94
- version_requirements: *70176520391440
94
+ version_requirements: *70319499852100
95
95
  - !ruby/object:Gem::Dependency
96
96
  name: rack-cache
97
- requirement: &70176520390140 !ruby/object:Gem::Requirement
97
+ requirement: &70319499897100 !ruby/object:Gem::Requirement
98
98
  none: false
99
99
  requirements:
100
100
  - - ~>
@@ -102,7 +102,7 @@ dependencies:
102
102
  version: '1.1'
103
103
  type: :development
104
104
  prerelease: false
105
- version_requirements: *70176520390140
105
+ version_requirements: *70319499897100
106
106
  description: Various middleware for Faraday
107
107
  email:
108
108
  - sferik@gmail.com