auth0 5.4.0 → 5.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +8 -0
- data/auth0.gemspec +1 -0
- data/lib/auth0/mixins/httpproxy.rb +69 -38
- data/lib/auth0/mixins/initializer.rb +1 -0
- data/lib/auth0/version.rb +1 -1
- data/spec/lib/auth0/mixins/httpproxy_spec.rb +189 -0
- data/spec/lib/auth0/mixins/initializer_spec.rb +7 -0
- metadata +16 -2
    
        checksums.yaml
    CHANGED
    
    | @@ -1,7 +1,7 @@ | |
| 1 1 | 
             
            ---
         | 
| 2 2 | 
             
            SHA256:
         | 
| 3 | 
            -
              metadata.gz:  | 
| 4 | 
            -
              data.tar.gz:  | 
| 3 | 
            +
              metadata.gz: a3d59041ebfdd2dfcbc326ea1ea9e416796afd2818607014757d90266ed16c07
         | 
| 4 | 
            +
              data.tar.gz: e9e950591d2027fc475fa437f144dea929a724eeea94bd9491b0a0af5095b271
         | 
| 5 5 | 
             
            SHA512:
         | 
| 6 | 
            -
              metadata.gz:  | 
| 7 | 
            -
              data.tar.gz:  | 
| 6 | 
            +
              metadata.gz: 4f6733b62fa9839d0c03f4a9b641c5f86ffd3a47b7961d76156881f95f34a5ca0cf63c765fccc124418affaca78f34d72e899d5592eddf690f18d4d939b3f9fe
         | 
| 7 | 
            +
              data.tar.gz: b9bf5d5f1e570a595388fbd3555ca23d6964c6a445d150b233f51dd2a19da30ef4a906825567da350a6411adbdee0a2af562953a3034e41f0c714a0ad0a4d04a
         | 
    
        data/CHANGELOG.md
    CHANGED
    
    | @@ -1,5 +1,13 @@ | |
| 1 1 | 
             
            # Change Log
         | 
| 2 2 |  | 
| 3 | 
            +
            ## [v5.5.0](https://github.com/auth0/ruby-auth0/tree/v5.5.0) (2021-08-06)
         | 
| 4 | 
            +
             | 
| 5 | 
            +
            [Full Changelog](https://github.com/auth0/ruby-auth0/compare/v5.4.0..v5.5.0)
         | 
| 6 | 
            +
             | 
| 7 | 
            +
            **Added**
         | 
| 8 | 
            +
             | 
| 9 | 
            +
            - Automatically retry requests when API returns a 429 rate-limit status header. [\#290](https://github.com/auth0/ruby-auth0/pull/290) ([davidpatrick](https://github.com/davidpatrick))
         | 
| 10 | 
            +
             | 
| 3 11 | 
             
            ## [v5.4.0](https://github.com/auth0/ruby-auth0/tree/v5.4.0) (2021-07-23)
         | 
| 4 12 |  | 
| 5 13 | 
             
            [Full Changelog](https://github.com/auth0/ruby-auth0/compare/v5.3.0..v5.4.0)
         | 
    
        data/auth0.gemspec
    CHANGED
    
    | @@ -20,6 +20,7 @@ Gem::Specification.new do |s| | |
| 20 20 | 
             
              s.add_runtime_dependency 'jwt', '~> 2.2'
         | 
| 21 21 | 
             
              s.add_runtime_dependency 'zache', '~> 0.12'
         | 
| 22 22 | 
             
              s.add_runtime_dependency 'addressable', '~> 2.8'
         | 
| 23 | 
            +
              s.add_runtime_dependency 'retryable', '~> 3.0'
         | 
| 23 24 |  | 
| 24 25 | 
             
              s.add_development_dependency 'bundler'
         | 
| 25 26 | 
             
              s.add_development_dependency 'rake', '~> 13.0'
         | 
| @@ -1,56 +1,52 @@ | |
| 1 1 | 
             
            require "addressable/uri"
         | 
| 2 | 
            +
            require "retryable"
         | 
| 3 | 
            +
            require_relative "../exception.rb"
         | 
| 2 4 |  | 
| 3 5 | 
             
            module Auth0
         | 
| 4 6 | 
             
              module Mixins
         | 
| 5 7 | 
             
                # here's the proxy for Rest calls based on rest-client, we're building all request on that gem
         | 
| 6 8 | 
             
                # for now, if you want to feel free to use your own http client
         | 
| 7 9 | 
             
                module HTTPProxy
         | 
| 8 | 
            -
                  attr_accessor :headers, :base_uri, :timeout
         | 
| 10 | 
            +
                  attr_accessor :headers, :base_uri, :timeout, :retry_count
         | 
| 11 | 
            +
                  DEAFULT_RETRIES = 3
         | 
| 12 | 
            +
                  MAX_ALLOWED_RETRIES = 10
         | 
| 13 | 
            +
                  MAX_REQUEST_RETRY_JITTER = 250
         | 
| 14 | 
            +
                  MAX_REQUEST_RETRY_DELAY = 1000
         | 
| 15 | 
            +
                  MIN_REQUEST_RETRY_DELAY = 100
         | 
| 9 16 |  | 
| 10 17 | 
             
                  # proxying requests from instance methods to HTTP class methods
         | 
| 11 18 | 
             
                  %i(get post post_file put patch delete delete_with_body).each do |method|
         | 
| 12 19 | 
             
                    define_method(method) do |uri, body = {}, extra_headers = {}|
         | 
| 20 | 
            +
                      body = body.delete_if { |_, v| v.nil? }
         | 
| 13 21 |  | 
| 14 | 
            -
                       | 
| 15 | 
            -
                         | 
| 16 | 
            -
                        safe_path = Addressable::URI.new(path: uri).normalized_path
         | 
| 17 | 
            -
                      else
         | 
| 18 | 
            -
                        safe_path = Addressable::URI.escape(uri)
         | 
| 22 | 
            +
                      Retryable.retryable(retry_options) do
         | 
| 23 | 
            +
                        request(method, uri, body, extra_headers)
         | 
| 19 24 | 
             
                      end
         | 
| 25 | 
            +
                    end
         | 
| 26 | 
            +
                  end
         | 
| 20 27 |  | 
| 21 | 
            -
             | 
| 22 | 
            -
             | 
| 23 | 
            -
             | 
| 24 | 
            -
             | 
| 25 | 
            -
             | 
| 26 | 
            -
             | 
| 27 | 
            -
             | 
| 28 | 
            -
                                 # Make the call with extra_headers, if provided.
         | 
| 29 | 
            -
                                 call(:get, url(safe_path), timeout, get_headers)
         | 
| 30 | 
            -
                               elsif method == :delete
         | 
| 31 | 
            -
                                 call(:delete, url(safe_path), timeout, add_headers({params: body}))
         | 
| 32 | 
            -
                               elsif method == :delete_with_body
         | 
| 33 | 
            -
                                 call(:delete, url(safe_path), timeout, headers, body.to_json)
         | 
| 34 | 
            -
                               elsif method == :post_file
         | 
| 35 | 
            -
                                 body.merge!(multipart: true)
         | 
| 36 | 
            -
                                 # Ignore the default Content-Type headers and let the HTTP client define them
         | 
| 37 | 
            -
                                 post_file_headers = headers.slice(*headers.keys - ['Content-Type'])
         | 
| 38 | 
            -
                                 # Actual call with the altered headers
         | 
| 39 | 
            -
                                 call(:post, url(safe_path), timeout, post_file_headers, body)
         | 
| 40 | 
            -
                               else
         | 
| 41 | 
            -
                                 call(method, url(safe_path), timeout, headers, body.to_json)
         | 
| 42 | 
            -
                               end
         | 
| 43 | 
            -
                      case result.code
         | 
| 44 | 
            -
                      when 200...226 then safe_parse_json(result.body)
         | 
| 45 | 
            -
                      when 400       then raise Auth0::BadRequest.new(result.body, code: result.code, headers: result.headers)
         | 
| 46 | 
            -
                      when 401       then raise Auth0::Unauthorized.new(result.body, code: result.code, headers: result.headers)
         | 
| 47 | 
            -
                      when 403       then raise Auth0::AccessDenied.new(result.body, code: result.code, headers: result.headers)
         | 
| 48 | 
            -
                      when 404       then raise Auth0::NotFound.new(result.body, code: result.code, headers: result.headers)
         | 
| 49 | 
            -
                      when 429       then raise Auth0::RateLimitEncountered.new(result.body, code: result.code, headers: result.headers)
         | 
| 50 | 
            -
                      when 500       then raise Auth0::ServerError.new(result.body, code: result.code, headers: result.headers)
         | 
| 51 | 
            -
                      else                raise Auth0::Unsupported.new(result.body, code: result.code, headers: result.headers)
         | 
| 52 | 
            -
                      end
         | 
| 28 | 
            +
                  def retry_options
         | 
| 29 | 
            +
                    sleep_timer = lambda do |attempt|
         | 
| 30 | 
            +
                      wait = 1000 * 2**attempt # Exponential delay with each subsequent request attempt.
         | 
| 31 | 
            +
                      wait += rand(wait..wait+MAX_REQUEST_RETRY_JITTER) # Add jitter to the delay window.
         | 
| 32 | 
            +
                      wait = [MAX_REQUEST_RETRY_DELAY, wait].min # Cap delay at MAX_REQUEST_RETRY_DELAY.
         | 
| 33 | 
            +
                      wait = [MIN_REQUEST_RETRY_DELAY, wait].max # Ensure delay is no less than MIN_REQUEST_RETRY_DELAY.
         | 
| 34 | 
            +
                      wait / 1000.to_f.round(2) # convert ms to seconds
         | 
| 53 35 | 
             
                    end
         | 
| 36 | 
            +
             | 
| 37 | 
            +
                    tries = 1 + [Integer(retry_count || DEAFULT_RETRIES), MAX_ALLOWED_RETRIES].min # Cap retries at MAX_ALLOWED_RETRIES
         | 
| 38 | 
            +
             | 
| 39 | 
            +
                    {
         | 
| 40 | 
            +
                      tries: tries,
         | 
| 41 | 
            +
                      sleep: sleep_timer,
         | 
| 42 | 
            +
                      on: Auth0::RateLimitEncountered
         | 
| 43 | 
            +
                    }
         | 
| 44 | 
            +
                  end
         | 
| 45 | 
            +
             | 
| 46 | 
            +
                  def encode_uri(uri)
         | 
| 47 | 
            +
                    # if a base_uri is set then the uri can be encoded as a path
         | 
| 48 | 
            +
                    path = base_uri ? Addressable::URI.new(path: uri).normalized_path : Addressable::URI.escape(uri)
         | 
| 49 | 
            +
                    url(path)
         | 
| 54 50 | 
             
                  end
         | 
| 55 51 |  | 
| 56 52 | 
             
                  def url(path)
         | 
| @@ -69,6 +65,41 @@ module Auth0 | |
| 69 65 | 
             
                    body
         | 
| 70 66 | 
             
                  end
         | 
| 71 67 |  | 
| 68 | 
            +
                  def request(method, uri, body, extra_headers)
         | 
| 69 | 
            +
                    result = if method == :get
         | 
| 70 | 
            +
                      # Mutate the headers property to add parameters.
         | 
| 71 | 
            +
                      add_headers({params: body})
         | 
| 72 | 
            +
                      # Merge custom headers into existing ones for this req.
         | 
| 73 | 
            +
                      # This prevents future calls from using them.
         | 
| 74 | 
            +
                      get_headers = headers.merge extra_headers
         | 
| 75 | 
            +
                      # Make the call with extra_headers, if provided.
         | 
| 76 | 
            +
                      call(:get, encode_uri(uri), timeout, get_headers)
         | 
| 77 | 
            +
                    elsif method == :delete
         | 
| 78 | 
            +
                      call(:delete, encode_uri(uri), timeout, add_headers({params: body}))
         | 
| 79 | 
            +
                    elsif method == :delete_with_body
         | 
| 80 | 
            +
                      call(:delete, encode_uri(uri), timeout, headers, body.to_json)
         | 
| 81 | 
            +
                    elsif method == :post_file
         | 
| 82 | 
            +
                      body.merge!(multipart: true)
         | 
| 83 | 
            +
                      # Ignore the default Content-Type headers and let the HTTP client define them
         | 
| 84 | 
            +
                      post_file_headers = headers.slice(*headers.keys - ['Content-Type'])
         | 
| 85 | 
            +
                      # Actual call with the altered headers
         | 
| 86 | 
            +
                      call(:post, encode_uri(uri), timeout, post_file_headers, body)
         | 
| 87 | 
            +
                    else
         | 
| 88 | 
            +
                      call(method, encode_uri(uri), timeout, headers, body.to_json)
         | 
| 89 | 
            +
                    end
         | 
| 90 | 
            +
             | 
| 91 | 
            +
                    case result.code
         | 
| 92 | 
            +
                    when 200...226 then safe_parse_json(result.body)
         | 
| 93 | 
            +
                    when 400       then raise Auth0::BadRequest.new(result.body, code: result.code, headers: result.headers)
         | 
| 94 | 
            +
                    when 401       then raise Auth0::Unauthorized.new(result.body, code: result.code, headers: result.headers)
         | 
| 95 | 
            +
                    when 403       then raise Auth0::AccessDenied.new(result.body, code: result.code, headers: result.headers)
         | 
| 96 | 
            +
                    when 404       then raise Auth0::NotFound.new(result.body, code: result.code, headers: result.headers)
         | 
| 97 | 
            +
                    when 429       then raise Auth0::RateLimitEncountered.new(result.body, code: result.code, headers: result.headers)
         | 
| 98 | 
            +
                    when 500       then raise Auth0::ServerError.new(result.body, code: result.code, headers: result.headers)
         | 
| 99 | 
            +
                    else           raise Auth0::Unsupported.new(result.body, code: result.code, headers: result.headers)
         | 
| 100 | 
            +
                    end
         | 
| 101 | 
            +
                  end
         | 
| 102 | 
            +
             | 
| 72 103 | 
             
                  def call(method, url, timeout, headers, body = nil)
         | 
| 73 104 | 
             
                    RestClient::Request.execute(
         | 
| 74 105 | 
             
                      method: method,
         | 
| @@ -15,6 +15,7 @@ module Auth0 | |
| 15 15 | 
             
                    @base_uri = base_url(options)
         | 
| 16 16 | 
             
                    @headers = client_headers
         | 
| 17 17 | 
             
                    @timeout = options[:timeout] || 10
         | 
| 18 | 
            +
                    @retry_count = options[:retry_count]
         | 
| 18 19 | 
             
                    extend Auth0::Api::AuthenticationEndpoints
         | 
| 19 20 | 
             
                    @client_id = options[:client_id]
         | 
| 20 21 | 
             
                    @client_secret = options[:client_secret]
         | 
    
        data/lib/auth0/version.rb
    CHANGED
    
    
| @@ -6,6 +6,7 @@ describe Auth0::Mixins::HTTPProxy do | |
| 6 6 | 
             
                dummy_instance = DummyClassForProxy.new
         | 
| 7 7 | 
             
                dummy_instance.extend(Auth0::Mixins::HTTPProxy)
         | 
| 8 8 | 
             
                dummy_instance.base_uri = "https://auth0.com"
         | 
| 9 | 
            +
                dummy_instance.retry_count = 0
         | 
| 9 10 |  | 
| 10 11 | 
             
                @instance = dummy_instance
         | 
| 11 12 | 
             
                @exception = DummyClassForRestClient.new
         | 
| @@ -152,6 +153,100 @@ describe Auth0::Mixins::HTTPProxy do | |
| 152 153 | 
             
                      .and_return(StubResponse.new({}, true, 200))
         | 
| 153 154 | 
             
                    expect { @instance.send(http_method, '/te st#test') }.not_to raise_error
         | 
| 154 155 | 
             
                  end
         | 
| 156 | 
            +
             | 
| 157 | 
            +
                  context "when status 429 is recieved on send http #{http_method} method" do
         | 
| 158 | 
            +
                    it "should retry 3 times when retry_count is not set" do
         | 
| 159 | 
            +
                      retry_instance = DummyClassForProxy.new
         | 
| 160 | 
            +
                      retry_instance.extend(Auth0::Mixins::HTTPProxy)
         | 
| 161 | 
            +
                      retry_instance.base_uri = "https://auth0.com"
         | 
| 162 | 
            +
             | 
| 163 | 
            +
                      @exception.response = StubResponse.new({}, false, 429)
         | 
| 164 | 
            +
                      allow(RestClient::Request).to receive(:execute).with(method: http_method,
         | 
| 165 | 
            +
                                                                          url: 'https://auth0.com/test',
         | 
| 166 | 
            +
                                                                          timeout: nil,
         | 
| 167 | 
            +
                                                                          headers: { params: {} },
         | 
| 168 | 
            +
                                                                          payload: nil)
         | 
| 169 | 
            +
                        .and_raise(@exception)
         | 
| 170 | 
            +
                      expect(RestClient::Request).to receive(:execute).exactly(4).times
         | 
| 171 | 
            +
             | 
| 172 | 
            +
                      expect { retry_instance.send(http_method, '/test') }.to raise_error { |error|
         | 
| 173 | 
            +
                        expect(error).to be_a(Auth0::RateLimitEncountered)
         | 
| 174 | 
            +
                      }
         | 
| 175 | 
            +
                    end
         | 
| 176 | 
            +
             | 
| 177 | 
            +
                    it "should retry 2 times when retry_count is set to 2" do
         | 
| 178 | 
            +
                      retry_instance = DummyClassForProxy.new
         | 
| 179 | 
            +
                      retry_instance.extend(Auth0::Mixins::HTTPProxy)
         | 
| 180 | 
            +
                      retry_instance.base_uri = "https://auth0.com"
         | 
| 181 | 
            +
                      retry_instance.retry_count = 2
         | 
| 182 | 
            +
             | 
| 183 | 
            +
                      @exception.response = StubResponse.new({}, false, 429)
         | 
| 184 | 
            +
                      allow(RestClient::Request).to receive(:execute).with(method: http_method,
         | 
| 185 | 
            +
                                                                          url: 'https://auth0.com/test',
         | 
| 186 | 
            +
                                                                          timeout: nil,
         | 
| 187 | 
            +
                                                                          headers: { params: {} },
         | 
| 188 | 
            +
                                                                          payload: nil)
         | 
| 189 | 
            +
                        .and_raise(@exception)
         | 
| 190 | 
            +
                      expect(RestClient::Request).to receive(:execute).exactly(3).times
         | 
| 191 | 
            +
             | 
| 192 | 
            +
                      expect { retry_instance.send(http_method, '/test') }.to raise_error { |error|
         | 
| 193 | 
            +
                        expect(error).to be_a(Auth0::RateLimitEncountered)
         | 
| 194 | 
            +
                      }
         | 
| 195 | 
            +
                    end
         | 
| 196 | 
            +
             | 
| 197 | 
            +
                    it "should not retry when retry_count is set to 0" do
         | 
| 198 | 
            +
                      retry_instance = DummyClassForProxy.new
         | 
| 199 | 
            +
                      retry_instance.extend(Auth0::Mixins::HTTPProxy)
         | 
| 200 | 
            +
                      retry_instance.base_uri = "https://auth0.com"
         | 
| 201 | 
            +
                      retry_instance.retry_count = 0
         | 
| 202 | 
            +
             | 
| 203 | 
            +
                      @exception.response = StubResponse.new({}, false, 429)
         | 
| 204 | 
            +
             | 
| 205 | 
            +
                      allow(RestClient::Request).to receive(:execute).with(method: http_method,
         | 
| 206 | 
            +
                                                                          url: 'https://auth0.com/test',
         | 
| 207 | 
            +
                                                                          timeout: nil,
         | 
| 208 | 
            +
                                                                          headers: { params: {} },
         | 
| 209 | 
            +
                                                                          payload: nil)
         | 
| 210 | 
            +
                        .and_raise(@exception)
         | 
| 211 | 
            +
                      
         | 
| 212 | 
            +
                      expect(RestClient::Request).to receive(:execute).exactly(1).times
         | 
| 213 | 
            +
                      expect { retry_instance.send(http_method, '/test') }.to raise_error { |error|
         | 
| 214 | 
            +
                        expect(error).to be_a(Auth0::RateLimitEncountered)
         | 
| 215 | 
            +
                      }
         | 
| 216 | 
            +
                    end
         | 
| 217 | 
            +
             | 
| 218 | 
            +
                    it "should have have random retry times grow with jitter backoff" do
         | 
| 219 | 
            +
                      retry_instance = DummyClassForProxy.new
         | 
| 220 | 
            +
                      retry_instance.extend(Auth0::Mixins::HTTPProxy)
         | 
| 221 | 
            +
                      retry_instance.base_uri = "https://auth0.com"
         | 
| 222 | 
            +
                      retry_instance.retry_count = 2
         | 
| 223 | 
            +
                      time_entries = []
         | 
| 224 | 
            +
                      @time_start
         | 
| 225 | 
            +
             | 
| 226 | 
            +
                      @exception.response = StubResponse.new({}, false, 429)
         | 
| 227 | 
            +
                      allow(RestClient::Request).to receive(:execute).with(method: http_method,
         | 
| 228 | 
            +
                                                                           url: 'https://auth0.com/test',
         | 
| 229 | 
            +
                                                                           timeout: nil,
         | 
| 230 | 
            +
                                                                           headers: { params: {} },
         | 
| 231 | 
            +
                                                                           payload: nil) do
         | 
| 232 | 
            +
             | 
| 233 | 
            +
                        time_entries.push(Time.now.to_f - @time_start.to_f)
         | 
| 234 | 
            +
                        @time_start = Time.now.to_f # restart the clock
         | 
| 235 | 
            +
                        raise @exception
         | 
| 236 | 
            +
                      end
         | 
| 237 | 
            +
             | 
| 238 | 
            +
                      @time_start = Time.now.to_f #start the clock
         | 
| 239 | 
            +
                      retry_instance.send(http_method, '/test') rescue nil
         | 
| 240 | 
            +
                      time_entries_first_set = time_entries.shift(time_entries.length)
         | 
| 241 | 
            +
             | 
| 242 | 
            +
                      retry_instance.send(http_method, '/test') rescue nil
         | 
| 243 | 
            +
                      time_entries.each_with_index do |entry, index|
         | 
| 244 | 
            +
                        if index > 0 #skip the first request
         | 
| 245 | 
            +
                          expect(entry != time_entries_first_set[index])
         | 
| 246 | 
            +
                        end
         | 
| 247 | 
            +
                      end
         | 
| 248 | 
            +
                    end
         | 
| 249 | 
            +
                  end
         | 
| 155 250 | 
             
                end
         | 
| 156 251 | 
             
              end
         | 
| 157 252 |  | 
| @@ -301,6 +396,100 @@ describe Auth0::Mixins::HTTPProxy do | |
| 301 396 | 
             
                      .and_return(StubResponse.new(res, true, 404))
         | 
| 302 397 | 
             
                    expect { @instance.send(http_method, '/test') }.to raise_error(Auth0::NotFound, res)
         | 
| 303 398 | 
             
                  end
         | 
| 399 | 
            +
             | 
| 400 | 
            +
                  context "when status 429 is recieved on send http #{http_method} method" do
         | 
| 401 | 
            +
                    it "should retry 3 times when retry_count is not set" do
         | 
| 402 | 
            +
                      retry_instance = DummyClassForProxy.new
         | 
| 403 | 
            +
                      retry_instance.extend(Auth0::Mixins::HTTPProxy)
         | 
| 404 | 
            +
                      retry_instance.base_uri = "https://auth0.com"
         | 
| 405 | 
            +
             | 
| 406 | 
            +
                      @exception.response = StubResponse.new({}, false, 429)
         | 
| 407 | 
            +
                      allow(RestClient::Request).to receive(:execute).with(method: http_method,
         | 
| 408 | 
            +
                                                                          url: 'https://auth0.com/test',
         | 
| 409 | 
            +
                                                                          timeout: nil,
         | 
| 410 | 
            +
                                                                          headers: nil,
         | 
| 411 | 
            +
                                                                          payload: '{}')
         | 
| 412 | 
            +
                        .and_raise(@exception)
         | 
| 413 | 
            +
                      expect(RestClient::Request).to receive(:execute).exactly(4).times
         | 
| 414 | 
            +
             | 
| 415 | 
            +
                      expect { retry_instance.send(http_method, '/test') }.to raise_error { |error|
         | 
| 416 | 
            +
                        expect(error).to be_a(Auth0::RateLimitEncountered)
         | 
| 417 | 
            +
                      }
         | 
| 418 | 
            +
                    end
         | 
| 419 | 
            +
             | 
| 420 | 
            +
                    it "should retry 2 times when retry_count is set to 2" do
         | 
| 421 | 
            +
                      retry_instance = DummyClassForProxy.new
         | 
| 422 | 
            +
                      retry_instance.extend(Auth0::Mixins::HTTPProxy)
         | 
| 423 | 
            +
                      retry_instance.base_uri = "https://auth0.com"
         | 
| 424 | 
            +
                      retry_instance.retry_count = 2
         | 
| 425 | 
            +
             | 
| 426 | 
            +
                      @exception.response = StubResponse.new({}, false, 429)
         | 
| 427 | 
            +
                      allow(RestClient::Request).to receive(:execute).with(method: http_method,
         | 
| 428 | 
            +
                                                                          url: 'https://auth0.com/test',
         | 
| 429 | 
            +
                                                                          timeout: nil,
         | 
| 430 | 
            +
                                                                          headers: nil,
         | 
| 431 | 
            +
                                                                          payload: '{}')
         | 
| 432 | 
            +
                        .and_raise(@exception)
         | 
| 433 | 
            +
                      expect(RestClient::Request).to receive(:execute).exactly(3).times
         | 
| 434 | 
            +
             | 
| 435 | 
            +
                      expect { retry_instance.send(http_method, '/test') }.to raise_error { |error|
         | 
| 436 | 
            +
                        expect(error).to be_a(Auth0::RateLimitEncountered)
         | 
| 437 | 
            +
                      }
         | 
| 438 | 
            +
                    end
         | 
| 439 | 
            +
             | 
| 440 | 
            +
                    it "should not retry when retry_count is set to 0" do
         | 
| 441 | 
            +
                      retry_instance = DummyClassForProxy.new
         | 
| 442 | 
            +
                      retry_instance.extend(Auth0::Mixins::HTTPProxy)
         | 
| 443 | 
            +
                      retry_instance.base_uri = "https://auth0.com"
         | 
| 444 | 
            +
                      retry_instance.retry_count = 0
         | 
| 445 | 
            +
             | 
| 446 | 
            +
                      @exception.response = StubResponse.new({}, false, 429)
         | 
| 447 | 
            +
             | 
| 448 | 
            +
                      allow(RestClient::Request).to receive(:execute).with(method: http_method,
         | 
| 449 | 
            +
                                                                          url: 'https://auth0.com/test',
         | 
| 450 | 
            +
                                                                          timeout: nil,
         | 
| 451 | 
            +
                                                                          headers: nil,
         | 
| 452 | 
            +
                                                                          payload: '{}')
         | 
| 453 | 
            +
                        .and_raise(@exception)
         | 
| 454 | 
            +
                      
         | 
| 455 | 
            +
                      expect(RestClient::Request).to receive(:execute).exactly(1).times
         | 
| 456 | 
            +
                      expect { retry_instance.send(http_method, '/test') }.to raise_error { |error|
         | 
| 457 | 
            +
                        expect(error).to be_a(Auth0::RateLimitEncountered)
         | 
| 458 | 
            +
                      }
         | 
| 459 | 
            +
                    end
         | 
| 460 | 
            +
             | 
| 461 | 
            +
                    it "should have have random retry times grow with jitter backoff" do
         | 
| 462 | 
            +
                      retry_instance = DummyClassForProxy.new
         | 
| 463 | 
            +
                      retry_instance.extend(Auth0::Mixins::HTTPProxy)
         | 
| 464 | 
            +
                      retry_instance.base_uri = "https://auth0.com"
         | 
| 465 | 
            +
                      retry_instance.retry_count = 2
         | 
| 466 | 
            +
                      time_entries = []
         | 
| 467 | 
            +
                      @time_start
         | 
| 468 | 
            +
             | 
| 469 | 
            +
                      @exception.response = StubResponse.new({}, false, 429)
         | 
| 470 | 
            +
                      allow(RestClient::Request).to receive(:execute).with(method: http_method,
         | 
| 471 | 
            +
                                                                           url: 'https://auth0.com/test',
         | 
| 472 | 
            +
                                                                           timeout: nil,
         | 
| 473 | 
            +
                                                                           headers: nil,
         | 
| 474 | 
            +
                                                                           payload: '{}') do
         | 
| 475 | 
            +
             | 
| 476 | 
            +
                        time_entries.push(Time.now.to_f - @time_start.to_f)
         | 
| 477 | 
            +
                        @time_start = Time.now.to_f # restart the clock
         | 
| 478 | 
            +
                        raise @exception
         | 
| 479 | 
            +
                      end
         | 
| 480 | 
            +
             | 
| 481 | 
            +
                      @time_start = Time.now.to_f #start the clock
         | 
| 482 | 
            +
                      retry_instance.send(http_method, '/test') rescue nil
         | 
| 483 | 
            +
                      time_entries_first_set = time_entries.shift(time_entries.length)
         | 
| 484 | 
            +
             | 
| 485 | 
            +
                      retry_instance.send(http_method, '/test') rescue nil
         | 
| 486 | 
            +
                      time_entries.each_with_index do |entry, index|
         | 
| 487 | 
            +
                        if index > 0 #skip the first request
         | 
| 488 | 
            +
                          expect(entry != time_entries_first_set[index])
         | 
| 489 | 
            +
                        end
         | 
| 490 | 
            +
                      end
         | 
| 491 | 
            +
                    end
         | 
| 492 | 
            +
                  end
         | 
| 304 493 | 
             
                end
         | 
| 305 494 | 
             
              end
         | 
| 306 495 | 
             
            end
         | 
| @@ -26,5 +26,12 @@ describe Auth0::Mixins::Initializer do | |
| 26 26 |  | 
| 27 27 | 
             
                  expect(instance.instance_variable_get('@token')).to eq('123')
         | 
| 28 28 | 
             
                end
         | 
| 29 | 
            +
             | 
| 30 | 
            +
                it 'sets retry_count when passed' do
         | 
| 31 | 
            +
                  params[:token] = '123'
         | 
| 32 | 
            +
                  params[:retry_count] = 10
         | 
| 33 | 
            +
             | 
| 34 | 
            +
                  expect(instance.instance_variable_get('@retry_count')).to eq(10)
         | 
| 35 | 
            +
                end
         | 
| 29 36 | 
             
              end
         | 
| 30 37 | 
             
            end
         | 
    
        metadata
    CHANGED
    
    | @@ -1,7 +1,7 @@ | |
| 1 1 | 
             
            --- !ruby/object:Gem::Specification
         | 
| 2 2 | 
             
            name: auth0
         | 
| 3 3 | 
             
            version: !ruby/object:Gem::Version
         | 
| 4 | 
            -
              version: 5. | 
| 4 | 
            +
              version: 5.5.0
         | 
| 5 5 | 
             
            platform: ruby
         | 
| 6 6 | 
             
            authors:
         | 
| 7 7 | 
             
            - Auth0
         | 
| @@ -11,7 +11,7 @@ authors: | |
| 11 11 | 
             
            autorequire:
         | 
| 12 12 | 
             
            bindir: bin
         | 
| 13 13 | 
             
            cert_chain: []
         | 
| 14 | 
            -
            date: 2021-07 | 
| 14 | 
            +
            date: 2021-08-07 00:00:00.000000000 Z
         | 
| 15 15 | 
             
            dependencies:
         | 
| 16 16 | 
             
            - !ruby/object:Gem::Dependency
         | 
| 17 17 | 
             
              name: rest-client
         | 
| @@ -69,6 +69,20 @@ dependencies: | |
| 69 69 | 
             
                - - "~>"
         | 
| 70 70 | 
             
                  - !ruby/object:Gem::Version
         | 
| 71 71 | 
             
                    version: '2.8'
         | 
| 72 | 
            +
            - !ruby/object:Gem::Dependency
         | 
| 73 | 
            +
              name: retryable
         | 
| 74 | 
            +
              requirement: !ruby/object:Gem::Requirement
         | 
| 75 | 
            +
                requirements:
         | 
| 76 | 
            +
                - - "~>"
         | 
| 77 | 
            +
                  - !ruby/object:Gem::Version
         | 
| 78 | 
            +
                    version: '3.0'
         | 
| 79 | 
            +
              type: :runtime
         | 
| 80 | 
            +
              prerelease: false
         | 
| 81 | 
            +
              version_requirements: !ruby/object:Gem::Requirement
         | 
| 82 | 
            +
                requirements:
         | 
| 83 | 
            +
                - - "~>"
         | 
| 84 | 
            +
                  - !ruby/object:Gem::Version
         | 
| 85 | 
            +
                    version: '3.0'
         | 
| 72 86 | 
             
            - !ruby/object:Gem::Dependency
         | 
| 73 87 | 
             
              name: bundler
         | 
| 74 88 | 
             
              requirement: !ruby/object:Gem::Requirement
         |