class Rack::IpAddressRestriction

Constants

DEFAULT_MAPPING
VERSION

Public Class Methods

new(app, options = {}) click to toggle source
# File lib/rack/ip_address_restriction.rb, line 11
def initialize(app, options = {})
  @app = app
  options = DEFAULT_MAPPING if options.empty?
  @mapping = create_mapping(options)
end

Public Instance Methods

call(env) click to toggle source
# File lib/rack/ip_address_restriction.rb, line 17
def call(env)
  if allow?(env)
    @app.call(env)
  else
    [403, { 'Content-Type' => 'text/html', 'Content-Length' => '0' }, []]
  end
end

Private Instance Methods

allow?(env) click to toggle source
# File lib/rack/ip_address_restriction.rb, line 49
def allow?(env)
  return true unless ip_masks = ip_masks_for_current_path(env)

  request = Request.new(env)
  ip_masks.any? { |addr| addr.include?(IPAddr.new(request.ip)) }
end
create_mapping(config) click to toggle source
# File lib/rack/ip_address_restriction.rb, line 27
def create_mapping(config)
  mapping = config.map do |location, ip_masks|
    host, path = parse_location(location)
    raise ArgumentError, 'paths need to start with /' if path[0] != '/'
    path_prefix = Pathname.new(path).cleanpath.to_s.chomp('/')

    ip_masks = ip_masks.map { |addr| addr.is_a?(IPAddr) ? addr : IPAddr.new(addr) }

    [host, path_prefix, ip_masks]
  end
  mapping.sort_by { |(host, path_prefix, _)| [host ? -host.size : (-1.0 / 0.0), -path_prefix.size] }
end
ip_masks_for_current_path(env) click to toggle source
# File lib/rack/ip_address_restriction.rb, line 56
def ip_masks_for_current_path(env)
  path = Pathname.new(env["PATH_INFO"].to_s).cleanpath.to_s

  @mapping.each do |host, path_prefix, ip_masks|
    next if host && ![env['HTTP_HOST'], env['SERVER_NAME']].include?(host)
    next if path !~ %r{\A#{Regexp.quote(path_prefix)}(.*)\z}i || !($1.empty? || $1[0] == '/')

    return ip_masks
  end

  nil
end
parse_location(location) click to toggle source
# File lib/rack/ip_address_restriction.rb, line 40
def parse_location(location)
  uri = URI.parse(location)
  if uri.host
    [uri.host, uri.path]
  else
    [nil, location]
  end
end