rack-secure_only 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/.document +5 -0
- data/.gitignore +21 -0
- data/LICENSE +20 -0
- data/README.rdoc +43 -0
- data/Rakefile +38 -0
- data/VERSION +1 -0
- data/lib/rack/secure_only.rb +66 -0
- data/rack-secure_only.gemspec +61 -0
- data/spec/rack/secure_only_spec.rb +145 -0
- data/spec/spec.opts +1 -0
- data/spec/spec_helper.rb +10 -0
- metadata +115 -0
data/.document
ADDED
data/.gitignore
ADDED
data/LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright (c) 2009 Klaas Speller
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.rdoc
ADDED
@@ -0,0 +1,43 @@
|
|
1
|
+
= rack-secure_only
|
2
|
+
|
3
|
+
SecureOnly will redirect to https if the request is on http.
|
4
|
+
|
5
|
+
When passed :secure => false it will do the opposite and redirect https to http.
|
6
|
+
|
7
|
+
The check if the current request is on https includes checking the HTTP_X_FORWARDED_PROTO header.
|
8
|
+
|
9
|
+
This means the redirect will also work on heroku.com
|
10
|
+
|
11
|
+
== Usage
|
12
|
+
|
13
|
+
require 'rack/secure_only'
|
14
|
+
|
15
|
+
app = Rack::Builder.new do
|
16
|
+
map '/secure' do
|
17
|
+
use Rack::SecureOnly
|
18
|
+
run lambda { |env| [200, { 'Content-Type' => 'text/plain' }, ["SECURE APP"]] }
|
19
|
+
end
|
20
|
+
|
21
|
+
map '/notsecure' do
|
22
|
+
use Rack::SecureOnly, :secure => false
|
23
|
+
run lambda { |env| [200, { 'Content-Type' => 'text/plain' }, ["NON SECURE APP"]] }
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
run app
|
28
|
+
|
29
|
+
This will redirect all requests to /secure to https and all requests to /notsecure to http.
|
30
|
+
|
31
|
+
== Note on Patches/Pull Requests
|
32
|
+
|
33
|
+
* Fork the project.
|
34
|
+
* Make your feature addition or bug fix.
|
35
|
+
* Add tests for it. This is important so I don't break it in a
|
36
|
+
future version unintentionally.
|
37
|
+
* Commit, do not mess with rakefile, version, or history.
|
38
|
+
(if you want to have your own version, that is fine but bump version in a commit by itself I can ignore when I pull)
|
39
|
+
* Send me a pull request. Bonus points for topic branches.
|
40
|
+
|
41
|
+
== Copyright
|
42
|
+
|
43
|
+
Copyright (c) 2010 Klaas Speller. See LICENSE for details.
|
data/Rakefile
ADDED
@@ -0,0 +1,38 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'rake'
|
3
|
+
|
4
|
+
begin
|
5
|
+
require 'jeweler'
|
6
|
+
Jeweler::Tasks.new do |gem|
|
7
|
+
gem.name = "rack-secure_only"
|
8
|
+
gem.summary = %Q{Redirect http to https and the other way around}
|
9
|
+
gem.description = %Q{Redirect http to https and the other way around}
|
10
|
+
gem.email = "klaasspeller@gmail.com"
|
11
|
+
gem.homepage = "http://github.com/spllr/rack-secure_only"
|
12
|
+
gem.authors = ["Klaas Speller"]
|
13
|
+
gem.add_development_dependency "rspec", ">= 1.2.9"
|
14
|
+
gem.add_development_dependency "rack-test", ">= 0.5.3"
|
15
|
+
gem.add_dependency "rack", ">= 1.1.0"
|
16
|
+
end
|
17
|
+
Jeweler::GemcutterTasks.new
|
18
|
+
rescue LoadError
|
19
|
+
puts "Jeweler (or a dependency) not available. Install it with: gem install jeweler"
|
20
|
+
end
|
21
|
+
|
22
|
+
require 'spec/rake/spectask'
|
23
|
+
Spec::Rake::SpecTask.new(:spec) do |spec|
|
24
|
+
spec.libs << 'lib' << 'spec'
|
25
|
+
spec.spec_files = FileList['spec/**/*_spec.rb']
|
26
|
+
end
|
27
|
+
|
28
|
+
task :default => :spec
|
29
|
+
|
30
|
+
require 'rake/rdoctask'
|
31
|
+
Rake::RDocTask.new do |rdoc|
|
32
|
+
version = File.exist?('VERSION') ? File.read('VERSION') : ""
|
33
|
+
|
34
|
+
rdoc.rdoc_dir = 'rdoc'
|
35
|
+
rdoc.title = "rack-secure_only #{version}"
|
36
|
+
rdoc.rdoc_files.include('README*')
|
37
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
38
|
+
end
|
data/VERSION
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
0.1.0
|
@@ -0,0 +1,66 @@
|
|
1
|
+
require "rack"
|
2
|
+
|
3
|
+
module Rack
|
4
|
+
|
5
|
+
# SecureOnly will redirect to https if the request is on http.
|
6
|
+
#
|
7
|
+
# When passed :secure => false it will do the opposite and redirect https to http
|
8
|
+
#
|
9
|
+
# The check if the current request is on https includes checking
|
10
|
+
# the HTTP_X_FORWARDED_PROTO header.
|
11
|
+
#
|
12
|
+
# This means the redirect will also work on heroku.com
|
13
|
+
#
|
14
|
+
class SecureOnly
|
15
|
+
def initialize(app, opts={})
|
16
|
+
opts = { :secure => true }.merge(opts)
|
17
|
+
@app = app
|
18
|
+
@secure = opts[:secure]
|
19
|
+
end
|
20
|
+
|
21
|
+
def call(env)
|
22
|
+
should_redirect, to_path = redirect?(env)
|
23
|
+
return [307, { 'Content-Type' => 'text/plain', 'Location' => to_path }, ["Redirect"]] if should_redirect
|
24
|
+
@app.call(env)
|
25
|
+
end
|
26
|
+
|
27
|
+
# Returns true if the current url scheme is http
|
28
|
+
# and the HTTP_X_FORWARDED_PROTO header is not set to https
|
29
|
+
#
|
30
|
+
def on_http?(env)
|
31
|
+
( env['rack.url_scheme'] == 'http' && env['HTTP_X_FORWARDED_PROTO'] != 'https')
|
32
|
+
end
|
33
|
+
|
34
|
+
# Returns true if the current url scheme is https or
|
35
|
+
# the HTTP_X_FORWARDED_PROTO header is set to https
|
36
|
+
#
|
37
|
+
def on_https?(env)
|
38
|
+
( env['rack.url_scheme'] == 'https' || env['HTTP_X_FORWARDED_PROTO'] == 'https')
|
39
|
+
end
|
40
|
+
|
41
|
+
# Boolean accesor for :secure
|
42
|
+
#
|
43
|
+
def secure?
|
44
|
+
!!@secure
|
45
|
+
end
|
46
|
+
|
47
|
+
# Inversed boolean accesor for :secure
|
48
|
+
#
|
49
|
+
def not_secure?
|
50
|
+
!secure?
|
51
|
+
end
|
52
|
+
|
53
|
+
protected
|
54
|
+
|
55
|
+
def redirect?(env)
|
56
|
+
req = Request.new(env)
|
57
|
+
if secure? && on_http?(env)
|
58
|
+
return [true, req.url.gsub(/^http:/,'https:')]
|
59
|
+
elsif not_secure? && on_https?(env)
|
60
|
+
return [true, req.url.gsub(/^https:/,'http:')]
|
61
|
+
else
|
62
|
+
return [false, req.url]
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
@@ -0,0 +1,61 @@
|
|
1
|
+
# Generated by jeweler
|
2
|
+
# DO NOT EDIT THIS FILE DIRECTLY
|
3
|
+
# Instead, edit Jeweler::Tasks in Rakefile, and run the gemspec command
|
4
|
+
# -*- encoding: utf-8 -*-
|
5
|
+
|
6
|
+
Gem::Specification.new do |s|
|
7
|
+
s.name = %q{rack-secure_only}
|
8
|
+
s.version = "0.1.0"
|
9
|
+
|
10
|
+
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
|
+
s.authors = ["Klaas Speller"]
|
12
|
+
s.date = %q{2010-05-21}
|
13
|
+
s.description = %q{Redirect http to https and the other way around}
|
14
|
+
s.email = %q{klaasspeller@gmail.com}
|
15
|
+
s.extra_rdoc_files = [
|
16
|
+
"LICENSE",
|
17
|
+
"README.rdoc"
|
18
|
+
]
|
19
|
+
s.files = [
|
20
|
+
".document",
|
21
|
+
".gitignore",
|
22
|
+
"LICENSE",
|
23
|
+
"README.rdoc",
|
24
|
+
"Rakefile",
|
25
|
+
"VERSION",
|
26
|
+
"lib/rack/secure_only.rb",
|
27
|
+
"rack-secure_only.gemspec",
|
28
|
+
"spec/rack/secure_only_spec.rb",
|
29
|
+
"spec/spec.opts",
|
30
|
+
"spec/spec_helper.rb"
|
31
|
+
]
|
32
|
+
s.homepage = %q{http://github.com/spllr/rack-secure_only}
|
33
|
+
s.rdoc_options = ["--charset=UTF-8"]
|
34
|
+
s.require_paths = ["lib"]
|
35
|
+
s.rubygems_version = %q{1.3.6}
|
36
|
+
s.summary = %q{Redirect http to https and the other way around}
|
37
|
+
s.test_files = [
|
38
|
+
"spec/rack/secure_only_spec.rb",
|
39
|
+
"spec/spec_helper.rb"
|
40
|
+
]
|
41
|
+
|
42
|
+
if s.respond_to? :specification_version then
|
43
|
+
current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
|
44
|
+
s.specification_version = 3
|
45
|
+
|
46
|
+
if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
|
47
|
+
s.add_development_dependency(%q<rspec>, [">= 1.2.9"])
|
48
|
+
s.add_development_dependency(%q<rack-test>, [">= 0.5.3"])
|
49
|
+
s.add_runtime_dependency(%q<rack>, [">= 1.1.0"])
|
50
|
+
else
|
51
|
+
s.add_dependency(%q<rspec>, [">= 1.2.9"])
|
52
|
+
s.add_dependency(%q<rack-test>, [">= 0.5.3"])
|
53
|
+
s.add_dependency(%q<rack>, [">= 1.1.0"])
|
54
|
+
end
|
55
|
+
else
|
56
|
+
s.add_dependency(%q<rspec>, [">= 1.2.9"])
|
57
|
+
s.add_dependency(%q<rack-test>, [">= 0.5.3"])
|
58
|
+
s.add_dependency(%q<rack>, [">= 1.1.0"])
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
@@ -0,0 +1,145 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
|
2
|
+
|
3
|
+
describe Rack::SecureOnly do
|
4
|
+
|
5
|
+
def app
|
6
|
+
Rack::Builder.new do
|
7
|
+
map '/secure' do
|
8
|
+
use Rack::SecureOnly
|
9
|
+
run lambda { |env| [200, { 'Content-Type' => 'text/plain' }, ["SECURE APP"]] }
|
10
|
+
end
|
11
|
+
|
12
|
+
map '/notsecure' do
|
13
|
+
use Rack::SecureOnly, :secure => false
|
14
|
+
run lambda { |env| [200, { 'Content-Type' => 'text/plain' }, ["NON SECURE APP"]] }
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
describe "Enforcing https" do
|
20
|
+
before(:each) do
|
21
|
+
@request = Rack::MockRequest.new(app)
|
22
|
+
@response = @request.get('https://www.example.com/secure')
|
23
|
+
end
|
24
|
+
|
25
|
+
describe "when requesting https://www.example.com/secure" do
|
26
|
+
it "should pass" do
|
27
|
+
@response.body.should == "SECURE APP"
|
28
|
+
end
|
29
|
+
|
30
|
+
it "should set status to 200 ok" do
|
31
|
+
@response.status.should == 200
|
32
|
+
end
|
33
|
+
|
34
|
+
it "should not set a location header" do
|
35
|
+
@response.location.should be_nil
|
36
|
+
end
|
37
|
+
|
38
|
+
describe "with HTTP_X_FORWARDED_PROTO header set to https (like with heroku ssl)" do
|
39
|
+
before(:each) do
|
40
|
+
@response = @request.get('http://www.example.com/secure', { 'HTTP_X_FORWARDED_PROTO' => 'https' })
|
41
|
+
end
|
42
|
+
|
43
|
+
it "should do no redirect" do
|
44
|
+
@response.location.should be_nil
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
end
|
49
|
+
|
50
|
+
describe "when requesting http://www.example.com/secure" do
|
51
|
+
before(:each) do
|
52
|
+
@response = @request.get('http://www.example.com/secure')
|
53
|
+
end
|
54
|
+
it "should respond with status 307 redirect" do
|
55
|
+
@response.status.should == 307
|
56
|
+
end
|
57
|
+
|
58
|
+
it "should set location to https://www.example.com/secure" do
|
59
|
+
@response.location.should == "https://www.example.com/secure"
|
60
|
+
end
|
61
|
+
|
62
|
+
it "should set a content type" do
|
63
|
+
@response.content_type.should == 'text/plain'
|
64
|
+
end
|
65
|
+
|
66
|
+
describe "following redirect" do
|
67
|
+
before(:each) do
|
68
|
+
@redirect_response = @request.get(@response.location)
|
69
|
+
end
|
70
|
+
|
71
|
+
it "should pass" do
|
72
|
+
@redirect_response.body.should == "SECURE APP"
|
73
|
+
end
|
74
|
+
|
75
|
+
it "should respond 200 ok" do
|
76
|
+
@redirect_response.status.should == 200
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
describe "Enforcing http" do
|
83
|
+
before(:each) do
|
84
|
+
@request = Rack::MockRequest.new(app)
|
85
|
+
@response = @request.get('https://www.example.com/notsecure')
|
86
|
+
end
|
87
|
+
|
88
|
+
describe "when requesting https://www.example.com/notsecure" do
|
89
|
+
|
90
|
+
it "should respond with status 307 redirect" do
|
91
|
+
@response.status.should == 307
|
92
|
+
end
|
93
|
+
|
94
|
+
it "should set location to http://www.example.com/notsecure" do
|
95
|
+
@response.location.should == "http://www.example.com/notsecure"
|
96
|
+
end
|
97
|
+
|
98
|
+
it "should set a content type" do
|
99
|
+
@response.content_type.should == 'text/plain'
|
100
|
+
end
|
101
|
+
|
102
|
+
describe "and following redirect" do
|
103
|
+
before(:each) do
|
104
|
+
@redirect_response = @request.get(@response.location)
|
105
|
+
end
|
106
|
+
|
107
|
+
it "should pass" do
|
108
|
+
@redirect_response.body.should == "NON SECURE APP"
|
109
|
+
end
|
110
|
+
|
111
|
+
it "should respond 200 ok" do
|
112
|
+
@redirect_response.status.should == 200
|
113
|
+
end
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
117
|
+
describe "when requesting http://www.example.com/notsecure" do
|
118
|
+
before(:each) do
|
119
|
+
@response = @request.get('http://www.example.com/notsecure')
|
120
|
+
end
|
121
|
+
|
122
|
+
it "should pass" do
|
123
|
+
@response.body.should == "NON SECURE APP"
|
124
|
+
end
|
125
|
+
|
126
|
+
it "should set status to 200 ok" do
|
127
|
+
@response.status.should == 200
|
128
|
+
end
|
129
|
+
|
130
|
+
it "should not set a location header" do
|
131
|
+
@response.location.should be_nil
|
132
|
+
end
|
133
|
+
|
134
|
+
describe "with HTTP_X_FORWARDED_PROTO header set to https (like with heroku ssl)" do
|
135
|
+
before(:each) do
|
136
|
+
@response = @request.get('http://www.example.com/notsecure', { 'HTTP_X_FORWARDED_PROTO' => 'https' })
|
137
|
+
end
|
138
|
+
|
139
|
+
it "should do redirect" do
|
140
|
+
@response.location.should == "http://www.example.com/notsecure"
|
141
|
+
end
|
142
|
+
end
|
143
|
+
end
|
144
|
+
end
|
145
|
+
end
|
data/spec/spec.opts
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
--color
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,10 @@
|
|
1
|
+
$LOAD_PATH.unshift(File.dirname(__FILE__))
|
2
|
+
$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
|
3
|
+
require 'rack/secure_only'
|
4
|
+
require 'spec'
|
5
|
+
require 'spec/autorun'
|
6
|
+
require 'rack/test'
|
7
|
+
|
8
|
+
Spec::Runner.configure do |config|
|
9
|
+
config.include Rack::Test::Methods
|
10
|
+
end
|
metadata
ADDED
@@ -0,0 +1,115 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: rack-secure_only
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
prerelease: false
|
5
|
+
segments:
|
6
|
+
- 0
|
7
|
+
- 1
|
8
|
+
- 0
|
9
|
+
version: 0.1.0
|
10
|
+
platform: ruby
|
11
|
+
authors:
|
12
|
+
- Klaas Speller
|
13
|
+
autorequire:
|
14
|
+
bindir: bin
|
15
|
+
cert_chain: []
|
16
|
+
|
17
|
+
date: 2010-05-21 00:00:00 +02:00
|
18
|
+
default_executable:
|
19
|
+
dependencies:
|
20
|
+
- !ruby/object:Gem::Dependency
|
21
|
+
name: rspec
|
22
|
+
prerelease: false
|
23
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
24
|
+
requirements:
|
25
|
+
- - ">="
|
26
|
+
- !ruby/object:Gem::Version
|
27
|
+
segments:
|
28
|
+
- 1
|
29
|
+
- 2
|
30
|
+
- 9
|
31
|
+
version: 1.2.9
|
32
|
+
type: :development
|
33
|
+
version_requirements: *id001
|
34
|
+
- !ruby/object:Gem::Dependency
|
35
|
+
name: rack-test
|
36
|
+
prerelease: false
|
37
|
+
requirement: &id002 !ruby/object:Gem::Requirement
|
38
|
+
requirements:
|
39
|
+
- - ">="
|
40
|
+
- !ruby/object:Gem::Version
|
41
|
+
segments:
|
42
|
+
- 0
|
43
|
+
- 5
|
44
|
+
- 3
|
45
|
+
version: 0.5.3
|
46
|
+
type: :development
|
47
|
+
version_requirements: *id002
|
48
|
+
- !ruby/object:Gem::Dependency
|
49
|
+
name: rack
|
50
|
+
prerelease: false
|
51
|
+
requirement: &id003 !ruby/object:Gem::Requirement
|
52
|
+
requirements:
|
53
|
+
- - ">="
|
54
|
+
- !ruby/object:Gem::Version
|
55
|
+
segments:
|
56
|
+
- 1
|
57
|
+
- 1
|
58
|
+
- 0
|
59
|
+
version: 1.1.0
|
60
|
+
type: :runtime
|
61
|
+
version_requirements: *id003
|
62
|
+
description: Redirect http to https and the other way around
|
63
|
+
email: klaasspeller@gmail.com
|
64
|
+
executables: []
|
65
|
+
|
66
|
+
extensions: []
|
67
|
+
|
68
|
+
extra_rdoc_files:
|
69
|
+
- LICENSE
|
70
|
+
- README.rdoc
|
71
|
+
files:
|
72
|
+
- .document
|
73
|
+
- .gitignore
|
74
|
+
- LICENSE
|
75
|
+
- README.rdoc
|
76
|
+
- Rakefile
|
77
|
+
- VERSION
|
78
|
+
- lib/rack/secure_only.rb
|
79
|
+
- rack-secure_only.gemspec
|
80
|
+
- spec/rack/secure_only_spec.rb
|
81
|
+
- spec/spec.opts
|
82
|
+
- spec/spec_helper.rb
|
83
|
+
has_rdoc: true
|
84
|
+
homepage: http://github.com/spllr/rack-secure_only
|
85
|
+
licenses: []
|
86
|
+
|
87
|
+
post_install_message:
|
88
|
+
rdoc_options:
|
89
|
+
- --charset=UTF-8
|
90
|
+
require_paths:
|
91
|
+
- lib
|
92
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - ">="
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
segments:
|
97
|
+
- 0
|
98
|
+
version: "0"
|
99
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
100
|
+
requirements:
|
101
|
+
- - ">="
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
segments:
|
104
|
+
- 0
|
105
|
+
version: "0"
|
106
|
+
requirements: []
|
107
|
+
|
108
|
+
rubyforge_project:
|
109
|
+
rubygems_version: 1.3.6
|
110
|
+
signing_key:
|
111
|
+
specification_version: 3
|
112
|
+
summary: Redirect http to https and the other way around
|
113
|
+
test_files:
|
114
|
+
- spec/rack/secure_only_spec.rb
|
115
|
+
- spec/spec_helper.rb
|