Restored throttling after removing side effects

Andrew Kane committed Aug 19, 2016
commit cff7cc19cbbfde834ce67f0affdf1c98777bd32d
Showing 6 changed files with 44 additions and 16 deletions
CHANGELOG.md +4 -0
@@ @@ -1,3 +1,7 @@
+ ## 1.5.1 [unreleased]
+
+ - Restored throttling after removing side effects
+
## 1.5.0
- Removed throttling due to unintended side effects with its implementation
README.md +0 -16
@@ @@ -530,18 +530,6 @@ Send a `POST` request as `Content-Type: application/json` to `/ahoy/events` with
Use an array to pass multiple events at once.
- ## Throttling
-
- To throttle requests to Ahoy endpoints, check out [Rack::Attack](https://github.com/kickstarter/ack-attack). Here’s a sample config:
-
- ```ruby
- Rack::Attack.throttle("ahoy/ip", limit: 20, period: 1.minute) do |req|
- if req.path.start_with?("/ahoy/")
- req.ip
- end
- end
- ```
-
## Reference
By default, Ahoy create endpoints at `/ahoy/visits` and `/ahoy/events`. To disable, use:
@@ @@ -552,10 +540,6 @@ Ahoy.mount = false
## Upgrading
- ### 1.5.0
-
- There’s nothing to do, but it’s worth noting that simple throttling, which was added in `1.3.0`, was removed due to unintended side effects with its implementation. See the [Throttling](#throttling) section for how to properly add it by hand if needed.
-
### 1.4.0
There’s nothing to do, but it’s worth noting the default store was changed from `ActiveRecordStore` to `ActiveRecordTokenStore` for new installations.
ahoy_matey.gemspec +1 -0
@@ @@ -27,6 +27,7 @@ Gem::Specification.new do |spec|
spec.add_dependency "request_store"
spec.add_dependency "uuidtools"
spec.add_dependency "safely_block", ">= 0.1.1"
+ spec.add_dependency "rack-attack", "< 6"
spec.add_development_dependency "bundler", "~> 1.5"
spec.add_development_dependency "rake"
ahoy.rb b/lib/ahoy.rb +9 -0
@@ @@ -72,6 +72,15 @@ module Ahoy
mattr_accessor :mount
self.mount = true
+ mattr_accessor :throttle
+ self.throttle = true
+
+ mattr_accessor :throttle_limit
+ self.throttle_limit = 20
+
+ mattr_accessor :throttle_period
+ self.throttle_period = 1.minute
+
mattr_accessor :job_queue
self.job_queue = :ahoy
ahoy/engine.rb b/lib/ahoy/engine.rb +5 -0
@@ @@ -1,6 +1,11 @@
module Ahoy
class Engine < ::Rails::Engine
initializer "ahoy.middleware", after: "sprockets.environment" do |app|
+ if Ahoy.throttle
+ require "ahoy/throttle"
+ app.middleware.use Ahoy::Throttle
+ end
+
next unless Ahoy.quiet
# Parse PATH_INFO by assets prefix
ahoy/throttle.rb b/lib/ahoy/throttle.rb +25 -0
@@ @@ -0,0 +1,25 @@
+ require "rack/attack"
+
+ module Ahoy
+ class Throttle < Rack::Attack
+ throttle("ahoy/ip", limit: Ahoy.throttle_limit, period: Ahoy.throttle_period) do |req|
+ if req.path.start_with?("/ahoy/")
+ req.ip
+ end
+ end
+
+ def_delegators self, :whitelisted?, :blacklisted?, :throttled?, :tracked?, :blocklisted?, :safelisted?
+
+ def self.throttled_response
+ Rack::Attack.throttled_response
+ end
+
+ def self.blacklisted_response
+ Rack::Attack.blacklisted_response
+ end
+
+ def self.blocklisted_response
+ Rack::Attack.blocklisted_response
+ end
+ end
+ end