1
0
Fork 0
mirror of https://github.com/rails/rails.git synced 2022-11-09 12:12:34 -05:00
rails--rails/actionpack/lib/action_dispatch/middleware/ssl.rb

73 lines
1.7 KiB
Ruby
Raw Normal View History

2012-03-16 22:22:25 -04:00
module ActionDispatch
class SSL
YEAR = 31536000
def self.default_hsts_options
{ :expires => YEAR, :subdomains => false }
end
def initialize(app, options = {})
@app = app
@hsts = options.fetch(:hsts, {})
@hsts = {} if @hsts == true
2012-03-16 22:22:25 -04:00
@hsts = self.class.default_hsts_options.merge(@hsts) if @hsts
@host = options[:host]
@port = options[:port]
end
def call(env)
request = Request.new(env)
if request.ssl?
2012-03-16 22:22:25 -04:00
status, headers, body = @app.call(env)
headers = hsts_headers.merge(headers)
flag_cookies_as_secure!(headers)
[status, headers, body]
else
redirect_to_https(request)
2012-03-16 22:22:25 -04:00
end
end
private
def redirect_to_https(request)
host = @host || request.host
port = @port || request.port
location = "https://#{host}"
location << ":#{port}" if port != 80
location << request.fullpath
headers = { 'Content-Type' => 'text/html', 'Location' => location }
2012-03-16 22:22:25 -04:00
[301, headers, []]
end
# http://tools.ietf.org/html/draft-hodges-strict-transport-sec-02
def hsts_headers
if @hsts
value = "max-age=#{@hsts[:expires].to_i}"
2012-03-16 22:22:25 -04:00
value += "; includeSubDomains" if @hsts[:subdomains]
{ 'Strict-Transport-Security' => value }
else
{}
end
end
def flag_cookies_as_secure!(headers)
if cookies = headers['Set-Cookie']
cookies = cookies.split("\n")
2012-03-16 22:22:25 -04:00
headers['Set-Cookie'] = cookies.map { |cookie|
if cookie !~ /;\s*secure\s*(;|$)/i
2012-03-16 22:22:25 -04:00
"#{cookie}; secure"
else
cookie
end
}.join("\n")
end
end
end
end