Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adds functionality to limit redirection to specific hosts #7

Open
wants to merge 8 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 6 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
## 0.0.3 (February 27, 2014)

- Added option to specify on which hosts to perform redirection


## 0.0.2 (June 14, 2011)

- Populate CHANGELOG.
Expand All @@ -9,4 +14,4 @@

## 0.0.1 (June 22, 2010)

- Initial release
- Initial release
6 changes: 6 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,12 @@ middleware at the top of the Rack stack::
end
end

You can also specify the `:only_hosts` parameter to limit redirection to specific hosts

config.middleware.use(Rack::NoWWW, only_hosts: "www.example.org")

Requests not made on www.example.org will not be redirected to the root domain.


Credits
-------
Expand Down
29 changes: 22 additions & 7 deletions lib/rack/no-www.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,21 +5,36 @@ class NoWWW

STARTS_WITH_WWW = /^www\./i

def initialize(app)
def initialize(app, options={})
default_options = {
only_hosts: []
}

@app = app
@options = default_options.merge(options)
end

def call(env)
if env['HTTP_HOST'] =~ STARTS_WITH_WWW
[301, no_www_request(env), ["Moved Permanently\n"]]
@env = env
if require_redirect?
[301, no_www_request, ["Moved Permanently\n"]]
else
@app.call(env)
@app.call(@env)
end
end

private
def no_www_request(env)
{ 'Location' => Rack::Request.new(env).url.sub(/www\./i, ''),
private

def require_redirect?
@env['HTTP_HOST'] =~ STARTS_WITH_WWW && host_match?
end

def host_match?
@options[:only_hosts].include?(@env['HTTP_HOST']) || @options[:only_hosts].empty?
end

def no_www_request
{ 'Location' => Rack::Request.new(@env).url.sub(/www\./i, ''),
'Content-Type' => 'text/html' }
end

Expand Down
2 changes: 1 addition & 1 deletion lib/rack/no-www/version.rb
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
module Rack
class NoWWW
VERSION = "0.0.2"
VERSION = "0.0.3"
end
end
74 changes: 56 additions & 18 deletions spec/rack_no_www_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,37 +3,75 @@
describe "Rack::NoWWW" do

include Rack::Test::Methods

def app
mock_endpoint = lambda { |env| [200, {}, ['Hello, world.']] }
app = Rack::NoWWW.new(mock_endpoint)
end
let(:mock_endpoint) { lambda { |env| [200, {}, ["Hello, world."]] } }

describe "when receiving a request with a 'www'" do
context "without the :only_hosts parameter specified" do

let :app do
Rack::NoWWW.new(mock_endpoint)
end

before(:each) do
request '/', {'HTTP_HOST' => 'www.example.org' }
end
before(:each) do
request '/', {'HTTP_HOST' => 'www.example.org' }
end

it "should issue a 301 redirect" do
last_response.status.should == 301
end
it "should issue a 301 redirect" do
last_response.status.should == 301
end

it "should redirect to the URL without the 'www'" do
last_response.headers['Location'].should == "http://example.org/"
it "should redirect to the URL without the 'www'" do
last_response.headers['Location'].should == "http://example.org/"
end

it "should have a text/html content type" do
last_response.headers['Content-Type'].should == "text/html"
end

it "should have a body of 'Moved Permanently\\n'" do
last_response.body.should == "Moved Permanently\n"
end

end

it "should have a text/html content type" do
last_response.headers['Content-Type'].should == "text/html"
context "with a non-matching domain in the :only_hosts parameter" do
let :app do
Rack::NoWWW.new(mock_endpoint, only_hosts: ['www.do-not-redirect.org'])
end

before(:each) do
request '/', {'HTTP_HOST' => 'www.example.org' }
end

it "should not issue a 301 redirect" do
last_response.status.should == 200
end
end

it "should have a body of 'Moved Permanently\\n'" do
last_response.body.should == "Moved Permanently\n"
context "with a matching domain in the :only_hosts parameter" do
let :app do
Rack::NoWWW.new(mock_endpoint, only_hosts: ['www.example.org'])
end

before(:each) do
request '/', {'HTTP_HOST' => 'www.example.org' }
end

it "should issue a 301 redirect" do
last_response.status.should == 301
end

it "should redirect to the URL without the 'www'" do
last_response.headers['Location'].should == "http://example.org/"
end
end

end

describe "when receiving a request without a 'www'" do
let :app do
Rack::NoWWW.new(mock_endpoint)
end

it "should fall through to the app" do
get '/'
last_response.status.should == 200
Expand Down