1- require "addressable/uri"
2- require "retryable"
3- require_relative "../exception.rb"
1+ # frozen_string_literal: true
2+
3+ require 'addressable/uri'
4+ require 'retryable'
5+ require_relative '../exception'
46
57module Auth0
68 module Mixins
79 # here's the proxy for Rest calls based on rest-client, we're building all request on that gem
810 # for now, if you want to feel free to use your own http client
911 module HTTPProxy
1012 attr_accessor :headers , :base_uri , :timeout , :retry_count
13+
1114 DEFAULT_RETRIES = 3
1215 MAX_ALLOWED_RETRIES = 10
1316 MAX_REQUEST_RETRY_JITTER = 250
@@ -16,19 +19,19 @@ module HTTPProxy
1619 BASE_DELAY = 100
1720
1821 # proxying requests from instance methods to HTTP class methods
19- %i( get post post_file post_form put patch delete delete_with_body ) . each do |method |
22+ %i[ get post post_file post_form put patch delete delete_with_body ] . each do |method |
2023 define_method ( method ) do |uri , body = { } , extra_headers = { } |
21- body = body . delete_if { | _ , v | v . nil? }
22- token = get_token ( )
24+ body = safe_merge_body ( body , extra_headers )
25+ token = get_token
2326 authorization_header ( token ) unless token . nil?
2427 request_with_retry ( method , uri , body , extra_headers )
2528 end
2629 end
2730
2831 def retry_options
2932 sleep_timer = lambda do |attempt |
30- wait = BASE_DELAY * ( 2 **attempt - 1 ) # Exponential delay with each subsequent request attempt.
31- wait += rand ( wait + 1 ..wait + MAX_REQUEST_RETRY_JITTER ) # Add jitter to the delay window.
33+ wait = BASE_DELAY * ( 2 **attempt - 1 ) # Exponential delay with each subsequent request attempt.
34+ wait += rand ( wait + 1 ..wait + MAX_REQUEST_RETRY_JITTER ) # Add jitter to the delay window.
3235 wait = [ MAX_REQUEST_RETRY_DELAY , wait ] . min # Cap delay at MAX_REQUEST_RETRY_DELAY.
3336 wait = [ MIN_REQUEST_RETRY_DELAY , wait ] . max # Ensure delay is no less than MIN_REQUEST_RETRY_DELAY.
3437 wait / 1000 . to_f . round ( 2 ) # convert ms to seconds
@@ -55,6 +58,7 @@ def url(path)
5558
5659 def add_headers ( h = { } )
5760 raise ArgumentError , 'Headers must be an object which responds to #to_hash' unless h . respond_to? ( :to_hash )
61+
5862 @headers ||= { }
5963 @headers . merge! ( h . to_hash )
6064 end
@@ -72,36 +76,38 @@ def request_with_retry(method, uri, body = {}, extra_headers = {})
7276 end
7377
7478 def request ( method , uri , body = { } , extra_headers = { } )
75- result = if method == :get
76- @headers ||= { }
77- get_headers = @headers . merge ( { params : body } ) . merge ( extra_headers )
78- call ( :get , encode_uri ( uri ) , timeout , get_headers )
79- elsif method == :delete
80- @headers ||= { }
81- delete_headers = @headers . merge ( { params : body } )
82- call ( :delete , encode_uri ( uri ) , timeout , delete_headers )
83- elsif method == :delete_with_body
84- call ( :delete , encode_uri ( uri ) , timeout , headers , body . to_json )
85- elsif method == :post_file
86- body . merge! ( multipart : true )
87- # Ignore the default Content-Type headers and let the HTTP client define them
88- post_file_headers = headers . except ( 'Content-Type' ) if headers != nil
89- # Actual call with the altered headers
90- call ( :post , encode_uri ( uri ) , timeout , post_file_headers , body )
91- elsif method == :post_form
92- form_post_headers = headers . except ( 'Content-Type' ) if headers != nil
93- call ( :post , encode_uri ( uri ) , timeout , form_post_headers , body . compact )
94- else
95- call ( method , encode_uri ( uri ) , timeout , headers , body . to_json )
96- end
79+ result = case method
80+ when :get
81+ @headers ||= { }
82+ get_headers = @headers . merge ( { params : body } ) . merge ( extra_headers )
83+ call ( :get , encode_uri ( uri ) , timeout , get_headers )
84+ when :delete
85+ @headers ||= { }
86+ delete_headers = @headers . merge ( { params : body } )
87+ call ( :delete , encode_uri ( uri ) , timeout , delete_headers )
88+ when :delete_with_body
89+ call ( :delete , encode_uri ( uri ) , timeout , headers , body . to_json )
90+ when :post_file
91+ body . merge! ( multipart : true )
92+ # Ignore the default Content-Type headers and let the HTTP client define them
93+ post_file_headers = headers . except ( 'Content-Type' ) unless headers . nil?
94+ # Actual call with the altered headers
95+ call ( :post , encode_uri ( uri ) , timeout , post_file_headers , body )
96+ when :post_form
97+ form_post_headers = headers . except ( 'Content-Type' ) unless headers . nil?
98+ call ( :post , encode_uri ( uri ) , timeout , form_post_headers , body . compact )
99+ else
100+ call ( method , encode_uri ( uri ) , timeout , headers , body . to_json )
101+ end
97102
98103 case result . code
99104 when 200 ...226 then safe_parse_json ( result . body )
100105 when 400 then raise Auth0 ::BadRequest . new ( result . body , code : result . code , headers : result . headers )
101106 when 401 then raise Auth0 ::Unauthorized . new ( result . body , code : result . code , headers : result . headers )
102107 when 403 then raise Auth0 ::AccessDenied . new ( result . body , code : result . code , headers : result . headers )
103108 when 404 then raise Auth0 ::NotFound . new ( result . body , code : result . code , headers : result . headers )
104- when 429 then raise Auth0 ::RateLimitEncountered . new ( result . body , code : result . code , headers : result . headers )
109+ when 429 then raise Auth0 ::RateLimitEncountered . new ( result . body , code : result . code ,
110+ headers : result . headers )
105111 when 500 then raise Auth0 ::ServerError . new ( result . body , code : result . code , headers : result . headers )
106112 else raise Auth0 ::Unsupported . new ( result . body , code : result . code , headers : result . headers )
107113 end
@@ -118,11 +124,19 @@ def call(method, url, timeout, headers, body = nil)
118124 rescue RestClient ::Exception => e
119125 case e
120126 when RestClient ::RequestTimeout
121- raise Auth0 ::RequestTimeout . new ( e . message )
127+ raise Auth0 ::RequestTimeout , e . message
122128 else
123- return e . response
129+ e . response
124130 end
125131 end
132+
133+ private
134+
135+ def safe_merge_body ( body , extra = { } )
136+ return body unless body . is_a? ( Hash )
137+ merged = extra . any? ? body . merge ( extra ) : body
138+ merged . compact
139+ end
126140 end
127141 end
128142end
0 commit comments