rack-domain 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.
- checksums.yaml +7 -0
- data/.gitignore +14 -0
- data/.travis.yml +6 -0
- data/.yardopts +1 -0
- data/Gemfile +8 -0
- data/LICENSE.txt +22 -0
- data/README.md +28 -0
- data/Rakefile +8 -0
- data/lib/rack/domain/dsl.rb +16 -0
- data/lib/rack/domain/version.rb +7 -0
- data/lib/rack/domain.rb +63 -0
- data/rack-domain.gemspec +33 -0
- data/test/subdomainer_test.rb +106 -0
- data/test/test_helper.rb +11 -0
- metadata +132 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 8f490d3f568d69528c7cc2079b82eb2eaa884096
|
4
|
+
data.tar.gz: 8f884b4ae54e454b95e5084c7476e79b3046bb16
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 3bf3fb2d14a573071bb4d42e26dbbae1d74f7c1ded555d546160b21c8200703e7f5c8672062f2438c5775f665d5d090f6f2d056d2f50689065b8d2b7e621a86a
|
7
|
+
data.tar.gz: dc2f9e6d7c1bc047cd8ecdfb2c9d00460286b14a0ed62447cd74c603d7c7c8052837b946a26697ccc8b20bc927f3bb9b49fb4b787f26886864a742b6daa00fe6
|
data/.gitignore
ADDED
data/.travis.yml
ADDED
data/.yardopts
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
--markup markdown
|
data/Gemfile
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2014 Andrea Leopardi
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,28 @@
|
|
1
|
+
# Rack::Domain
|
2
|
+
|
3
|
+
|
4
|
+
## Installation
|
5
|
+
|
6
|
+
Add this line to your application's Gemfile:
|
7
|
+
|
8
|
+
```ruby
|
9
|
+
gem 'rack-domain'
|
10
|
+
```
|
11
|
+
|
12
|
+
And then execute:
|
13
|
+
|
14
|
+
$ bundle
|
15
|
+
|
16
|
+
Or install it yourself as:
|
17
|
+
|
18
|
+
$ gem install rack-domain
|
19
|
+
|
20
|
+
|
21
|
+
## Contributing
|
22
|
+
|
23
|
+
Fork, make changes, commit, open Pull Request! Read the [GitHub guide to
|
24
|
+
forking][forking] if you don't know how to.
|
25
|
+
|
26
|
+
|
27
|
+
|
28
|
+
[forking]: https://help.github.com/articles/fork-a-repo/
|
data/Rakefile
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
require 'rack/domain'
|
2
|
+
|
3
|
+
# This class is monkeypatched with the `#domain` method.
|
4
|
+
class Rack::Builder
|
5
|
+
# Behaves just like `use Rack::Domain`, but with a simpler and clearer syntax.
|
6
|
+
#
|
7
|
+
# @param [String, Regexp] filter The filter used to match the domain.
|
8
|
+
# @param [Hash] opts An hash of options.
|
9
|
+
# @option opts [#call, nil] :run The app to run if the domain matches.
|
10
|
+
#
|
11
|
+
# @raise [ArgumentError] if no app to run or block were passed, or if both
|
12
|
+
# were passed.
|
13
|
+
def domain(filter, opts = {}, &block)
|
14
|
+
use(Rack::Domain, filter, opts, &block)
|
15
|
+
end
|
16
|
+
end
|
data/lib/rack/domain.rb
ADDED
@@ -0,0 +1,63 @@
|
|
1
|
+
require 'rack/domain/version'
|
2
|
+
|
3
|
+
# This Rack middleware allows to intercept requests and route them to different
|
4
|
+
# apps based on the domain (full, with subdomains and the TLD).
|
5
|
+
class Rack::Domain
|
6
|
+
# Create a new instance of this middleware.
|
7
|
+
# **Note** that this method is the method called by `Rack::Builder#use`.
|
8
|
+
#
|
9
|
+
# @param [#call] next_app The next app on the stack, filled automatically by
|
10
|
+
# Rack when building the middlware chain.
|
11
|
+
# @param [String, Regexp] filter The filter used to, well, filter the domain.
|
12
|
+
# If `filter` is a `String`, it will be matched *at the beginning* of the
|
13
|
+
# domain name; this is done so that it's easy to match subdomains and
|
14
|
+
# domains without TLDs.
|
15
|
+
# @param [Hash] opts An hash of options.
|
16
|
+
# @option opts [#call, nil] :run The Rack app to run if the domain matches the
|
17
|
+
# filter. If you don't want to pass a ready application, you can pass a
|
18
|
+
# block with `Rack::Builder` syntax which will create a Rack app on-the-fly.
|
19
|
+
# @raise [ArgumentError] if both a building block and an app to run were
|
20
|
+
# passed to this function.
|
21
|
+
def initialize(next_app, filter, opts = {}, &block)
|
22
|
+
if opts[:run] && block_given?
|
23
|
+
fail ArgumentError, 'Pass either an app to run or a block, not both'
|
24
|
+
end
|
25
|
+
|
26
|
+
@next_app = next_app
|
27
|
+
@filter = filter
|
28
|
+
@app_to_run = opts[:run]
|
29
|
+
@dsl_block = block
|
30
|
+
end
|
31
|
+
|
32
|
+
# The `call` method as per the Rack middleware specification.
|
33
|
+
# @param [Hash] env The environment passed around in the middlware chain.
|
34
|
+
def call(env)
|
35
|
+
@domain = Rack::Request.new(env).host
|
36
|
+
app = domain_matches? ? app_or_dsl_block : @next_app
|
37
|
+
app.call(env)
|
38
|
+
end
|
39
|
+
|
40
|
+
private
|
41
|
+
|
42
|
+
# Return the app that was specified to be run if the domain matches or, if the
|
43
|
+
# app was specified on-the-fly with a builder block, return a new app created
|
44
|
+
# with that block (and `Rack::Builder`).
|
45
|
+
# @return [#call]
|
46
|
+
def app_or_dsl_block
|
47
|
+
@app_to_run || Rack::Builder.new(&@dsl_block)
|
48
|
+
end
|
49
|
+
|
50
|
+
# Return `true` if the domain of the current request matches the given
|
51
|
+
# `@filter`, `false` otherwise.
|
52
|
+
# @return [Boolean]
|
53
|
+
def domain_matches?
|
54
|
+
case @filter
|
55
|
+
when Regexp
|
56
|
+
@filter =~ @domain
|
57
|
+
when String
|
58
|
+
@domain.start_with?(@filter)
|
59
|
+
else
|
60
|
+
fail 'The filter must be a Regexp or a String'
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
data/rack-domain.gemspec
ADDED
@@ -0,0 +1,33 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'rack/domain/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = 'rack-domain'
|
8
|
+
spec.version = Rack::Domain::VERSION
|
9
|
+
spec.authors = ['Andrea Leopardi']
|
10
|
+
spec.email = 'an.leopardi@gmail.com'
|
11
|
+
spec.homepage = 'https://github.com/whatyouhide/rack-domain'
|
12
|
+
spec.license = 'MIT'
|
13
|
+
spec.summary = <<-SUMMARY
|
14
|
+
Rack middleware for dispatching Rack apps based on the domain'
|
15
|
+
SUMMARY
|
16
|
+
spec.description = <<-DESCRIPTION
|
17
|
+
This Rack middleware allows you to run specific apps when the request
|
18
|
+
domain matches a given filter. The filter can be provided in a number of
|
19
|
+
ways, for example as a regex or as a string.
|
20
|
+
DESCRIPTION
|
21
|
+
|
22
|
+
spec.files = `git ls-files -z`.split("\x0")
|
23
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
24
|
+
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
25
|
+
spec.require_paths = ['lib']
|
26
|
+
|
27
|
+
spec.add_runtime_dependency 'rack', '>= 1.5'
|
28
|
+
|
29
|
+
spec.add_development_dependency 'bundler', '~> 1.6'
|
30
|
+
spec.add_development_dependency 'rake', '~> 10'
|
31
|
+
spec.add_development_dependency 'minitest', '~> 5'
|
32
|
+
spec.add_development_dependency 'minitest-reporters', '~> 1'
|
33
|
+
end
|
@@ -0,0 +1,106 @@
|
|
1
|
+
require_relative 'test_helper'
|
2
|
+
|
3
|
+
NOT_FOUNDER = lambda { |env| [404, {}, ['Error']] }
|
4
|
+
LOBSTER = Rack::Builder.new do
|
5
|
+
map('/lobster') { run Rack::Lobster.new }
|
6
|
+
map('/') { run NOT_FOUNDER }
|
7
|
+
end
|
8
|
+
|
9
|
+
class DomainTest < Minitest::Test
|
10
|
+
include Rack::Test::Methods
|
11
|
+
|
12
|
+
BASE_URL = 'http://example.com'
|
13
|
+
BASE_URL_WITH_SUBDOMAIN = 'http://api.example.com'
|
14
|
+
|
15
|
+
def test_with_a_string
|
16
|
+
%w(api api.example api.example.com).each do |str|
|
17
|
+
set_app_to do
|
18
|
+
use Rack::Domain, str, run: Rack::Lobster.new
|
19
|
+
run NOT_FOUNDER
|
20
|
+
end
|
21
|
+
|
22
|
+
assert_dispatches_to_the_right_app
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
def test_with_regexps
|
27
|
+
[/^api\./, /.+/, /example/, /\.com$/].each do |regexp|
|
28
|
+
set_app_to do
|
29
|
+
use Rack::Domain, regexp, run: Rack::Lobster.new
|
30
|
+
run NOT_FOUNDER
|
31
|
+
end
|
32
|
+
|
33
|
+
assert_dispatches_to_the_right_app
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
def test_with_a_block
|
38
|
+
['api', 'api.exam', /example/, /\.com$/].each do |filter|
|
39
|
+
set_app_to do
|
40
|
+
use Rack::Domain, filter do
|
41
|
+
run Rack::Lobster.new
|
42
|
+
end
|
43
|
+
|
44
|
+
run NOT_FOUNDER
|
45
|
+
end
|
46
|
+
|
47
|
+
assert_dispatches_to_the_right_app
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
def test_rack_builder_dsl_extension
|
52
|
+
require 'rack/domain/dsl'
|
53
|
+
|
54
|
+
set_app_to do
|
55
|
+
domain 'api', run: Rack::Lobster.new
|
56
|
+
run NOT_FOUNDER
|
57
|
+
end
|
58
|
+
assert_dispatches_to_the_right_app
|
59
|
+
|
60
|
+
set_app_to do
|
61
|
+
domain /^api\./, run: Rack::Lobster.new
|
62
|
+
run NOT_FOUNDER
|
63
|
+
end
|
64
|
+
assert_dispatches_to_the_right_app
|
65
|
+
end
|
66
|
+
|
67
|
+
def test_argument_errors
|
68
|
+
assert_app_raises ArgumentError do
|
69
|
+
lob = Rack::Lobster.new
|
70
|
+
use(Rack::Domain, 'api', { run: Rack::Lobster.new }) { lob }
|
71
|
+
run lob
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
private
|
76
|
+
|
77
|
+
def set_app_to(app = nil, &block)
|
78
|
+
define_singleton_method(:app) do
|
79
|
+
app || Rack::Builder.new(&block)
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
def assert_app_raises(error, &block)
|
84
|
+
assert_raises error do
|
85
|
+
set_app_to(&block)
|
86
|
+
get '/'
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
def assert_dispatches_to_the_right_app
|
91
|
+
get BASE_URL
|
92
|
+
assert last_response.not_found?,
|
93
|
+
'The app was intercepted when it should not have been'
|
94
|
+
|
95
|
+
get BASE_URL_WITH_SUBDOMAIN
|
96
|
+
assert_lobster_responded
|
97
|
+
end
|
98
|
+
|
99
|
+
def assert_lobster_responded
|
100
|
+
assert last_response.ok?,
|
101
|
+
"The response was #{last_response.status} instead of 200 OK"
|
102
|
+
assert last_response.body.include?('Lobstericious'),
|
103
|
+
'The run app was not Rack::Lobster'
|
104
|
+
end
|
105
|
+
|
106
|
+
end
|
data/test/test_helper.rb
ADDED
metadata
ADDED
@@ -0,0 +1,132 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: rack-domain
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Andrea Leopardi
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2014-10-23 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: rack
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ">="
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '1.5'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ">="
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '1.5'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: bundler
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '1.6'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '1.6'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: rake
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '10'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '10'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: minitest
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - "~>"
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '5'
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - "~>"
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '5'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: minitest-reporters
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - "~>"
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '1'
|
76
|
+
type: :development
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - "~>"
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '1'
|
83
|
+
description: |2
|
84
|
+
This Rack middleware allows you to run specific apps when the request
|
85
|
+
domain matches a given filter. The filter can be provided in a number of
|
86
|
+
ways, for example as a regex or as a string.
|
87
|
+
email: an.leopardi@gmail.com
|
88
|
+
executables: []
|
89
|
+
extensions: []
|
90
|
+
extra_rdoc_files: []
|
91
|
+
files:
|
92
|
+
- ".gitignore"
|
93
|
+
- ".travis.yml"
|
94
|
+
- ".yardopts"
|
95
|
+
- Gemfile
|
96
|
+
- LICENSE.txt
|
97
|
+
- README.md
|
98
|
+
- Rakefile
|
99
|
+
- lib/rack/domain.rb
|
100
|
+
- lib/rack/domain/dsl.rb
|
101
|
+
- lib/rack/domain/version.rb
|
102
|
+
- rack-domain.gemspec
|
103
|
+
- test/subdomainer_test.rb
|
104
|
+
- test/test_helper.rb
|
105
|
+
homepage: https://github.com/whatyouhide/rack-domain
|
106
|
+
licenses:
|
107
|
+
- MIT
|
108
|
+
metadata: {}
|
109
|
+
post_install_message:
|
110
|
+
rdoc_options: []
|
111
|
+
require_paths:
|
112
|
+
- lib
|
113
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
114
|
+
requirements:
|
115
|
+
- - ">="
|
116
|
+
- !ruby/object:Gem::Version
|
117
|
+
version: '0'
|
118
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
119
|
+
requirements:
|
120
|
+
- - ">="
|
121
|
+
- !ruby/object:Gem::Version
|
122
|
+
version: '0'
|
123
|
+
requirements: []
|
124
|
+
rubyforge_project:
|
125
|
+
rubygems_version: 2.2.2
|
126
|
+
signing_key:
|
127
|
+
specification_version: 4
|
128
|
+
summary: Rack middleware for dispatching Rack apps based on the domain'
|
129
|
+
test_files:
|
130
|
+
- test/subdomainer_test.rb
|
131
|
+
- test/test_helper.rb
|
132
|
+
has_rdoc:
|