Skip to content

Commit

Permalink
Backport authorization procs to 1.x branch (#1322)
Browse files Browse the repository at this point in the history
  • Loading branch information
jarl-dk committed Sep 17, 2021
1 parent d881f16 commit 2a5702a
Show file tree
Hide file tree
Showing 3 changed files with 57 additions and 6 deletions.
10 changes: 10 additions & 0 deletions docs/middleware/request/authentication.md
Expand Up @@ -23,6 +23,16 @@ Faraday.new(...) do |conn|
end
```

### With a proc

You can also provide a proc, which will be evaluated on each request:

```ruby
Faraday.new(...) do |conn|
conn.request :authorization, 'Bearer', -> { MyAuthStorage.get_auth_token }
end
```

### Basic Authentication

`BasicAuthentication` adds a 'Basic' type Authorization header to a Faraday request.
Expand Down
45 changes: 39 additions & 6 deletions lib/faraday/request/authorization.rb
@@ -1,5 +1,7 @@
# frozen_string_literal: true

require 'base64'

module Faraday
class Request
# Request middleware for the Authorization HTTP header
Expand Down Expand Up @@ -39,16 +41,47 @@ def self.build_hash(type, hash)

# @param app [#call]
# @param type [String, Symbol] Type of Authorization
# @param token [String, Symbol, Hash] Token value for the Authorization
def initialize(app, type, token)
@header_value = self.class.header(type, token)
# @param params [Array<String, Proc>] parameters to build the Authorization header.
# If the type is `:basic`, then these can be a login and password pair.
# Otherwise, a single value is expected that will be appended after the type.
# This value can be a proc, in which case it will be invoked on each request.
def initialize(app, type, *params)
@type = type
@params = params
@header_value = self.class.header(type, params[0]) unless params[0].is_a? Proc
super(app)
end

# @param env [Faraday::Env]
def call(env)
env.request_headers[KEY] = @header_value unless env.request_headers[KEY]
@app.call(env)
def on_request(env)
return if env.request_headers[KEY]

env.request_headers[KEY] = header_from(@type, *@params)
end

private

# @param type [String, Symbol]
# @param params [Array]
# @return [String] a header value
def header_from(type, *params)
return @header_value if @header_value

if type.to_s.casecmp('basic').zero? && params.size == 2
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)
"#{type} #{value}"
end
end

def basic_header_from(login, pass)
value = Base64.encode64("#{login}:#{pass}")
value.delete!("\n")
"Basic #{value}"
end
end
end
Expand Down
8 changes: 8 additions & 0 deletions spec/faraday/request/authorization_spec.rb
Expand Up @@ -84,5 +84,13 @@

include_examples 'does not interfere with existing authentication'
end

context 'when passed a string and a proc' do
let(:auth_config) { ['Bearer', -> { 'custom_from_proc' }] }

it { expect(response.body).to eq('Bearer custom_from_proc') }

include_examples 'does not interfere with existing authentication'
end
end
end

0 comments on commit 2a5702a

Please sign in to comment.