Class: Rack::Killswitch

Inherits:
Object
  • Object
show all
Defined in:
lib/rack/killswitch.rb

Overview

Killswitch is a Rack Middleware to disable access to a Rails (or Rack) app

Inspired by rack-maintenance - https://github.com/ddollar/rack-maintenance
(Credit where credit is due!)

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

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

Returns a new instance of Killswitch.

Raises:

  • (ArgumentError)


10
11
12
13
14
15
16
# File 'lib/rack/killswitch.rb', line 10

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

  raise(ArgumentError, 'Must specify a trigger file (:trigger)') unless options[:trigger]
  raise(ArgumentError, 'Must specify a holding page (:page)') unless options[:page]
end

Instance Attribute Details

#appObject (readonly)

Returns the value of attribute app.



8
9
10
# File 'lib/rack/killswitch.rb', line 8

def app
  @app
end

#optionsObject (readonly)

Returns the value of attribute options.



8
9
10
# File 'lib/rack/killswitch.rb', line 8

def options
  @options
end

Instance Method Details

#call(env) ⇒ Object



18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
# File 'lib/rack/killswitch.rb', line 18

def call(env)
  # If the site is down and the user visits the defined override path, set a cookie so he can get in
  if down? and options[:override_path] and env['REQUEST_URI'] == options[:override_path]
    # HTTP 303: "See Other" 
    # The response to the request can be found under a different URI and SHOULD be retrieved using a
    # GET method on that resource. The new URI is not a substitute reference for the originally requested
    # resource. The 303 response MUST NOT be cached.
    response = Rack::Response.new([''], 303, { 'Location' => '/', 'Content-Length' => '0' })
    response.set_cookie("override_killswitch", {:value => "true", :path => "/", :expires => Time.now+24*60*60})
    response.finish
  elsif down? and not cookie_set?(env)
    # Ensure holding page exists
    raise "Holding page file #{options[:page]} does not exist" unless File.exists?(options[:page])
    
    # Get what's in there and send it over to the unsuspecting user
    data = File.read(options[:page])
    [ 503, { 'Content-Type' => 'text/html', 'Content-Length' => data.length.to_s }, [data] ] 
  else
    # Business as usual
    app.call(env)
  end
end