class Fbe::Middleware::RateLimit

License
MIT
Copyright
Copyright © 2024-2025 Zerocracy
Author

Yegor Bugayenko (yegor256@gmail.com)
end
f.use Fbe::Middleware::RateLimit
connection = Faraday.new do |f|
@example Usage in Faraday middleware stack
by allowing the request to pass through to the GitHub API.
it for each API call. Every 100 requests, it refreshes the cached data
the results locally. It tracks the remaining requests count and decrements
This middleware intercepts calls to the /rate_limit endpoint and caches
Faraday middleware that caches GitHub API rate limit information.

def call(env)

Returns:
  • (Faraday::Response) - The response from cache or the next middleware

Parameters:
  • env (Faraday::Env) -- The request environment
def call(env)
  if env.url.path == '/rate_limit'
    handle_rate_limit_request(env)
  else
    track_request
    @app.call(env)
  end
end

def extract_remaining_count(response)

Returns:
  • (Integer) - The remaining requests count

Parameters:
  • response (Faraday::Response) -- The API response
def extract_remaining_count(response)
  body = response.body
  if body.is_a?(String)
    begin
      body = JSON.parse(body)
    rescue JSON::ParserError
      return 0
    end
  end
  return 0 unless body.is_a?(Hash)
  body.dig('rate', 'remaining') || 0
end

def handle_rate_limit_request(env)

Returns:
  • (Faraday::Response) - Cached or fresh response

Parameters:
  • env (Faraday::Env) -- The request environment
def handle_rate_limit_request(env)
  if @cached_response.nil? || @request_counter >= 100
    response = @app.call(env)
    @cached_response = response.dup
    @remaining_count = extract_remaining_count(response)
    @request_counter = 0
    response
  else
    response = @cached_response.dup
    update_remaining_count(response)
    Faraday::Response.new(response_env(env, response))
  end
end

def initialize(app)

Parameters:
  • app (Object) -- The next middleware in the stack
def initialize(app)
  super
  @cached_response = nil
  @remaining_count = nil
  @request_counter = 0
end

def response_env(env, response)

Returns:
  • (Hash) - Response environment hash

Parameters:
  • response (Faraday::Response) -- The cached response
  • env (Faraday::Env) -- The original request environment
def response_env(env, response)
  headers = response.headers.dup
  headers['x-ratelimit-remaining'] = @remaining_count.to_s if @remaining_count
  {
    method: env.method,
    url: env.url,
    request_headers: env.request_headers,
    request_body: env.request_body,
    status: response.status,
    response_headers: headers,
    body: response.body
  }
end

def track_request

Tracks non-rate_limit requests and decrements counter.
def track_request
  return if @remaining_count.nil?
  @remaining_count -= 1 if @remaining_count.positive?
  @request_counter += 1
end

def update_remaining_count(response)

Parameters:
  • response (Faraday::Response) -- The cached response to update
def update_remaining_count(response)
  body = response.body
  original_was_string = body.is_a?(String)
  if original_was_string
    begin
      body = JSON.parse(body)
    rescue JSON::ParserError
      return
    end
  end
  return unless body.is_a?(Hash) && body['rate']
  body['rate']['remaining'] = @remaining_count
  return unless original_was_string
  response.instance_variable_set(:@body, body.to_json)
end