Class: IpBlocker::Middleware

Inherits:
Object
  • Object
show all
Defined in:
lib/ip_blocker/middleware.rb

Constant Summary collapse

BLOCKED_RESPONSE =

Response to return when the request IP is blocked.

[
  403,
  {"Content-Type".freeze => "text/html".freeze},
  ["<h1>403 Forbidden</h1>".freeze]
]
RACK_IP_ENV_KEY =
"REMOTE_ADDR".freeze
RAILS_IP_ENV_KEY =
"action_dispatch.remote_ip".freeze
@@blocked_ips =

List of blocked IPs. Use Set instead of Array for faster include? lookups, as order or uniqueness doesn’t matter here.

nil

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(app, options = {}) ⇒ Middleware

Returns a new instance of Middleware.



31
32
33
34
35
36
37
38
# File 'lib/ip_blocker/middleware.rb', line 31

def initialize(app, options = {})
  @app = app
  @options = options

  if rails?
    @options[:file_path] ||= Rails.configuration.ip_blocker.file_path
  end
end

Class Method Details

.blocked_ips(file_path) ⇒ Object



6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# File 'lib/ip_blocker/middleware.rb', line 6

def self.blocked_ips(file_path)
  @@blocked_ips ||= Set.new(
    # Remove newlines at the end of each line.
    File.readlines(file_path).map { |line|
      line.chomp.strip
    }.reject { |line|
      # Skip empty lines or comments.
      line.empty? || line.start_with?("#")
    }.freeze.map(&:freeze)
  )
rescue Errno::ENOENT
  warn "IpBlocker: File with blocked IP's '#{file_path}' doesn't exist. " \
    "Not blocking anything."
  @@blocked_ips = []
end

Instance Method Details

#call(env) ⇒ Object



40
41
42
43
44
45
46
47
48
49
50
51
52
53
# File 'lib/ip_blocker/middleware.rb', line 40

def call(env)
  ip = env.fetch(
    rails? ? RAILS_IP_ENV_KEY : RACK_IP_ENV_KEY,
    "".freeze
  ).to_s

  # IP is blocked, return the blocked response.
  if blocked_ips.include?(ip)
    BLOCKED_RESPONSE
  # Let the request through.
  else
    @app.call(env)
  end
end