Class: Rack::Access
- Inherits:
-
Object
- Object
- Rack::Access
- Defined in:
- lib/rack/contrib/access.rb
Overview
Rack middleware for limiting access based on IP address
Options:
path => ipmasks ipmasks: Array of remote addresses which are allowed to access
Examples:
use Rack::Access, '/backend' => [ '127.0.0.1', '192.168.1.0/24' ]
Instance Attribute Summary collapse
-
#options ⇒ Object
readonly
Returns the value of attribute options.
Instance Method Summary collapse
- #call(env) ⇒ Object
- #forbidden! ⇒ Object
-
#initialize(app, options = {}) ⇒ Access
constructor
A new instance of Access.
- #ip_authorized?(request, ipmasks) ⇒ Boolean
- #ipmasks_for_path(env) ⇒ Object
- #remap(mapping) ⇒ Object
Constructor Details
#initialize(app, options = {}) ⇒ Access
Returns a new instance of Access.
25 26 27 28 29 |
# File 'lib/rack/contrib/access.rb', line 25 def initialize(app, = {}) @app = app mapping = .empty? ? {"/" => ["127.0.0.1"]} : @mapping = remap(mapping) end |
Instance Attribute Details
#options ⇒ Object (readonly)
Returns the value of attribute options.
23 24 25 |
# File 'lib/rack/contrib/access.rb', line 23 def @options end |
Instance Method Details
#call(env) ⇒ Object
52 53 54 55 56 57 58 |
# File 'lib/rack/contrib/access.rb', line 52 def call(env) request = Request.new(env) ipmasks = ipmasks_for_path(env) return forbidden! unless (request, ipmasks) status, headers, body = @app.call(env) [status, headers, body] end |
#forbidden! ⇒ Object
74 75 76 |
# File 'lib/rack/contrib/access.rb', line 74 def forbidden! [403, { 'content-type' => 'text/html', 'content-length' => '0' }, []] end |
#ip_authorized?(request, ipmasks) ⇒ Boolean
78 79 80 81 82 83 84 |
# File 'lib/rack/contrib/access.rb', line 78 def (request, ipmasks) return true if ipmasks.nil? ipmasks.any? do |ip_mask| ip_mask.include?(IPAddr.new(request.ip)) end end |
#ipmasks_for_path(env) ⇒ Object
60 61 62 63 64 65 66 67 68 69 70 71 72 |
# File 'lib/rack/contrib/access.rb', line 60 def ipmasks_for_path(env) path = env["PATH_INFO"].to_s hHost, sName, sPort = env.values_at('HTTP_HOST','SERVER_NAME','SERVER_PORT') @mapping.each do |host, location, match, ipmasks| next unless (hHost == host || sName == host \ || (host.nil? && (hHost == sName || hHost == sName+':'+sPort))) next unless path =~ match && rest = $1 next unless rest.empty? || rest[0] == ?/ return ipmasks end nil end |
#remap(mapping) ⇒ Object
31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 |
# File 'lib/rack/contrib/access.rb', line 31 def remap(mapping) mapping.map { |location, ipmasks| if location =~ %r{\Ahttps?://(.*?)(/.*)} host, location = $1, $2 else host = nil end unless location[0] == ?/ raise ArgumentError, "paths need to start with /" end location = location.chomp('/') match = Regexp.new("^#{Regexp.quote(location).gsub('/', '/+')}(.*)", Regexp::NOENCODING) ipmasks.collect! do |ipmask| ipmask.is_a?(IPAddr) ? ipmask : IPAddr.new(ipmask) end [host, location, match, ipmasks] }.sort_by { |(h, l, m, a)| [h ? -h.size : (-1.0 / 0.0), -l.size] } # Longest path first end |