Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

allow development server run on non-ssl port 3000 and still get all t…

…he security in production
  • Loading branch information...
commit 5938d3b8ed6991a56c7e78cb96dadaa2ba7d9672 1 parent 6a6c15d
@mkristian authored
Showing with 38 additions and 13 deletions.
  1. +1 −1  README.md
  2. +13 −8 lib/rack/ssl.rb
  3. +24 −4 test/test_ssl.rb
View
2  README.md
@@ -3,7 +3,7 @@ Rack::SSL
Force SSL/TLS in your app.
-1. Redirects all "http" requests to "https"
+1. Redirects all "http" on given port (option-key :port, default 80) requests to "https" with a given port (option-key :ssl_port, default 443)
2. Set `Strict-Transport-Security` header
3. Flag all cookies as "secure"
View
21 lib/rack/ssl.rb
@@ -16,9 +16,10 @@ def initialize(app, options = {})
@hsts = {} if @hsts.nil? || @hsts == true
@hsts = self.class.default_hsts_options.merge(@hsts) if @hsts
- @exclude = options[:exclude]
- @host = options[:host]
- @port = options[:port]
+ @exclude = options[:exclude]
+ @host = options[:host]
+ @port = options[:port] || 80
+ @ssl_port = options[:ssl_port]
end
def call(env)
@@ -30,7 +31,13 @@ def call(env)
flag_cookies_as_secure!(headers)
[status, headers, body]
else
- redirect_to_https(env)
+ req = Request.new(env)
+ url = URI(req.url)
+ if @port && url.port != @port.to_i
+ @app.call(env)
+ else
+ redirect_to_https(url)
+ end
end
end
@@ -46,12 +53,10 @@ def scheme(env)
end
end
- def redirect_to_https(env)
- req = Request.new(env)
- url = URI(req.url)
+ def redirect_to_https(url)
url.scheme = "https"
url.host = @host if @host
- url.port = @port if @port
+ url.port = @ssl_port if @ssl_port
headers = hsts_headers.merge('Content-Type' => 'text/html',
'Location' => url.to_s)
View
28 test/test_ssl.rb
@@ -81,6 +81,13 @@ def test_flag_cookies_as_secure
last_response.headers['Set-Cookie'].split("\n")
end
+ def test_flag_cookies_as_secure_on_ssl_port
+ self.app = Rack::SSL.new(default_app, :ssl_port => 8443)
+ get "https://example.org:8443/"
+ assert_equal ["id=1; path=/; secure", "token=abc; path=/; secure; HttpOnly" ],
+ last_response.headers['Set-Cookie'].split("\n")
+ end
+
def test_flag_cookies_as_secure_at_end_of_line
self.app = Rack::SSL.new(lambda { |env|
headers = {
@@ -124,20 +131,33 @@ def test_redirect_to_host
last_response.headers['Location']
end
- def test_redirect_to_port
- self.app = Rack::SSL.new(default_app, :port => 8443)
+ def test_redirect_to_ssl_port
+ self.app = Rack::SSL.new(default_app, :ssl_port => 8443)
get "http://example.org/path?key=value"
assert_equal "https://example.org:8443/path?key=value",
last_response.headers['Location']
end
- def test_redirect_to_host_and_port
- self.app = Rack::SSL.new(default_app, :host => "ssl.example.org", :port => 8443)
+ def test_redirect_to_host_and_ssl_port
+ self.app = Rack::SSL.new(default_app, :host => "ssl.example.org", :ssl_port => 8443)
get "http://example.org/path?key=value"
assert_equal "https://ssl.example.org:8443/path?key=value",
last_response.headers['Location']
end
+ def test_do_not_redirect_on_unknown_port
+ self.app = Rack::SSL.new(default_app, :port => 8080)
+ get "http://example.org:3000/path?key=value"
+ assert_nil last_response.headers['Location']
+ end
+
+ def test_redirect_on_known_port
+ self.app = Rack::SSL.new(default_app, :port => 8080, :ssl_port => 8443)
+ get "http://example.org:8080/path?key=value"
+ assert_equal "https://example.org:8443/path?key=value",
+ last_response.headers['Location']
+ end
+
def test_redirect_to_secure_host_when_on_subdomain
self.app = Rack::SSL.new(default_app, :host => "ssl.example.org")
get "http://ssl.example.org/path?key=value"
Please sign in to comment.
Something went wrong with that request. Please try again.