rack-canonical-host 0.0.3 → 0.0.4

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/.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.