faraday_middleware 0.9.0 → 0.9.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 281f479ebac151c76b6f622d3e2d919fcba90d3e
4
+ data.tar.gz: b536b23c23f5980b7d1645b5907a0bd8401369c3
5
+ SHA512:
6
+ metadata.gz: cb1e56ae090cdf939b3b9a74b366a7d6abb787486b019cbe8f9803295bfb600f78a276d47360af69e54138d601ea2d02c02e78fe7143e1b3a0bbb5158e709cff
7
+ data.tar.gz: ba124f9959f87f44128b8b7ab782360932d068077311a2ab15de90e37b784cb71350d1d2e47df0f660051e850ea6fbcd5917c741e36bbfdf50ab4295db02b255
@@ -0,0 +1,46 @@
1
+ ## Contributing
2
+ In the spirit of [free software][free-sw], **everyone** is encouraged to help
3
+ improve this project.
4
+
5
+ [free-sw]: http://www.fsf.org/licensing/essays/free-sw.html
6
+
7
+ Here are some ways *you* can contribute:
8
+
9
+ * by using alpha, beta, and prerelease versions
10
+ * by reporting bugs
11
+ * by suggesting new features
12
+ * by writing or editing documentation
13
+ * by writing specifications
14
+ * by writing code (**no patch is too small**: fix typos, add comments, clean up
15
+ inconsistent whitespace)
16
+ * by refactoring code
17
+ * by fixing [issues][]
18
+ * by reviewing patches
19
+
20
+ [issues]: https://github.com/lostisland/faraday_middleware/issues
21
+
22
+ ## Submitting an Issue
23
+ We use the [GitHub issue tracker][issues] to track bugs and features. Before
24
+ submitting a bug report or feature request, check to make sure it hasn't
25
+ already been submitted. When submitting a bug report, please include a [Gist][]
26
+ that includes a stack trace and any details that may be necessary to reproduce
27
+ the bug, including your gem version, Ruby version, and operating system.
28
+ Ideally, a bug report should include a pull request with failing specs.
29
+
30
+ [gist]: https://gist.github.com/
31
+
32
+ ## Submitting a Pull Request
33
+ 1. [Fork the repository.][fork]
34
+ 2. [Create a topic branch.][branch]
35
+ 3. Add specs for your unimplemented feature or bug fix.
36
+ 4. Run `bundle exec rake spec`. If your specs pass, return to step 3.
37
+ 5. Implement your feature or bug fix.
38
+ 6. Run `bundle exec rake spec`. If your specs fail, return to step 5.
39
+ 7. Run `open coverage/index.html`. If your changes are not completely covered
40
+ by your tests, return to step 3.
41
+ 8. Add, commit, and push your changes.
42
+ 9. [Submit a pull request.][pr]
43
+
44
+ [fork]: http://help.github.com/fork-a-repo/
45
+ [branch]: http://learn.github.com/p/branching.html
46
+ [pr]: http://help.github.com/send-pull-requests/
data/README.md CHANGED
@@ -50,5 +50,5 @@ end
50
50
  ```
51
51
 
52
52
 
53
- [faraday]: https://github.com/technoweenie/faraday#readme
54
- [docs]: https://github.com/pengwynn/faraday_middleware/wiki
53
+ [faraday]: https://github.com/lostisland/faraday#readme
54
+ [docs]: https://github.com/lostisland/faraday_middleware/wiki
data/Rakefile CHANGED
@@ -1,7 +1,11 @@
1
- if defined? RUBY_ENGINE and 'ruby' == RUBY_ENGINE and RUBY_VERSION.index('1.9') == 0
2
- task :default => [:enable_coverage, :spec, :test, :quality]
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]
3
7
  else
4
- task :default => [:spec, :test]
8
+ task :default => [:spec]
5
9
  end
6
10
 
7
11
  require 'bundler'
@@ -14,16 +18,11 @@ task :enable_coverage do
14
18
  ENV['COVERAGE'] = 'yes'
15
19
  end
16
20
 
17
- desc %(Run Test::Unit tests)
18
- task :test do
19
- sh 'ruby', '-Ilib', 'spec/caching_test.rb'
20
- end
21
-
22
21
  desc %(Check code quality metrics with Cane)
23
22
  task :quality do
24
23
  sh 'cane',
25
24
  '--abc-max=15',
26
25
  '--style-measure=110',
27
- '--gte=coverage/covered_percent,99',
26
+ '--gte=coverage/covered_percent,98.9',
28
27
  '--max-violations=0'
29
28
  end
@@ -1,23 +1,23 @@
1
- require File.expand_path('../lib/faraday_middleware/version', __FILE__)
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'faraday_middleware/version'
2
5
 
3
- Gem::Specification.new do |gem|
4
- gem.add_dependency 'faraday', ['>= 0.7.4', '< 0.9']
5
- gem.add_development_dependency 'multi_xml', '~> 0.2'
6
- gem.add_development_dependency 'rake', '~> 0.9'
7
- gem.add_development_dependency 'hashie', '~> 1.2'
8
- gem.add_development_dependency 'rash', '~> 0.3'
9
- gem.add_development_dependency 'rspec', '~> 2.6'
10
- gem.add_development_dependency 'simple_oauth', '~> 0.1'
11
- gem.add_development_dependency 'rack-cache', '~> 1.1'
12
- gem.authors = ["Erik Michaels-Ober", "Wynn Netherland"]
13
- gem.description = %q{Various middleware for Faraday}
14
- gem.email = ['sferik@gmail.com', 'wynn.netherland@gmail.com']
15
- gem.files = `git ls-files`.split("\n")
16
- gem.homepage = 'https://github.com/pengwynn/faraday_middleware'
17
- gem.name = 'faraday_middleware'
18
- gem.require_paths = ['lib']
19
- gem.required_rubygems_version = Gem::Requirement.new('>= 1.3.6')
20
- gem.summary = gem.description
21
- gem.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
22
- gem.version = FaradayMiddleware::VERSION
6
+ Gem::Specification.new do |spec|
7
+ spec.add_dependency 'faraday', ['>= 0.7.4', '< 0.10']
8
+ spec.add_development_dependency 'bundler', '~> 1.0'
9
+ spec.authors = ["Erik Michaels-Ober", "Wynn Netherland"]
10
+ spec.description = %q{Various middleware for Faraday}
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/**/*")
15
+ spec.homepage = 'https://github.com/lostisland/faraday_middleware'
16
+ spec.licenses = ['MIT']
17
+ spec.name = 'faraday_middleware'
18
+ spec.require_paths = ['lib']
19
+ spec.required_rubygems_version = '>= 1.3.5'
20
+ spec.summary = spec.description
21
+ spec.test_files += Dir.glob("spec/**/*")
22
+ spec.version = FaradayMiddleware::VERSION
23
23
  end
@@ -18,14 +18,14 @@ module FaradayMiddleware
18
18
  autoload :FollowRedirects, 'faraday_middleware/response/follow_redirects'
19
19
  autoload :Instrumentation, 'faraday_middleware/instrumentation'
20
20
 
21
- if Faraday.respond_to? :register_middleware
22
- Faraday.register_middleware :request,
21
+ if Faraday::Middleware.respond_to? :register_middleware
22
+ Faraday::Request.register_middleware \
23
23
  :oauth => lambda { OAuth },
24
24
  :oauth2 => lambda { OAuth2 },
25
25
  :json => lambda { EncodeJson },
26
26
  :method_override => lambda { MethodOverride }
27
27
 
28
- Faraday.register_middleware :response,
28
+ Faraday::Response.register_middleware \
29
29
  :mashify => lambda { Mashify },
30
30
  :rashify => lambda { Rashify },
31
31
  :json => lambda { ParseJson },
@@ -38,7 +38,7 @@ module FaradayMiddleware
38
38
  :follow_redirects => lambda { FollowRedirects },
39
39
  :chunked => lambda { Chunked }
40
40
 
41
- Faraday.register_middleware \
41
+ Faraday::Middleware.register_middleware \
42
42
  :instrumentation => lambda { Instrumentation }
43
43
  end
44
44
  end
@@ -8,8 +8,8 @@ module FaradayMiddleware
8
8
  def initialize(app, rack_handler, *args)
9
9
  # tiny middleware that decomposes a Faraday::Response to standard Rack
10
10
  # array: [status, headers, body]
11
- compatible_app = lambda do |env|
12
- restore_env(env)
11
+ compatible_app = lambda do |rack_env|
12
+ env = restore_env(rack_env)
13
13
  response = app.call(env)
14
14
  [response.status, response.headers, Array(response.body)]
15
15
  end
@@ -17,43 +17,47 @@ module FaradayMiddleware
17
17
  end
18
18
 
19
19
  def call(env)
20
- prepare_env(env)
21
- rack_response = @rack.call(env)
20
+ rack_env = prepare_env(env)
21
+ rack_response = @rack.call(rack_env)
22
22
  finalize_response(env, rack_response)
23
23
  end
24
24
 
25
25
  NonPrefixedHeaders = %w[CONTENT_LENGTH CONTENT_TYPE]
26
26
 
27
27
  # faraday to rack-compatible
28
- def prepare_env(env)
29
- headers_to_rack(env)
28
+ def prepare_env(faraday_env)
29
+ env = headers_to_rack(faraday_env)
30
30
 
31
- url = env[:url]
31
+ url = faraday_env[:url]
32
32
  env['rack.url_scheme'] = url.scheme
33
33
  env['PATH_INFO'] = url.path
34
34
  env['SERVER_PORT'] = url.respond_to?(:inferred_port) ? url.inferred_port : url.port
35
35
  env['QUERY_STRING'] = url.query
36
- env['REQUEST_METHOD'] = env[:method].to_s.upcase
36
+ env['REQUEST_METHOD'] = faraday_env[:method].to_s.upcase
37
37
 
38
38
  env['rack.errors'] ||= StringIO.new
39
+ env['faraday'] = faraday_env
39
40
 
40
41
  env
41
42
  end
42
43
 
43
44
  def headers_to_rack(env)
45
+ rack_env = {}
44
46
  env[:request_headers].each do |name, value|
45
47
  name = name.upcase.tr('-', '_')
46
48
  name = "HTTP_#{name}" unless NonPrefixedHeaders.include? name
47
- env[name] = value
49
+ rack_env[name] = value
48
50
  end
51
+ rack_env
49
52
  end
50
53
 
51
54
  # rack to faraday-compatible
52
- def restore_env(env)
55
+ def restore_env(rack_env)
56
+ env = rack_env.fetch('faraday')
53
57
  headers = env[:request_headers]
54
58
  headers.clear
55
59
 
56
- env.each do |name, value|
60
+ rack_env.each do |name, value|
57
61
  next unless String === name
58
62
  if NonPrefixedHeaders.include? name or name.index('HTTP_') == 0
59
63
  name = name.sub(/^HTTP_/, '').downcase.tr('_', '-')
@@ -61,7 +65,8 @@ module FaradayMiddleware
61
65
  end
62
66
  end
63
67
 
64
- env[:method] = env['REQUEST_METHOD'].downcase.to_sym
68
+ env[:method] = rack_env['REQUEST_METHOD'].downcase.to_sym
69
+ env[:rack_errors] = rack_env['rack.errors']
65
70
  env
66
71
  end
67
72
 
@@ -72,7 +72,7 @@ module FaradayMiddleware
72
72
  end
73
73
 
74
74
  def include_body_params?(env)
75
- # see RFC 5489, section 3.4.1.3.1 for details
75
+ # see RFC 5849, section 3.4.1.3.1 for details
76
76
  !(type = env[:request_headers][CONTENT_TYPE]) or type == TYPE_URLENCODED
77
77
  end
78
78
 
@@ -31,8 +31,9 @@ module FaradayMiddleware
31
31
 
32
32
  def call(env)
33
33
  params = { param_name => @token }.update query_params(env[:url])
34
+ token = params[param_name]
34
35
 
35
- if token = params[param_name] and !token.empty?
36
+ if token.respond_to?(:empty?) && !token.empty?
36
37
  env[:url].query = build_query params
37
38
  env[:request_headers][AUTH_HEADER] ||= %(Token token="#{token}")
38
39
  end
@@ -47,7 +47,7 @@ module FaradayMiddleware
47
47
  if url.query && params_to_ignore.any?
48
48
  params = parse_query url.query
49
49
  params.reject! {|k,| params_to_ignore.include? k }
50
- url.query = build_query params
50
+ url.query = params.any? ? build_query(params) : nil
51
51
  end
52
52
  url.normalize!
53
53
  url.request_uri
@@ -4,7 +4,7 @@ require "faraday"
4
4
  module FaradayMiddleware
5
5
  # Parse dates from response body
6
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
7
+ ISO_DATE_FORMAT = /\A\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(\.\d+)?Z\Z/m
8
8
 
9
9
  def initialize(app, options = {})
10
10
  @regexp = options[:match] || ISO_DATE_FORMAT
@@ -75,4 +75,36 @@ module FaradayMiddleware
75
75
  env[:request].fetch(:preserve_raw, @options[:preserve_raw])
76
76
  end
77
77
  end
78
+
79
+ # DRAGONS
80
+ module OptionsExtension
81
+ attr_accessor :preserve_raw
82
+
83
+ def to_hash
84
+ super.update(:preserve_raw => preserve_raw)
85
+ end
86
+
87
+ def each
88
+ return to_enum(:each) unless block_given?
89
+ super
90
+ yield :preserve_raw, preserve_raw
91
+ end
92
+
93
+ def fetch(key, *args)
94
+ if :preserve_raw == key
95
+ value = __send__(key)
96
+ value.nil? ? args.fetch(0) : value
97
+ else
98
+ super
99
+ end
100
+ end
101
+ end
102
+
103
+ if defined?(Faraday::RequestOptions)
104
+ begin
105
+ Faraday::RequestOptions.from(:preserve_raw => true)
106
+ rescue NoMethodError
107
+ Faraday::RequestOptions.send(:include, OptionsExtension)
108
+ end
109
+ end
78
110
  end
@@ -1,3 +1,3 @@
1
1
  module FaradayMiddleware
2
- VERSION = "0.9.0"
2
+ VERSION = "0.9.1" unless defined?(FaradayMiddleware::VERSION)
3
3
  end
@@ -0,0 +1,170 @@
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