diff --git a/docs/middleware/request/authentication.md b/docs/middleware/request/authentication.md index f365552f2..f4192fa40 100644 --- a/docs/middleware/request/authentication.md +++ b/docs/middleware/request/authentication.md @@ -30,6 +30,14 @@ Faraday.new(...) do |conn| end ``` +If the proc takes an argument, it will receive the forwarded `env` + +```ruby +Faraday.new(...) do |conn| + conn.request :authorization, 'Bearer', ->(env) { MyAuthStorage.get_auth_token(env) } +end +``` + ### Basic Authentication The middleware will automatically Base64 encode your Basic username and password: diff --git a/lib/faraday/request/authorization.rb b/lib/faraday/request/authorization.rb index 3eb104217..43732432d 100644 --- a/lib/faraday/request/authorization.rb +++ b/lib/faraday/request/authorization.rb @@ -23,22 +23,27 @@ def initialize(app, type, *params) def on_request(env) return if env.request_headers[KEY] - env.request_headers[KEY] = header_from(@type, *@params) + env.request_headers[KEY] = header_from(@type, env, *@params) end private # @param type [String, Symbol] + # @param env [Faraday::Env] # @param params [Array] # @return [String] a header value - def header_from(type, *params) + def header_from(type, env, *params) if type.to_s.casecmp('basic').zero? && params.size == 2 Utils.basic_header_from(*params) elsif params.size != 1 raise ArgumentError, "Unexpected params received (got #{params.size} instead of 1)" else value = params.first - value = value.call if value.is_a?(Proc) || value.respond_to?(:call) + if (value.is_a?(Proc) && value.arity == 1) || (value.respond_to?(:call) && value.method(:call).arity == 1) + value = value.call(env) + elsif value.is_a?(Proc) || value.respond_to?(:call) + value = value.call + end "#{type} #{value}" end end diff --git a/spec/faraday/request/authorization_spec.rb b/spec/faraday/request/authorization_spec.rb index 9f4e863de..437c88ae0 100644 --- a/spec/faraday/request/authorization_spec.rb +++ b/spec/faraday/request/authorization_spec.rb @@ -72,6 +72,41 @@ include_examples 'does not interfere with existing authentication' end + context 'with an argument' do + let(:response) { conn.get('/auth-echo', nil, 'middle' => 'crunchy surprise') } + + context 'when passed a proc' do + let(:auth_config) { [proc { |env| "proc #{env.request_headers['middle']}" }] } + + it { expect(response.body).to eq('Bearer proc crunchy surprise') } + + include_examples 'does not interfere with existing authentication' + end + + context 'when passed a lambda' do + let(:auth_config) { [->(env) { "lambda #{env.request_headers['middle']}" }] } + + it { expect(response.body).to eq('Bearer lambda crunchy surprise') } + + include_examples 'does not interfere with existing authentication' + end + + context 'when passed a callable with an argument' do + let(:callable) do + Class.new do + def call(env) + "callable #{env.request_headers['middle']}" + end + end.new + end + let(:auth_config) { [callable] } + + it { expect(response.body).to eq('Bearer callable crunchy surprise') } + + include_examples 'does not interfere with existing authentication' + end + end + context 'when passed too many arguments' do let(:auth_config) { %w[baz foo] }