rack-canonical-host 0.0.3 → 0.0.4

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore ADDED
@@ -0,0 +1,18 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .rvmrc
6
+ .yardoc
7
+ Gemfile.lock
8
+ InstalledFiles
9
+ _yardoc
10
+ coverage
11
+ doc
12
+ lib/bundler/man
13
+ pkg
14
+ rdoc
15
+ spec/reports
16
+ test/tmp
17
+ test/version_tmp
18
+ tmp
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --color
2
+ --format progress
data/CHANGELOG.md ADDED
@@ -0,0 +1,24 @@
1
+ # Changelog
2
+
3
+ ## Rack::CanonicalHost 0.0.4
4
+
5
+ * Add option to ignored certain hosts ([Eric Allam][rubymaverick])
6
+ * Add tests ([Nathaniel Bibler][nbibler])
7
+ * Add HTML response body on redirect
8
+ * Set `Content-Type` header on redirect ([Jon Wood][jellybob])
9
+
10
+ ## Rack::CanonicalHost 0.0.3
11
+
12
+ * Allow `env` to be passed to the optional block
13
+
14
+ ## Rack::CanonicalHost 0.0.2
15
+
16
+ * Move `CanonicalHost` into `Rack` namespace
17
+
18
+ ## Rack::CanonicalHost 0.0.1
19
+
20
+ * Initial release
21
+
22
+ [jellybob]: http://github.com/jellybob
23
+ [nbibler]: http://github.com/nbibler
24
+ [rubymaverick]: http://github.com/rubymaverick
data/Gemfile ADDED
@@ -0,0 +1,3 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gemspec
data/README.md ADDED
@@ -0,0 +1,97 @@
1
+ # Rack Canonical Host
2
+
3
+ Rack middleware that lets you define a single host name as the canonical host
4
+ for your application. Requests for other host names will then be redirected to
5
+ the canonical host.
6
+
7
+
8
+ ## Installation
9
+
10
+ Add this line to your application's `Gemfile`:
11
+
12
+ ``` ruby
13
+ gem 'rack-canonical-host'
14
+ ```
15
+
16
+ And then execute:
17
+
18
+ $ bundle
19
+
20
+ Or install it yourself as:
21
+
22
+ $ gem install rack-canonical-host
23
+
24
+
25
+ ## Usage
26
+
27
+ For most applications, you can insert the middleware into the `config.ru` file
28
+ in the root of the application.
29
+
30
+ Here's a simple example of what the `config.ru` in a Rails application might
31
+ look like after adding the `Rack::CanonicalHost` middleware.
32
+
33
+ ``` ruby
34
+ require ::File.expand_path('../config/environment', __FILE__)
35
+
36
+ use Rack::CanonicalHost, 'example.com'
37
+ run YourRailsApp::Application
38
+ ```
39
+
40
+ In this case, any requests coming in that aren't for the specified host,
41
+ `example.com`, will be redirected, keeping the requested path intact.
42
+
43
+
44
+ ### Environment-Specific Configuration
45
+
46
+ You probably don't want your redirect to happen when developing locally. One
47
+ way to prevent this from happening is to use environment variables in your
48
+ production environment to set the canonical host name.
49
+
50
+ With Heroku, you would do this like so:
51
+
52
+ $ heroku config:add CANONICAL_HOST=example.com
53
+
54
+ Then, can configure the middleware like this:
55
+
56
+ ``` ruby
57
+ use Rack::CanonicalHost, ENV['CANONICAL_HOST'] if ENV['CANONICAL_HOST']
58
+ ```
59
+
60
+ Now, the middleware will only be used if a canonical host has been defined.
61
+
62
+
63
+ ### Options
64
+
65
+ If you'd like the middleware to ignore certain hosts, use the `:ignore_hosts`
66
+ option:
67
+
68
+ ``` ruby
69
+ use Rack::CanonicalHost, 'example.com', ignored_hosts: ['api.example.com']
70
+ ```
71
+
72
+ In this case, requests for the host `api.example.com` will not be redirected.
73
+
74
+ Alternatively, you can pass a block whose return value will be used as the
75
+ canonical host name.
76
+
77
+ ``` ruby
78
+ use Rack::CanonicalHost do
79
+ case ENV['RACK_ENV'].to_sym
80
+ when :staging then 'example.com'
81
+ when :production then 'staging.example.com'
82
+ end
83
+ end
84
+ ```
85
+
86
+
87
+ ## Contributors
88
+
89
+ Thanks to the following people who have contributed patches or helpful
90
+ suggestions:
91
+
92
+ * [Peter Baker](http://github.com/finack)
93
+ * [Jon Wood](http://github.com/jellybob)
94
+ * [Nathaniel Bibler](http://github.com/nbibler)
95
+ * [Eric Allam](http://github.com/rubymaverick)
96
+
97
+
data/Rakefile ADDED
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env rake
2
+
3
+ require 'bundler/gem_tasks'
@@ -1,30 +1 @@
1
- module Rack # :nodoc:
2
- class CanonicalHost
3
- def initialize(app, host=nil, &block)
4
- @app = app
5
- @host = host
6
- @block = block
7
- end
8
-
9
- def call(env)
10
- if url = url(env)
11
- [301, { 'Location' => url }, ['Redirecting...']]
12
- else
13
- @app.call(env)
14
- end
15
- end
16
-
17
- def url(env)
18
- if (host = host(env)) && env['SERVER_NAME'] != host
19
- url = Rack::Request.new(env).url
20
- url.sub(%r{\A(https?://)(.*?)(:\d+)?(/|$)}, "\\1#{host}\\3/")
21
- end
22
- end
23
- private :url
24
-
25
- def host(env)
26
- @block ? @block.call(env) || @host : @host
27
- end
28
- private :host
29
- end
30
- end
1
+ require 'rack/canonical_host'
@@ -0,0 +1,48 @@
1
+ require 'rack'
2
+
3
+ module Rack # :nodoc:
4
+ class CanonicalHost
5
+ HTML_TEMPLATE = <<-HTML
6
+ <!DOCTYPE html>
7
+ <html lang="en-US">
8
+ <head><title>301 Moved Permanently</title></head>
9
+ <body>
10
+ <h1>Moved Permanently</h1>
11
+ <p>The document has moved <a href="%s">here</a>.</p>
12
+ </body>
13
+ </html>
14
+ HTML
15
+
16
+ def initialize(app, host=nil, options={}, &block)
17
+ @app = app
18
+ @host = host
19
+ @block = block
20
+ @ignored_hosts = options[:ignored_hosts] || []
21
+ end
22
+
23
+ def call(env)
24
+ if url = url(env)
25
+ [
26
+ 301,
27
+ { 'Location' => url, 'Content-Type' => 'text/html' },
28
+ [HTML_TEMPLATE % url]
29
+ ]
30
+ else
31
+ @app.call(env)
32
+ end
33
+ end
34
+
35
+ def url(env)
36
+ if (host = host(env)) && env['SERVER_NAME'] != host && !@ignored_hosts.include?(env['SERVER_NAME'])
37
+ url = Rack::Request.new(env).url
38
+ url.sub(%r{\A(https?://)(.*?)(:\d+)?(/|$)}, "\\1#{host}\\3/")
39
+ end
40
+ end
41
+ private :url
42
+
43
+ def host(env)
44
+ @block ? @block.call(env) || @host : @host
45
+ end
46
+ private :host
47
+ end
48
+ end
@@ -0,0 +1,5 @@
1
+ module Rack
2
+ class CanonicalHost
3
+ VERSION = '0.0.4'
4
+ end
5
+ end
@@ -0,0 +1,17 @@
1
+ require './lib/rack/canonical_host/version'
2
+
3
+ Gem::Specification.new do |gem|
4
+ gem.name = 'rack-canonical-host'
5
+ gem.version = Rack::CanonicalHost::VERSION
6
+ gem.summary = 'Rack middleware for defining a canonical host name.'
7
+ gem.homepage = 'http://github.com/tylerhunt/rack-canonical-host'
8
+ gem.author = 'Tyler Hunt'
9
+
10
+ gem.add_dependency 'rack', '~> 1.0'
11
+ gem.add_development_dependency 'rspec', '~> 2.0'
12
+
13
+ gem.files = `git ls-files`.split($\)
14
+ gem.executables = gem.files.grep(%r{^bin/}).map { |f| File.basename(f) }
15
+ gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
16
+ gem.require_paths = ['lib']
17
+ end
@@ -0,0 +1,73 @@
1
+ require 'spec_helper'
2
+
3
+ describe Rack::CanonicalHost do
4
+ let(:response) { [200, { 'Content-Type' => 'text/plain' }, 'OK'] }
5
+ let(:inner_app) { lambda { |env| response } }
6
+
7
+ def build_app(host=nil, options={}, inner_app=inner_app, &block)
8
+ Rack::Builder.new do
9
+ use Rack::Lint
10
+ use Rack::CanonicalHost, host, options, &block
11
+ run inner_app
12
+ end
13
+ end
14
+
15
+ shared_context 'matching and non-matching requests' do
16
+ context 'with a request to a matching host' do
17
+ let(:url) { 'http://example.com/full/path' }
18
+
19
+ it { should_not be_redirect }
20
+
21
+ it 'calls the inner app' do
22
+ inner_app.should_receive(:call).with(env).and_return(response)
23
+ subject
24
+ end
25
+ end
26
+
27
+ context 'with a request to a non-matching host' do
28
+ let(:url) { 'http://www.example.com/full/path' }
29
+
30
+ it { should be_redirect.via(301).to('http://example.com/full/path') }
31
+
32
+ it 'does not call the inner app' do
33
+ inner_app.should_not_receive(:call)
34
+ subject
35
+ end
36
+ end
37
+ end
38
+
39
+ context '#call' do
40
+ let(:env) { Rack::MockRequest.env_for(url) }
41
+
42
+ subject { app.call(env) }
43
+
44
+ context 'without any options' do
45
+ let(:app) { build_app('example.com') }
46
+
47
+ include_context 'matching and non-matching requests'
48
+ end
49
+
50
+ context 'with ignored hosts' do
51
+ let(:app) { build_app('example.com', ignored_hosts: ['example.net']) }
52
+
53
+ include_context 'matching and non-matching requests'
54
+
55
+ context 'with a request to an ignored host' do
56
+ let(:url) { 'http://example.net/full/path' }
57
+
58
+ it { should_not be_redirect }
59
+
60
+ it 'calls the inner app' do
61
+ inner_app.should_receive(:call).with(env).and_return(response)
62
+ subject
63
+ end
64
+ end
65
+ end
66
+
67
+ context 'with a block' do
68
+ let(:app) { build_app { 'example.com' } }
69
+
70
+ include_context 'matching and non-matching requests'
71
+ end
72
+ end
73
+ end
@@ -0,0 +1,11 @@
1
+ require 'rack/canonical_host'
2
+
3
+ Dir[File.expand_path('../support/**/*.rb', __FILE__)].each do |file|
4
+ require(file)
5
+ end
6
+
7
+ RSpec.configure do |config|
8
+ config.treat_symbols_as_metadata_keys_with_true_values = true
9
+ config.run_all_when_everything_filtered = true
10
+ config.filter_run :focus
11
+ end
@@ -0,0 +1,67 @@
1
+ module BeRedirect
2
+ class Matcher
3
+ attr :expected_status_code
4
+ attr :expected_location
5
+ attr :actual_status_code
6
+ attr :actual_location
7
+
8
+ def matches?(response)
9
+ @actual_status_code, headers, _ = response
10
+ @actual_location = headers['Location']
11
+
12
+ status_code_matches? && location_matches?
13
+ end
14
+
15
+ def via(expected_status_code)
16
+ @expected_status_code = expected_status_code
17
+ self
18
+ end
19
+
20
+ def to(expected_location)
21
+ @expected_location = expected_location
22
+ self
23
+ end
24
+
25
+ def description
26
+ if expected_status_code && expected_location
27
+ "redirect via #{expected_status_code} to #{expected_location.inspect}"
28
+ elsif expected_status_code
29
+ "redirect via #{expected_status_code}"
30
+ elsif expected_location
31
+ "redirect to #{expected_location.inspect}"
32
+ else
33
+ "be a redirect"
34
+ end
35
+ end
36
+
37
+ def failure_message_for_should
38
+ "Expected response to #{description}"
39
+ end
40
+
41
+ def failure_message_for_should_not
42
+ "Did not expect response to #{description}"
43
+ end
44
+
45
+ def status_code_matches?
46
+ if expected_status_code
47
+ actual_status_code == expected_status_code
48
+ else
49
+ actual_status_code.to_s =~ /^30[1237]$/
50
+ end
51
+ end
52
+ private :status_code_matches?
53
+
54
+ def location_matches?
55
+ !expected_location || (expected_location == actual_location)
56
+ end
57
+ private :location_matches?
58
+ end
59
+
60
+ def be_redirect
61
+ Matcher.new
62
+ end
63
+ end
64
+
65
+ RSpec.configure do |config|
66
+ config.include(BeRedirect)
67
+ end
metadata CHANGED
@@ -1,80 +1,93 @@
1
- --- !ruby/object:Gem::Specification
1
+ --- !ruby/object:Gem::Specification
2
2
  name: rack-canonical-host
3
- version: !ruby/object:Gem::Version
4
- prerelease: false
5
- segments:
6
- - 0
7
- - 0
8
- - 3
9
- version: 0.0.3
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.4
5
+ prerelease:
10
6
  platform: ruby
11
- authors:
7
+ authors:
12
8
  - Tyler Hunt
13
9
  autorequire:
14
10
  bindir: bin
15
11
  cert_chain: []
16
-
17
- date: 2011-02-09 00:00:00 -05:00
18
- default_executable:
19
- dependencies:
20
- - !ruby/object:Gem::Dependency
12
+ date: 2012-06-20 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
21
15
  name: rack
22
- prerelease: false
23
- requirement: &id001 !ruby/object:Gem::Requirement
16
+ requirement: !ruby/object:Gem::Requirement
24
17
  none: false
25
- requirements:
26
- - - ">="
27
- - !ruby/object:Gem::Version
28
- segments:
29
- - 1
30
- - 0
31
- - 0
32
- version: 1.0.0
18
+ requirements:
19
+ - - ~>
20
+ - !ruby/object:Gem::Version
21
+ version: '1.0'
33
22
  type: :runtime
34
- version_requirements: *id001
23
+ prerelease: false
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ~>
28
+ - !ruby/object:Gem::Version
29
+ version: '1.0'
30
+ - !ruby/object:Gem::Dependency
31
+ name: rspec
32
+ requirement: !ruby/object:Gem::Requirement
33
+ none: false
34
+ requirements:
35
+ - - ~>
36
+ - !ruby/object:Gem::Version
37
+ version: '2.0'
38
+ type: :development
39
+ prerelease: false
40
+ version_requirements: !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ~>
44
+ - !ruby/object:Gem::Version
45
+ version: '2.0'
35
46
  description:
36
47
  email:
37
48
  executables: []
38
-
39
49
  extensions: []
40
-
41
50
  extra_rdoc_files: []
42
-
43
- files:
51
+ files:
52
+ - .gitignore
53
+ - .rspec
54
+ - CHANGELOG.md
55
+ - Gemfile
44
56
  - LICENSE
45
- - README.rdoc
57
+ - README.md
58
+ - Rakefile
46
59
  - lib/rack-canonical-host.rb
47
- has_rdoc: true
60
+ - lib/rack/canonical_host.rb
61
+ - lib/rack/canonical_host/version.rb
62
+ - rack-canonical-host.gemspec
63
+ - spec/rack/canonical_host_spec.rb
64
+ - spec/spec_helper.rb
65
+ - spec/support/matchers/be_redirect.rb
48
66
  homepage: http://github.com/tylerhunt/rack-canonical-host
49
67
  licenses: []
50
-
51
68
  post_install_message:
52
69
  rdoc_options: []
53
-
54
- require_paths:
70
+ require_paths:
55
71
  - lib
56
- required_ruby_version: !ruby/object:Gem::Requirement
72
+ required_ruby_version: !ruby/object:Gem::Requirement
57
73
  none: false
58
- requirements:
59
- - - ">="
60
- - !ruby/object:Gem::Version
61
- segments:
62
- - 0
63
- version: "0"
64
- required_rubygems_version: !ruby/object:Gem::Requirement
74
+ requirements:
75
+ - - ! '>='
76
+ - !ruby/object:Gem::Version
77
+ version: '0'
78
+ required_rubygems_version: !ruby/object:Gem::Requirement
65
79
  none: false
66
- requirements:
67
- - - ">="
68
- - !ruby/object:Gem::Version
69
- segments:
70
- - 0
71
- version: "0"
80
+ requirements:
81
+ - - ! '>='
82
+ - !ruby/object:Gem::Version
83
+ version: '0'
72
84
  requirements: []
73
-
74
85
  rubyforge_project:
75
- rubygems_version: 1.3.7
86
+ rubygems_version: 1.8.24
76
87
  signing_key:
77
88
  specification_version: 3
78
89
  summary: Rack middleware for defining a canonical host name.
79
- test_files: []
80
-
90
+ test_files:
91
+ - spec/rack/canonical_host_spec.rb
92
+ - spec/spec_helper.rb
93
+ - spec/support/matchers/be_redirect.rb
data/README.rdoc DELETED
@@ -1,32 +0,0 @@
1
- = Rack Canonical Host
2
-
3
- Rack Canonical Host is a bit of Rack middleware that lets you define a single
4
- host as the canonical host for your site, and redirect all other hostnames to
5
- that canonical host.
6
-
7
- In the simplest case, just specify the host name and any requests coming in
8
- that aren't for the host example.com will be rewritten with the proper host.
9
-
10
- use Rack::CanonicalHost, 'example.com'
11
-
12
- You could also define a constant in your environment-specific configuration
13
- files to set up a canonical host redirect for only certain environments.
14
-
15
- CANONICAL_HOST = 'example.com'
16
-
17
- Then, you can set up the middle are like this.
18
-
19
- use Rack::CanonicalHost, CANONICAL_HOST if defined?(CANONICAL_HOST)
20
-
21
- Alternatively, you can pass a block whose return value will be used to set the
22
- canonical host.
23
-
24
- use Rack::CanonicalHost do
25
- case ENV['RACK_ENV'].to_sym
26
- when :staging then 'example.com'
27
- when :production then 'staging.example.com'
28
- end
29
- end
30
-
31
-
32
- Copyright (c) 2009 Tyler Hunt. See LICENSE for details.