Skip to content

RFC: Issues with multiple Attack instances in the same process / Rack stack (class ivar binding) #178

Closed
@julik

Description

@julik

I would like to use multiple instances of Rack::Attack in the same Rack stack, but in different places. Each one of these would accept it's own throttles, blacklists etc. Judging from the code, I assumed I could do

 class MyThrottle < Rack::Attack
    throttle(...) do |req|
      ...
    end
 end

It turned out, however, that the method performing the throttling still reaches into the attribute reader of the superclass, and thus finds throttles defined on the parent instance. I think the same is the case for blacklisting and whitelisting, but I don't necessarily need them in this specific application. I was only able to make throttles work in a subclass by doing

 class MyThrottle < Rack::Attack
    ...
    def throttled?(req)
      self.class.throttles.any? do |name, throttle|
        throttle[req]
      end
    end
 end

This stems from the fact that some smart machinery is involved in making the configuration available on the class level. I think that it might make more sense if the same configuration could be applied with, say, options (since block handling with middleware attachment is not that well understood):

 my_attack_config = Rack::Attack::Config.new do |c|
    c.throttle(...) do |req| # etc
      ...
    end
 end
 use Rack::Attack, config: my_attack_config

So I think there was some thought given to separating the various classes' configurations within one Ruby process, but this was not really tested. You could in theory alter the throttled? etc. methods to call into the right class for the variables and consider this a bug, but maybe the API can just be improved and handle this explicitly?

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions