Class: Deflectable::Watcher
- Inherits:
-
Object
- Object
- Deflectable::Watcher
- Defined in:
- lib/deflectable/watcher.rb
Instance Attribute Summary collapse
-
#options ⇒ Object
Returns the value of attribute options.
Instance Method Summary collapse
- #block! ⇒ Object
- #block_expired? ⇒ Boolean
- #blocked? ⇒ Boolean
- #call(env) ⇒ Object
- #clear! ⇒ Object
- #detect?(env) ⇒ Boolean
- #exceeded_request_threshold? ⇒ Boolean
- #increment_requests ⇒ Object
-
#initialize(app, options = {}) ⇒ Watcher
constructor
A new instance of Watcher.
- #log(message) ⇒ Object
- #map ⇒ Object
- #reject! ⇒ Object
- #watch ⇒ Object
- #watch_expired? ⇒ Boolean
- #watching? ⇒ Boolean
Constructor Details
#initialize(app, options = {}) ⇒ Watcher
Returns a new instance of Watcher.
7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
# File 'lib/deflectable/watcher.rb', line 7 def initialize(app, = {}) @mutex = Mutex.new @app = app conf = YAML.load_file(Rails.root.join('config/deflect.yml')) rescue {} = { :log => true, :log_format => 'deflect(%s): %s', :log_date_format => '%m/%d/%Y', :request_threshold => 100, :interval => 5, :block_duration => 900, :whitelist => [], :blacklist => [], }.merge(conf) end |
Instance Attribute Details
#options ⇒ Object
Returns the value of attribute options.
5 6 7 |
# File 'lib/deflectable/watcher.rb', line 5 def end |
Instance Method Details
#block! ⇒ Object
60 61 62 63 64 |
# File 'lib/deflectable/watcher.rb', line 60 def block! return if blocked? log "blocked #{@remote_addr}" map[:block_expires] = Time.now + [:block_duration] end |
#block_expired? ⇒ Boolean
70 71 72 |
# File 'lib/deflectable/watcher.rb', line 70 def block_expired? map[:block_expires] < Time.now rescue false end |
#blocked? ⇒ Boolean
66 67 68 |
# File 'lib/deflectable/watcher.rb', line 66 def blocked? map.has_key? :block_expires end |
#call(env) ⇒ Object
23 24 25 26 27 |
# File 'lib/deflectable/watcher.rb', line 23 def call(env) return reject! if detect?(env) status, headers, body = @app.call(env) [status, headers, body] end |
#clear! ⇒ Object
78 79 80 81 82 |
# File 'lib/deflectable/watcher.rb', line 78 def clear! return unless watching? log "released #{@remote_addr}" if blocked? @remote_addr_map.delete @remote_addr end |
#detect?(env) ⇒ Boolean
38 39 40 41 42 43 |
# File 'lib/deflectable/watcher.rb', line 38 def detect?(env) @remote_addr = env['REMOTE_ADDR'] return false if [:whitelist].include? @remote_addr return true if [:blacklist].include? @remote_addr @mutex.synchronize { watch } end |
#exceeded_request_threshold? ⇒ Boolean
88 89 90 |
# File 'lib/deflectable/watcher.rb', line 88 def exceeded_request_threshold? map[:requests] > [:request_threshold] end |
#increment_requests ⇒ Object
84 85 86 |
# File 'lib/deflectable/watcher.rb', line 84 def increment_requests map[:requests] += 1 end |
#log(message) ⇒ Object
96 97 98 99 |
# File 'lib/deflectable/watcher.rb', line 96 def log return unless [:log] [:log].puts([:log_format] % [Time.now.strftime([:log_date_format]), ]) end |
#map ⇒ Object
53 54 55 56 57 58 |
# File 'lib/deflectable/watcher.rb', line 53 def map @remote_addr_map[@remote_addr] ||= { :expires => Time.now + [:interval], :requests => 0 } end |
#reject! ⇒ Object
29 30 31 32 33 34 35 36 |
# File 'lib/deflectable/watcher.rb', line 29 def reject! res = Rack::Response.new do |r| r.status = 403 r['Content-Type'] = 'text/html;charset=utf-8' r.write File.read(Rails.root.join('public/403.html')) end res.finish end |
#watch ⇒ Object
45 46 47 48 49 50 51 |
# File 'lib/deflectable/watcher.rb', line 45 def watch increment_requests clear! if watch_expired? and not blocked? clear! if blocked? and block_expired? block! if watching? and exceeded_request_threshold? blocked? end |
#watch_expired? ⇒ Boolean
92 93 94 |
# File 'lib/deflectable/watcher.rb', line 92 def watch_expired? map[:expires] <= Time.now end |
#watching? ⇒ Boolean
74 75 76 |
# File 'lib/deflectable/watcher.rb', line 74 def watching? @remote_addr_map.has_key? @remote_addr end |