Loading lib/httpx/plugins/auth.rb +21 −2 Original line number Diff line number Diff line Loading @@ -81,10 +81,14 @@ module HTTPX def generate_auth_token return unless (auth_value = @options.auth_header_value) auth_value = auth_value.call(self) if auth_value.respond_to?(:call) auth_value = auth_value.call(self) if dynamic_auth_token?(auth_value) auth_value end def dynamic_auth_token?(auth_header_value) auth_header_value&.respond_to?(:call) end end module RequestMethods Loading @@ -99,14 +103,29 @@ module HTTPX module AuthRetries module InstanceMethods private def retryable_request?(request, response, options) super || auth_error?(response, options) end def retryable_response?(response, options) auth_error?(response, options) || super end def prepare_to_retry(request, response) super return unless @options.generate_auth_value_on_retry && @options.generate_auth_value_on_retry.call(response) return unless auth_error?(response, request.options) || (@options.generate_auth_value_on_retry && @options.generate_auth_value_on_retry.call(response)) request.headers.get("authorization").pop @auth_header_value = generate_auth_token end def auth_error?(response, options) response.is_a?(Response) && response.status == 401 && dynamic_auth_token?(options.auth_header_value) end end end end Loading lib/httpx/plugins/oauth.rb +8 −18 Original line number Diff line number Diff line Loading @@ -259,32 +259,22 @@ module HTTPX @oauth_session.fetch_access_token(self) end end module OAuthRetries class << self def extra_options(options) options.merge( retry_on: method(:response_oauth_error?), generate_auth_value_on_retry: method(:response_oauth_error?) ) end def response_oauth_error?(res) res.is_a?(Response) && res.status == 401 def dynamic_auth_token?(auth_header_value) @oauth_session end end module OAuthRetries module InstanceMethods def prepare_to_retry(_request, response) unless @oauth_session && @options.generate_auth_value_on_retry && @options.generate_auth_value_on_retry.call(response) return super end private @oauth_session.reset! def prepare_to_retry(_request, response) @oauth_session.reset! if @oauth_session super end end end end Loading sig/plugins/auth.rbs +10 −1 Original line number Diff line number Diff line module HTTPX module Plugins module Auth type auth_header_value_type = String | ^(Request request) -> string interface _AuthOptions def auth_header_value: () -> (String | ^(Request request) -> string)? def auth_header_value: () -> auth_header_value_type? def auth_header_type: () -> String? end Loading @@ -22,6 +24,8 @@ module HTTPX private def generate_auth_token: () -> String? def dynamic_auth_token?: (auth_header_value_type auth_header_value) -> boolish end module RequestMethods Loading @@ -29,6 +33,11 @@ module HTTPX end module AuthRetries module InstanceMethods private def auth_error?: (response response, Options options) -> boolish end end end Loading sig/plugins/oauth.rbs +0 −2 Original line number Diff line number Diff line Loading @@ -87,8 +87,6 @@ module HTTPX end module OAuthRetries def self?.response_oauth_error?: (response res) -> bool module InstanceMethods end end Loading test/support/requests/plugins/auth.rb +14 −5 Original line number Diff line number Diff line Loading @@ -50,18 +50,27 @@ module Requests end def test_plugin_auth_regenerate_on_retry uri = build_uri("/status/401") i = 0 session = HTTPX.plugin(RequestInspector) .plugin(:retries, max_retries: 1, retry_on: ->(res) { res.status == 401 }) .plugin(:auth, generate_auth_value_on_retry: ->(res) { res.status == 401 }) .plugin(:retries, max_retries: 1, retry_on: ->(res) { res.status == 400 }) .plugin(:auth, generate_auth_value_on_retry: ->(res) { res.status == 400 }) .authorization { "TOKEN#{i += 1}" } response = session.get(uri) verify_status(response, 401) response = session.get(build_uri("/status/400")) verify_status(response, 400) assert session.calls == 1, "expected two errors to have been sent" req1, req2 = session.total_requests assert req1.headers["authorization"] == "TOKEN1" assert req2.headers["authorization"] == "TOKEN2" session.reset # 401 errors are always retried with a fresh token, no matter the verb response = session.get(build_uri("/status/401")) verify_status(response, 401) assert session.calls == 1, "expected two errors to have been sent" req1, req2 = session.total_requests assert req1.headers["authorization"] == "TOKEN2", "the last successful token should have been reused" assert req2.headers["authorization"] == "TOKEN3" end # Bearer Auth Loading Loading
lib/httpx/plugins/auth.rb +21 −2 Original line number Diff line number Diff line Loading @@ -81,10 +81,14 @@ module HTTPX def generate_auth_token return unless (auth_value = @options.auth_header_value) auth_value = auth_value.call(self) if auth_value.respond_to?(:call) auth_value = auth_value.call(self) if dynamic_auth_token?(auth_value) auth_value end def dynamic_auth_token?(auth_header_value) auth_header_value&.respond_to?(:call) end end module RequestMethods Loading @@ -99,14 +103,29 @@ module HTTPX module AuthRetries module InstanceMethods private def retryable_request?(request, response, options) super || auth_error?(response, options) end def retryable_response?(response, options) auth_error?(response, options) || super end def prepare_to_retry(request, response) super return unless @options.generate_auth_value_on_retry && @options.generate_auth_value_on_retry.call(response) return unless auth_error?(response, request.options) || (@options.generate_auth_value_on_retry && @options.generate_auth_value_on_retry.call(response)) request.headers.get("authorization").pop @auth_header_value = generate_auth_token end def auth_error?(response, options) response.is_a?(Response) && response.status == 401 && dynamic_auth_token?(options.auth_header_value) end end end end Loading
lib/httpx/plugins/oauth.rb +8 −18 Original line number Diff line number Diff line Loading @@ -259,32 +259,22 @@ module HTTPX @oauth_session.fetch_access_token(self) end end module OAuthRetries class << self def extra_options(options) options.merge( retry_on: method(:response_oauth_error?), generate_auth_value_on_retry: method(:response_oauth_error?) ) end def response_oauth_error?(res) res.is_a?(Response) && res.status == 401 def dynamic_auth_token?(auth_header_value) @oauth_session end end module OAuthRetries module InstanceMethods def prepare_to_retry(_request, response) unless @oauth_session && @options.generate_auth_value_on_retry && @options.generate_auth_value_on_retry.call(response) return super end private @oauth_session.reset! def prepare_to_retry(_request, response) @oauth_session.reset! if @oauth_session super end end end end Loading
sig/plugins/auth.rbs +10 −1 Original line number Diff line number Diff line module HTTPX module Plugins module Auth type auth_header_value_type = String | ^(Request request) -> string interface _AuthOptions def auth_header_value: () -> (String | ^(Request request) -> string)? def auth_header_value: () -> auth_header_value_type? def auth_header_type: () -> String? end Loading @@ -22,6 +24,8 @@ module HTTPX private def generate_auth_token: () -> String? def dynamic_auth_token?: (auth_header_value_type auth_header_value) -> boolish end module RequestMethods Loading @@ -29,6 +33,11 @@ module HTTPX end module AuthRetries module InstanceMethods private def auth_error?: (response response, Options options) -> boolish end end end Loading
sig/plugins/oauth.rbs +0 −2 Original line number Diff line number Diff line Loading @@ -87,8 +87,6 @@ module HTTPX end module OAuthRetries def self?.response_oauth_error?: (response res) -> bool module InstanceMethods end end Loading
test/support/requests/plugins/auth.rb +14 −5 Original line number Diff line number Diff line Loading @@ -50,18 +50,27 @@ module Requests end def test_plugin_auth_regenerate_on_retry uri = build_uri("/status/401") i = 0 session = HTTPX.plugin(RequestInspector) .plugin(:retries, max_retries: 1, retry_on: ->(res) { res.status == 401 }) .plugin(:auth, generate_auth_value_on_retry: ->(res) { res.status == 401 }) .plugin(:retries, max_retries: 1, retry_on: ->(res) { res.status == 400 }) .plugin(:auth, generate_auth_value_on_retry: ->(res) { res.status == 400 }) .authorization { "TOKEN#{i += 1}" } response = session.get(uri) verify_status(response, 401) response = session.get(build_uri("/status/400")) verify_status(response, 400) assert session.calls == 1, "expected two errors to have been sent" req1, req2 = session.total_requests assert req1.headers["authorization"] == "TOKEN1" assert req2.headers["authorization"] == "TOKEN2" session.reset # 401 errors are always retried with a fresh token, no matter the verb response = session.get(build_uri("/status/401")) verify_status(response, 401) assert session.calls == 1, "expected two errors to have been sent" req1, req2 = session.total_requests assert req1.headers["authorization"] == "TOKEN2", "the last successful token should have been reused" assert req2.headers["authorization"] == "TOKEN3" end # Bearer Auth Loading