faraday_middleware 0.8.4 → 0.8.5

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