faraday_middleware 0.9.1 → 0.9.2

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.
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