Skip to content
Closed
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 13 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,19 @@ parameters take precedence:
use Rack::Timeout, service_timeout: 15, wait_timeout: 30
```

```ruby
# config/initializers/rack_timeout.rb

# pass the conditional variables as a proc object
Rails.application.config.middleware.insert_before(
Rack::Runtime,
Rack::Timeout,
service_timeout: ->(ENV) {
ENV['DEV'] || ENV['ADMIN']] || ENV.fetch('DEV_TIMEOUT', 15).to_i
}
)
```

For more on these settings, please see [doc/settings](doc/settings.md).

Further Documentation
Expand Down
20 changes: 20 additions & 0 deletions lib/rack/timeout/core.rb
Original file line number Diff line number Diff line change
Expand Up @@ -53,12 +53,27 @@ def read_timeout_property value, default
when nil ; read_timeout_property default, default
when false ; false
when 0 ; false
when Proc
value
when String
read_timeout_property value.to_i, default
else
value.is_a?(Numeric) && value > 0 or raise ArgumentError, "value #{value.inspect} should be false, zero, or a positive number."
value
end
end

# New helper: if +value+ is a Proc, then it will be called with +*args+ and
# the result returned. Otherwise, the +value+ is returned as is.
def proc_or_value(value, *args)
case value
when Proc
value.call(*args)
else
value
end
end

attr_reader \
:service_timeout, # How long the application can take to complete handling the request once it's passed down to it.
:wait_timeout, # How long the request is allowed to have waited before reaching rack. If exceeded, the request is 'expired', i.e. dropped entirely without being passed down to the application.
Expand Down Expand Up @@ -86,6 +101,11 @@ def initialize(app, service_timeout:nil, wait_timeout:nil, wait_overtime:nil, se
@app = app
end

# Overriding attribute readers to evaluate Procs
def service_timeout; proc_or_value(@service_timeout, @env); end
def wait_timeout; proc_or_value(@wait_timeout, @env); end
def wait_overtime; proc_or_value(@wait_overtime, @env); end
def service_past_wait; proc_or_value(@service_past_wait, @env); end

RT = self # shorthand reference
def call(env)
Expand Down
7 changes: 7 additions & 0 deletions test/basic_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,13 @@ def test_timeout
end
end

def test_timeout_with_proc
self.settings = { service_timeout: proc { 5 } }
assert_raises(Rack::Timeout::RequestTimeoutError) do
get "/sleep"
end
end

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would also be nice to have tests that do something different based on the env parameter to #call


def test_wait_timeout
self.settings = { service_timeout: 1, wait_timeout: 15 }
assert_raises(Rack::Timeout::RequestExpiryError) do
Expand Down