Last active
August 29, 2015 13:56
-
-
Save carpodaster/8807139 to your computer and use it in GitHub Desktop.
Spec'ing a Rack middleware-based firewall/blacklist
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class Firewall < Struct.new(:app) | |
class << self | |
def blacklist | |
@blacklist ||= ['192.0.2.1'].freeze # Example IP, see RFC 5735 | |
end | |
end | |
def call(env) | |
if self.class.blacklist.include? env['HTTP_X_FORWARDED_FOR'] | |
message = 'Your IP-address has been banned for security reasons.' + | |
'If you feel this is a mistake, please contact ' + | |
'[email protected]' | |
[403, {}, [message]] | |
else | |
app.call(env) | |
end | |
end | |
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
require 'spec_helper' | |
describe Firewall do | |
let(:app) { ->(env) { [200, env, 'app'] } } | |
subject { described_class.new(app) } | |
describe '.blacklist' do | |
it 'returns a frozen list' do | |
expect(described_class.blacklist).not_to be_empty | |
expect(described_class.blacklist).to be_frozen | |
end | |
end | |
it 'passes request down the middleware stack' do | |
allowed_ip = '1.2.3.4' | |
code, _, _ = subject.call rackenv.merge('HTTP_X_FORWARDED_FOR' => allowed_ip) | |
expect(code).to eql 200 # calls the fake app above | |
end | |
it 'blocks the ip' do | |
banned_ip = '1.2.3.4' | |
described_class.stub(:blacklist).and_return([banned_ip]) | |
code, _, body = subject.call rackenv.merge('HTTP_X_FORWARDED_FOR' => banned_ip) | |
expect(code).to eql 403 # forbidden | |
expect(body.to_s).to match 'banned' | |
end | |
def rackenv(*args) | |
Rack::MockRequest.env_for(*args) | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment