ignore Rack::Timeout middle in specific rails routes

1.6k views Asked by At

I have installed rack-timeout gem and created rack_timeout.rb inside the initializers.I have set Rack::Timeout.service_timeout = 1 inside rack_timeout.rb.I want to restrict the rack-timeout to halt the execution if timeout exceeded in controllers other than controllers inside api.Only the api controllers' execution should be stopped.I have created a custom middleware inside lib named my_middleware.rb

 class MyMiddleware < Rack::Timeout
  def initialize(app, options = {})
    @app = app
    @exclude = options[:exclude]
  end

  def call(env)
    if env['PATH_INFO'].include? "api"
      super(env)
    else
      @app.call(env)
    end
  end
end

config/development.rb

config.middleware.use "MyMiddleware"

but its not working.everywhere rack timeout is throwing the exception when timeout happened.

1

There are 1 answers

0
mkrl On

Very interesting question. It's not a very good practice to timeout your requests outside of whenever they are being executed from, but it seems like there is no other ready-to-go solution.

I went ahead and forked rack_timeout, and added filtering based on request paths, slightly based on your code.

Basically, it extends Rack::Timeout with Select class

class Select < Timeout
  def call(env)
    if exclude_or_any?(env) #checking for parameters passed on init
      super(env)
    else
      @app.call(env)
    end
  end
  ...
end

It is using the original initialize method and accepts 2 additional parameters:

  • exclude: ["paths", "to", "exclude"] - Do not run timeout for requests coming from paths containing strings provided.
  • only: ["only_timeout_this"] - Only process requests with from those paths.

I would not recommend using it on a regular basis since it's better to keep your timeouts within whatever processes your requests, but for the sake of development and simplicity, it should be enough.

More information available in the repo: