Added throttling, max_content_length, and max_events_per_request - #150
Andrew Kane
committed Mar 07, 2016
commit ec2bb23471af3e4ea7f81253915732f5c404be0e
Showing 7
changed files with
56 additions
and 2 deletions
CHANGELOG.md
+5
-0
| @@ | @@ -1,3 +1,8 @@ |
| + | ## 1.3.0 |
| + | |
| + | - Added throttling |
| + | - Added `max_content_length` and `max_events_per_request` |
| + | |
| ## 1.2.2 | |
| - Fixed issue with latest version of `browser` gem | |
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 "errbase" | |
| + | spec.add_dependency "rack-attack" |
| spec.add_development_dependency "bundler", "~> 1.5" | |
| spec.add_development_dependency "rake" | |
app/controllers/ahoy/base_controller.rb
+11
-0
| @@ | @@ -4,12 +4,23 @@ module Ahoy |
| filters = _process_action_callbacks.map(&:filter) - [:load_authlogic] | |
| if respond_to?(:skip_action) | |
| skip_action *filters | |
| + | before_action :verify_request_size |
| else | |
| skip_filter *filters | |
| + | before_filter :verify_request_size |
| end | |
| + | protected |
| + | |
| def ahoy | |
| @ahoy ||= Ahoy::Tracker.new(controller: self, api: true) | |
| end | |
| + | |
| + | def verify_request_size |
| + | if request.content_length > Ahoy.max_content_length |
| + | logger.info "[ahoy] Payload too large" |
| + | render text: "Payload too large\n", status: 413 |
| + | end |
| + | end |
| end | |
| end | |
app/controllers/ahoy/events_controller.rb
+1
-1
| @@ | @@ -14,7 +14,7 @@ module Ahoy |
| end | |
| end | |
| - | events.each do |event| |
| + | events.first(Ahoy.max_events_per_request).each do |event| |
| time = Time.zone.parse(event["time"]) rescue nil | |
| # timestamp is deprecated | |
ahoy.rb b/lib/ahoy.rb
+15
-0
| @@ | @@ -62,6 +62,21 @@ module Ahoy |
| mattr_accessor :geocode | |
| self.geocode = true | |
| + | mattr_accessor :max_content_length |
| + | self.max_content_length = 8192 |
| + | |
| + | mattr_accessor :max_events_per_request |
| + | self.max_events_per_request = 10 |
| + | |
| + | mattr_accessor :throttle |
| + | self.throttle = true |
| + | |
| + | mattr_accessor :throttle_limit |
| + | self.throttle_limit = 20 |
| + | |
| + | mattr_accessor :throttle_period |
| + | self.throttle_period = 1.minute |
| + | |
| def self.ensure_uuid(id) | |
| valid = UUIDTools::UUID.parse(id) rescue nil | |
| if valid | |
ahoy/engine.rb b/lib/ahoy/engine.rb
+6
-1
| @@ | @@ -1,7 +1,12 @@ |
| module Ahoy | |
| class Engine < ::Rails::Engine | |
| - | initializer "ahoy.middleware", after: "sprockets.environment" do |
| + | initializer "ahoy.middleware", after: "sprockets.environment" do |app| |
| Rails::Rack::Logger.send(:prepend, Ahoy::LogSilencer) if Ahoy.quiet | |
| + | |
| + | if Ahoy.throttle |
| + | require "ahoy/throttle" |
| + | app.middleware.use Ahoy::Throttle |
| + | end |
| end | |
| end | |
| end | |
ahoy/throttle.rb b/lib/ahoy/throttle.rb
+17
-0
| @@ | @@ -0,0 +1,17 @@ |
| + | 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? |
| + | |
| + | def self.throttled_response |
| + | Rack::Attack.throttled_response |
| + | end |
| + | end |
| + | end |