faraday_middleware 0.9.1 → 0.9.2

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 281f479ebac151c76b6f622d3e2d919fcba90d3e
4
- data.tar.gz: b536b23c23f5980b7d1645b5907a0bd8401369c3
3
+ metadata.gz: 64c9daf051fce97f6b839b78e9def268977e3db9
4
+ data.tar.gz: f0cb5693d722bdf1097671a2e6f4ecdf8cf91049
5
5
  SHA512:
6
- metadata.gz: cb1e56ae090cdf939b3b9a74b366a7d6abb787486b019cbe8f9803295bfb600f78a276d47360af69e54138d601ea2d02c02e78fe7143e1b3a0bbb5158e709cff
7
- data.tar.gz: ba124f9959f87f44128b8b7ab782360932d068077311a2ab15de90e37b784cb71350d1d2e47df0f660051e850ea6fbcd5917c741e36bbfdf50ab4295db02b255
6
+ metadata.gz: 00f5f605da468818380c4bf562e8d1cab6f20a5b6d175b7f10ed54a77eb12b1069ba167d3e4dd2e33225b2fba58044a7bcdf1176d7f79cd2b1c112ce9dad6fdb
7
+ data.tar.gz: ccae90f3b06312f241d28739ba818cbd4ab56f2e2886c84a6d38e6452999be54544d4e46d51b4128c1287544b6b1df5f57abbd2c2ead6ebb76c97e0668d1b9f9
@@ -35,7 +35,7 @@ Ideally, a bug report should include a pull request with failing specs.
35
35
  3. Add specs for your unimplemented feature or bug fix.
36
36
  4. Run `bundle exec rake spec`. If your specs pass, return to step 3.
37
37
  5. Implement your feature or bug fix.
38
- 6. Run `bundle exec rake spec`. If your specs fail, return to step 5.
38
+ 6. Run `COVERAGE=true bundle exec rake spec`. If your specs fail, return to step 5.
39
39
  7. Run `open coverage/index.html`. If your changes are not completely covered
40
40
  by your tests, return to step 3.
41
41
  8. Add, commit, and push your changes.
@@ -9,15 +9,12 @@ Gem::Specification.new do |spec|
9
9
  spec.authors = ["Erik Michaels-Ober", "Wynn Netherland"]
10
10
  spec.description = %q{Various middleware for Faraday}
11
11
  spec.email = ['sferik@gmail.com', 'wynn.netherland@gmail.com']
12
- spec.files = %w(CHANGELOG.md CONTRIBUTING.md LICENSE.md README.md Rakefile faraday_middleware.gemspec)
13
- spec.files += Dir.glob("lib/**/*.rb")
14
- spec.files += Dir.glob("spec/**/*")
12
+ spec.files = %w(CHANGELOG.md CONTRIBUTING.md LICENSE.md README.md faraday_middleware.gemspec) + Dir['lib/**/*.rb']
15
13
  spec.homepage = 'https://github.com/lostisland/faraday_middleware'
16
14
  spec.licenses = ['MIT']
17
15
  spec.name = 'faraday_middleware'
18
16
  spec.require_paths = ['lib']
19
17
  spec.required_rubygems_version = '>= 1.3.5'
20
18
  spec.summary = spec.description
21
- spec.test_files += Dir.glob("spec/**/*")
22
19
  spec.version = FaradayMiddleware::VERSION
23
20
  end
@@ -22,7 +22,7 @@ module FaradayMiddleware
22
22
  end
23
23
 
24
24
  def call(env)
25
- ActiveSupport::Notifications.instrument(@name, env) do
25
+ ::ActiveSupport::Notifications.instrument(@name, env) do
26
26
  @app.call(env)
27
27
  end
28
28
  end
@@ -58,7 +58,7 @@ module FaradayMiddleware
58
58
  headers.clear
59
59
 
60
60
  rack_env.each do |name, value|
61
- next unless String === name
61
+ next unless String === name && String === value
62
62
  if NonPrefixedHeaders.include? name or name.index('HTTP_') == 0
63
63
  name = name.sub(/^HTTP_/, '').downcase.tr('_', '-')
64
64
  headers[name] = value
@@ -43,6 +43,10 @@ module FaradayMiddleware
43
43
  # Default value for max redirects followed
44
44
  FOLLOW_LIMIT = 3
45
45
 
46
+ # Regex that matches characters that need to be escaped in URLs, sans
47
+ # the "%" character which we assume already represents an escaped sequence.
48
+ URI_UNSAFE = /[^\-_.!~*'()a-zA-Z\d;\/?:@&=+$,\[\]%]/
49
+
46
50
  # Public: Initialize the middleware.
47
51
  #
48
52
  # options - An options Hash (default: {}):
@@ -78,18 +82,18 @@ module FaradayMiddleware
78
82
  request_body = env[:body]
79
83
  response = @app.call(env)
80
84
 
81
- response.on_complete do |env|
82
- if follow_redirect?(env, response)
85
+ response.on_complete do |response_env|
86
+ if follow_redirect?(response_env, response)
83
87
  raise RedirectLimitReached, response if follows.zero?
84
- env = update_env(env, request_body, response)
85
- response = perform_with_redirection(env, follows - 1)
88
+ new_request_env = update_env(response_env, request_body, response)
89
+ response = perform_with_redirection(new_request_env, follows - 1)
86
90
  end
87
91
  end
88
92
  response
89
93
  end
90
94
 
91
95
  def update_env(env, request_body, response)
92
- env[:url] += response['location']
96
+ env[:url] += safe_escape(response['location'])
93
97
  if @options[:cookies]
94
98
  cookies = keep_cookies(env)
95
99
  env[:request_headers][:cookies] = cookies unless cookies.nil?
@@ -138,5 +142,15 @@ module FaradayMiddleware
138
142
  def standards_compliant?
139
143
  @options.fetch(:standards_compliant, false)
140
144
  end
145
+
146
+ # Internal: escapes unsafe characters from an URL which might be a path
147
+ # component only or a fully qualified URI so that it can be joined onto an
148
+ # URI:HTTP using the `+` operator. Doesn't escape "%" characters so to not
149
+ # risk double-escaping.
150
+ def safe_escape(uri)
151
+ uri.to_s.gsub(URI_UNSAFE) { |match|
152
+ '%' + match.unpack('H2' * match.bytesize).join('%').upcase
153
+ }
154
+ end
141
155
  end
142
156
  end
@@ -2,6 +2,23 @@ require 'faraday_middleware/response_middleware'
2
2
 
3
3
  module FaradayMiddleware
4
4
  # Public: Parse response bodies as YAML.
5
+ #
6
+ # Warning: this uses `YAML.load()` by default and as such is not safe against
7
+ # code injection or DoS attacks. If you're loading resources from an
8
+ # untrusted host or over HTTP, you should subclass this middleware and
9
+ # redefine it to use `safe_load()` if you're using a Psych version that
10
+ # supports it:
11
+ #
12
+ # class SafeYaml < FaradayMiddleware::ParseYaml
13
+ # define_parser do |body|
14
+ # YAML.safe_load(body)
15
+ # end
16
+ # end
17
+ #
18
+ # Faraday.new(..) do |config|
19
+ # config.use SafeYaml
20
+ # ...
21
+ # end
5
22
  class ParseYaml < ResponseMiddleware
6
23
  dependency 'yaml'
7
24
 
@@ -1,3 +1,3 @@
1
1
  module FaradayMiddleware
2
- VERSION = "0.9.1" unless defined?(FaradayMiddleware::VERSION)
2
+ VERSION = "0.9.2" unless defined?(FaradayMiddleware::VERSION)
3
3
  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.9.1
4
+ version: 0.9.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Erik Michaels-Ober
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2014-04-19 00:00:00.000000000 Z
12
+ date: 2015-07-07 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: faraday
@@ -57,7 +57,6 @@ files:
57
57
  - CONTRIBUTING.md
58
58
  - LICENSE.md
59
59
  - README.md
60
- - Rakefile
61
60
  - faraday_middleware.gemspec
62
61
  - lib/faraday_middleware.rb
63
62
  - lib/faraday_middleware/addressable_patch.rb
@@ -80,21 +79,6 @@ files:
80
79
  - lib/faraday_middleware/response/rashify.rb
81
80
  - lib/faraday_middleware/response_middleware.rb
82
81
  - lib/faraday_middleware/version.rb
83
- - spec/caching_spec.rb
84
- - spec/chunked_spec.rb
85
- - spec/encode_json_spec.rb
86
- - spec/follow_redirects_spec.rb
87
- - spec/helper.rb
88
- - spec/mashify_spec.rb
89
- - spec/method_override_spec.rb
90
- - spec/oauth2_spec.rb
91
- - spec/oauth_spec.rb
92
- - spec/parse_dates_spec.rb
93
- - spec/parse_json_spec.rb
94
- - spec/parse_marshal_spec.rb
95
- - spec/parse_xml_spec.rb
96
- - spec/parse_yaml_spec.rb
97
- - spec/rashify_spec.rb
98
82
  homepage: https://github.com/lostisland/faraday_middleware
99
83
  licenses:
100
84
  - MIT
@@ -115,24 +99,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
115
99
  version: 1.3.5
116
100
  requirements: []
117
101
  rubyforge_project:
118
- rubygems_version: 2.2.0
102
+ rubygems_version: 2.2.2
119
103
  signing_key:
120
104
  specification_version: 4
121
105
  summary: Various middleware for Faraday
122
- test_files:
123
- - spec/caching_spec.rb
124
- - spec/chunked_spec.rb
125
- - spec/encode_json_spec.rb
126
- - spec/follow_redirects_spec.rb
127
- - spec/helper.rb
128
- - spec/mashify_spec.rb
129
- - spec/method_override_spec.rb
130
- - spec/oauth2_spec.rb
131
- - spec/oauth_spec.rb
132
- - spec/parse_dates_spec.rb
133
- - spec/parse_json_spec.rb
134
- - spec/parse_marshal_spec.rb
135
- - spec/parse_xml_spec.rb
136
- - spec/parse_yaml_spec.rb
137
- - spec/rashify_spec.rb
138
- has_rdoc:
106
+ test_files: []
data/Rakefile DELETED
@@ -1,28 +0,0 @@
1
- ruby_19 = RUBY_VERSION > '1.9'
2
- ruby_mri = !defined?(RUBY_ENGINE) || 'ruby' == RUBY_ENGINE
3
- default_gemfile = ENV['BUNDLE_GEMFILE'] =~ /Gemfile$/
4
-
5
- if ruby_19 && ruby_mri && default_gemfile
6
- task :default => [:enable_coverage, :spec, :quality]
7
- else
8
- task :default => [:spec]
9
- end
10
-
11
- require 'bundler'
12
- Bundler::GemHelper.install_tasks
13
-
14
- require 'rspec/core/rake_task'
15
- RSpec::Core::RakeTask.new(:spec)
16
-
17
- task :enable_coverage do
18
- ENV['COVERAGE'] = 'yes'
19
- end
20
-
21
- desc %(Check code quality metrics with Cane)
22
- task :quality do
23
- sh 'cane',
24
- '--abc-max=15',
25
- '--style-measure=110',
26
- '--gte=coverage/covered_percent,98.9',
27
- '--max-violations=0'
28
- end
@@ -1,170 +0,0 @@
1
- require 'helper'
2
- require 'forwardable'
3
- require 'fileutils'
4
- require 'rack/cache'
5
- require 'faraday'
6
- require 'faraday_middleware/response/caching'
7
- require 'faraday_middleware/rack_compatible'
8
-
9
- describe FaradayMiddleware::Caching do
10
- before do
11
- @cache = TestCache.new
12
- request_count = 0
13
- response = lambda { |env|
14
- [200, {'Content-Type' => 'text/plain'}, "request:#{request_count+=1}"]
15
- }
16
-
17
- @conn = Faraday.new do |b|
18
- b.use CachingLint
19
- b.use FaradayMiddleware::Caching, @cache, options
20
- b.adapter :test do |stub|
21
- stub.get('/', &response)
22
- stub.get('/?foo=bar', &response)
23
- stub.post('/', &response)
24
- stub.get('/other', &response)
25
- end
26
- end
27
- end
28
-
29
- let(:options) { {} }
30
-
31
- extend Forwardable
32
- def_delegators :@conn, :get, :post
33
-
34
- it 'caches get requests' do
35
- expect(get('/').body).to eq('request:1')
36
- expect(get('/').body).to eq('request:1')
37
- expect(get('/other').body).to eq('request:2')
38
- expect(get('/other').body).to eq('request:2')
39
- end
40
-
41
- it 'includes request params in the response' do
42
- get('/') # make cache
43
- response = get('/')
44
- expect(response.env[:method]).to eq(:get)
45
- expect(response.env[:url].request_uri).to eq('/')
46
- end
47
-
48
- it 'caches requests with query params' do
49
- expect(get('/').body).to eq('request:1')
50
- expect(get('/?foo=bar').body).to eq('request:2')
51
- expect(get('/?foo=bar').body).to eq('request:2')
52
- expect(get('/').body).to eq('request:1')
53
- end
54
-
55
- it 'does not cache post requests' do
56
- expect(post('/').body).to eq('request:1')
57
- expect(post('/').body).to eq('request:2')
58
- expect(post('/').body).to eq('request:3')
59
- end
60
-
61
- context ":ignore_params" do
62
- let(:options) { {:ignore_params => %w[ utm_source utm_term ]} }
63
-
64
- it "strips ignored parameters from cache_key" do
65
- expect(get('/').body).to eq('request:1')
66
- expect(get('/?utm_source=a').body).to eq('request:1')
67
- expect(get('/?utm_source=a&utm_term=b').body).to eq('request:1')
68
- expect(get('/?utm_source=a&utm_term=b&foo=bar').body).to eq('request:2')
69
- expect(get('/?foo=bar').body).to eq('request:2')
70
- end
71
- end
72
-
73
- class TestCache < Hash
74
- def read(key)
75
- if cached = self[key]
76
- Marshal.load(cached)
77
- end
78
- end
79
-
80
- def write(key, data)
81
- self[key] = Marshal.dump(data)
82
- end
83
-
84
- def fetch(key)
85
- read(key) || yield.tap { |data| write(key, data) }
86
- end
87
- end
88
-
89
- class CachingLint < Struct.new(:app)
90
- def call(env)
91
- app.call(env).on_complete do
92
- raise "no headers" unless env[:response_headers].is_a? Hash
93
- raise "no response" unless env[:response].is_a? Faraday::Response
94
- # raise "env not identical" unless env[:response].env.object_id == env.object_id
95
- end
96
- end
97
- end
98
- end
99
-
100
- # RackCompatible + Rack::Cache
101
- describe FaradayMiddleware::RackCompatible, 'caching' do
102
- include FileUtils
103
-
104
- CACHE_DIR = File.expand_path('../../tmp/cache', __FILE__)
105
-
106
- before do
107
- rm_r CACHE_DIR if File.exists? CACHE_DIR
108
- # force reinitializing cache dirs
109
- Rack::Cache::Storage.instance.clear
110
-
111
- request_count = 0
112
- response = lambda { |env|
113
- [200, { 'Content-Type' => 'text/plain',
114
- 'Cache-Control' => 'public, max-age=900',
115
- },
116
- "request:#{request_count+=1}"]
117
- }
118
-
119
- @conn = Faraday.new do |b|
120
- b.use RackErrorsComplainer
121
-
122
- b.use FaradayMiddleware::RackCompatible, Rack::Cache::Context,
123
- :metastore => "file:#{CACHE_DIR}/rack/meta",
124
- :entitystore => "file:#{CACHE_DIR}/rack/body",
125
- :verbose => true
126
-
127
- b.adapter :test do |stub|
128
- stub.get('/', &response)
129
- stub.post('/', &response)
130
- end
131
- end
132
- end
133
-
134
- extend Forwardable
135
- def_delegators :@conn, :get, :post
136
-
137
- it 'caches get requests' do
138
- response = get('/', :user_agent => 'test')
139
- expect(response.body).to eq('request:1')
140
- expect(response.env[:method]).to eq(:get)
141
- expect(response.status).to eq(200)
142
-
143
- response = get('/', :user_agent => 'test')
144
- expect(response.body).to eq('request:1')
145
- expect(response['content-type']).to eq('text/plain')
146
- expect(response.env[:method]).to eq(:get)
147
- expect(response.env[:request].respond_to?(:fetch)).to be_true
148
- expect(response.status). to eq(200)
149
-
150
- expect(post('/').body).to eq('request:2')
151
- end
152
-
153
- it 'does not cache post requests' do
154
- expect(get('/').body).to eq('request:1')
155
- expect(post('/').body).to eq('request:2')
156
- expect(post('/').body).to eq('request:3')
157
- end
158
-
159
- # middleware to check whether "rack.errors" is free of error reports
160
- class RackErrorsComplainer < Struct.new(:app)
161
- def call(env)
162
- response = app.call(env)
163
- error_stream = env[:rack_errors]
164
- if error_stream.respond_to?(:string) && error_stream.string.include?('error')
165
- raise %(unexpected error in 'rack.errors': %p) % error_stream.string
166
- end
167
- response
168
- end
169
- end
170
- end
@@ -1,78 +0,0 @@
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
- expect(process(nil).body).to be_nil
8
- end
9
-
10
- it "doesn't change an empty body" do
11
- expect(process('').body).to eq('')
12
- end
13
-
14
- it "doesn't change a normal body" do
15
- expect(process('asdf').body).to eq('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
- expect(process(nil).body).to be_nil
24
- end
25
-
26
- it "doesn't change an empty body" do
27
- expect(process('').body).to eq('')
28
- end
29
-
30
- it "doesn't change a normal body" do
31
- expect(process('asdf').body).to eq('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
- expect(process(nil).body).to be_nil
40
- end
41
-
42
- it "doesn't change an empty body" do
43
- expect(process('').body).to eq('')
44
- end
45
-
46
- it "parses a basic chunked body" do
47
- expect(process("10\r\nasdfghjklasdfghj\r\n0\r\n").body).to eq('asdfghjklasdfghj')
48
- end
49
-
50
- it "parses a chunked body with no ending chunk" do
51
- expect(process("10\r\nasdfghjklasdfghj\r\n").body).to eq('asdfghjklasdfghj')
52
- end
53
-
54
- it "parses a chunked body with no trailing CRLF on the data chunk" do
55
- expect(process("10\r\nasdfghjklasdfghj0\r\n").body).to eq('asdfghjklasdfghj')
56
- end
57
-
58
- it "parses a chunked body with an extension" do
59
- expect(process("10;foo=bar\r\nasdfghjklasdfghj\r\n0\r\n").body).to eq('asdfghjklasdfghj')
60
- end
61
-
62
- it "parses a chunked body with two extensions" do
63
- expect(process("10;foo=bar;bar=baz\r\nasdfghjklasdfghj\r\n0\r\n").body).to eq('asdfghjklasdfghj')
64
- end
65
-
66
- it "parses a chunked body with two chunks" do
67
- expect(process("8\r\nasdfghjk\r\n8\r\nlasdfghj\r\n0\r\n").body).to eq('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
- expect(process("10\r\nasdfghjklasdfghj\r\n0\r\n").body).to eq('asdfghjklasdfghj')
76
- end
77
- end
78
- end