redirect 0.3.2 → 0.4.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +4 -0
- data/Gemfile +4 -0
- data/README.md +63 -0
- data/Rakefile +1 -18
- data/autotest/discover.rb +1 -0
- data/lib/redirect.rb +3 -105
- data/lib/redirect/app.rb +123 -0
- data/lib/redirect/redirect.rb +63 -0
- data/lib/redirect/test.rb +3 -2
- data/lib/redirect/version.rb +3 -0
- data/redirect.gemspec +23 -0
- data/spec/fixtures/private +1 -0
- data/spec/fixtures/public/index.html +5 -0
- data/spec/helper.rb +5 -5
- data/spec/rack_spec.rb +224 -122
- metadata +51 -24
- data/README.txt +0 -70
data/.gitignore
ADDED
data/Gemfile
ADDED
data/README.md
ADDED
@@ -0,0 +1,63 @@
|
|
1
|
+
# Redirect
|
2
|
+
|
3
|
+
http://github.com/p8/redirect/tree/master
|
4
|
+
|
5
|
+
## Description
|
6
|
+
Redirect is a simple Ruby redirect DSL built on Rack.
|
7
|
+
It's like a simple Ruby mod_rewrite, so you can write and test your redirects in Ruby.
|
8
|
+
|
9
|
+
## Getting started
|
10
|
+
- Install the gem `gem install redirect`
|
11
|
+
- Create a new redirect rack app: `redirect_app my_redirect_app`
|
12
|
+
- This creates a directory called `my_redirect_app` with the required files and tests.
|
13
|
+
- Open `my_redirect_app/my_redirect_app.rb` in your favorite editor and add some redirect rules.
|
14
|
+
|
15
|
+
To run the app locally just run the main rb file: `ruby my_redirect_app.rb`.
|
16
|
+
|
17
|
+
## Defining redirects
|
18
|
+
Redirects are processed in the same order as they are defined:
|
19
|
+
|
20
|
+
redirect ['/catch_url', '/redirect_url'], ['/catch_url2', '/redirect_url2']
|
21
|
+
|
22
|
+
The first one is evaluated first, then the next one, etc..
|
23
|
+
The catch_url can be a regular expression:
|
24
|
+
|
25
|
+
['^/some_regexp', '/all']
|
26
|
+
[/old\/(.*)/, '/new/$1'] # /old/2008/02/01 will be redirected to /new/2008/02/01
|
27
|
+
|
28
|
+
You can also pass extra options as follows:
|
29
|
+
|
30
|
+
:code # Overwrite the http code (defaults is 301) in the options,
|
31
|
+
:name # named redirects are public so they'll appear in you sitemap.
|
32
|
+
['/catch_url', '/redirect_url', {:code => 307, :name => 'redirect link'}]`
|
33
|
+
|
34
|
+
The default redirect code can be changed by specifying:
|
35
|
+
|
36
|
+
Redirect.default_code = 307
|
37
|
+
|
38
|
+
All redirects with a name will be specified in the generated /sitemap.xml.
|
39
|
+
|
40
|
+
## License
|
41
|
+
|
42
|
+
(The MIT License)
|
43
|
+
|
44
|
+
Copyright (c) 2009 Petrik de Heus
|
45
|
+
|
46
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
47
|
+
a copy of this software and associated documentation files (the
|
48
|
+
'Software'), to deal in the Software without restriction, including
|
49
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
50
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
51
|
+
permit persons to whom the Software is furnished to do so, subject to
|
52
|
+
the following conditions:
|
53
|
+
|
54
|
+
The above copyright notice and this permission notice shall be
|
55
|
+
included in all copies or substantial portions of the Software.
|
56
|
+
|
57
|
+
THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
|
58
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
59
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
60
|
+
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
61
|
+
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
62
|
+
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
63
|
+
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/Rakefile
CHANGED
@@ -1,18 +1 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
require 'rubygems'
|
4
|
-
require 'lib/redirect.rb'
|
5
|
-
|
6
|
-
require 'hoe' rescue nil
|
7
|
-
if defined? Hoe
|
8
|
-
Hoe.new('redirect', Redirect::VERSION) do |p|
|
9
|
-
p.developer('Petrik de Heus', 'FIX@example.com')
|
10
|
-
p.remote_rdoc_dir = '' # Release to root
|
11
|
-
end
|
12
|
-
end
|
13
|
-
|
14
|
-
# require 'metric_fu'
|
15
|
-
#
|
16
|
-
# MetricFu::Configuration.run do |config|
|
17
|
-
# config.coverage = { :test_files => ['spec/**/*_spec.rb'] }
|
18
|
-
# end
|
1
|
+
require 'bundler/gem_tasks'
|
@@ -0,0 +1 @@
|
|
1
|
+
Autotest.add_discovery { "rspec2" }
|
data/lib/redirect.rb
CHANGED
@@ -1,110 +1,8 @@
|
|
1
|
-
require '
|
1
|
+
require 'redirect/version'
|
2
2
|
require 'rack'
|
3
3
|
require 'rack/showexceptions'
|
4
4
|
require 'rack/request'
|
5
5
|
require 'rack/response'
|
6
|
+
require 'redirect/redirect'
|
7
|
+
require 'redirect/app'
|
6
8
|
|
7
|
-
module Redirect
|
8
|
-
VERSION = '0.3.2'
|
9
|
-
|
10
|
-
def self.default_code= default_code
|
11
|
-
@default_code = default_code
|
12
|
-
end
|
13
|
-
|
14
|
-
def self.default_code
|
15
|
-
@default_code ||= 301
|
16
|
-
end
|
17
|
-
|
18
|
-
def self.autorun= autorun
|
19
|
-
@autorun = autorun
|
20
|
-
end
|
21
|
-
|
22
|
-
def self.autorun
|
23
|
-
@autorun = true unless @autorun == false
|
24
|
-
@autorun
|
25
|
-
end
|
26
|
-
|
27
|
-
def self.app= app
|
28
|
-
@app = app
|
29
|
-
end
|
30
|
-
|
31
|
-
def self.app
|
32
|
-
@app
|
33
|
-
end
|
34
|
-
|
35
|
-
class Data
|
36
|
-
attr_reader :catch_url, :redirect_url, :code, :name
|
37
|
-
def initialize(catch_url, redirect_url, options = {})
|
38
|
-
@catch_url = catch_url
|
39
|
-
@redirect_url = redirect_url
|
40
|
-
@code = options[:code] || Redirect.default_code
|
41
|
-
@name = options[:name]
|
42
|
-
end
|
43
|
-
end
|
44
|
-
|
45
|
-
end
|
46
|
-
|
47
|
-
def redirect(*redirects)
|
48
|
-
|
49
|
-
Redirect.app = Rack::Redirect.new(*redirects)
|
50
|
-
if Redirect.autorun
|
51
|
-
Rack::Handler::WEBrick.run \
|
52
|
-
Rack::ShowExceptions.new(Rack::Lint.new(Redirect.app)),
|
53
|
-
:Port => 3000
|
54
|
-
run Redirect.app
|
55
|
-
end
|
56
|
-
end
|
57
|
-
|
58
|
-
module Rack
|
59
|
-
|
60
|
-
class Redirect
|
61
|
-
attr_reader :redirects
|
62
|
-
def initialize(*redirects)
|
63
|
-
@redirects = redirects.collect do |r|
|
64
|
-
::Redirect::Data.new(*r)
|
65
|
-
end
|
66
|
-
end
|
67
|
-
|
68
|
-
def call(env)
|
69
|
-
req = Request.new(env)
|
70
|
-
if req.fullpath == '/sitemap.xml'
|
71
|
-
return [200, {"Content-Type" => "text/xml"}, sitemap(req.host)]
|
72
|
-
end
|
73
|
-
if req.fullpath == '/' && index
|
74
|
-
return [200, {"Content-Type" => "text/html"}, index]
|
75
|
-
end
|
76
|
-
@redirects.each do |r|
|
77
|
-
if req.fullpath.match(r.catch_url)
|
78
|
-
redirect_url = r.redirect_url
|
79
|
-
if $1
|
80
|
-
redirect_url.gsub!('$1', $1)
|
81
|
-
end
|
82
|
-
puts "Match found for #{r.catch_url}."
|
83
|
-
puts "Redirecting to #{redirect_url}"
|
84
|
-
return [r.code, {"Location" => redirect_url, "Content-Type" => "text/html"}, "Redirecting to: #{redirect_url}"]
|
85
|
-
end
|
86
|
-
end
|
87
|
-
[404, {"Content-Type" => "text/html"}, "not found"]
|
88
|
-
end
|
89
|
-
|
90
|
-
def sitemap(host)
|
91
|
-
%(<?xml version="1.0" encoding="UTF-8"?>\n) +
|
92
|
-
%(<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">\n) +
|
93
|
-
@redirects.select{|r| r.name }.collect { |r|
|
94
|
-
%(<url>\n) +
|
95
|
-
%(<loc>http://#{host}#{r.redirect_url}</loc>\n) +
|
96
|
-
%(</url>\n)}.join +
|
97
|
-
%(</urlset>\n)
|
98
|
-
end
|
99
|
-
|
100
|
-
def index
|
101
|
-
@index
|
102
|
-
end
|
103
|
-
|
104
|
-
def index= index
|
105
|
-
@index = index
|
106
|
-
end
|
107
|
-
|
108
|
-
end
|
109
|
-
|
110
|
-
end
|
data/lib/redirect/app.rb
ADDED
@@ -0,0 +1,123 @@
|
|
1
|
+
module Redirect
|
2
|
+
|
3
|
+
class App
|
4
|
+
|
5
|
+
class StaticFile
|
6
|
+
def initialize(path)
|
7
|
+
@path = path
|
8
|
+
end
|
9
|
+
|
10
|
+
def available?
|
11
|
+
expanded_path && expanded_path == path and File.file?(expanded_path)
|
12
|
+
end
|
13
|
+
|
14
|
+
def path
|
15
|
+
@path
|
16
|
+
end
|
17
|
+
|
18
|
+
def expanded_path
|
19
|
+
@static_file_expanded_path ||= File.expand_path(path)
|
20
|
+
end
|
21
|
+
|
22
|
+
end
|
23
|
+
|
24
|
+
attr_reader :redirects
|
25
|
+
attr_accessor :public_dir
|
26
|
+
|
27
|
+
def initialize(*redirects)
|
28
|
+
@redirects = redirects.collect do |r|
|
29
|
+
Data.new(*r)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
def call(env)
|
34
|
+
@env = env
|
35
|
+
@request = Rack::Request.new(env)
|
36
|
+
if static_file.available?
|
37
|
+
return static_response
|
38
|
+
end
|
39
|
+
if request.fullpath == '/sitemap.xml'
|
40
|
+
return sitemap_response
|
41
|
+
end
|
42
|
+
if request.fullpath == '/' && index_file.available?
|
43
|
+
return index_response
|
44
|
+
end
|
45
|
+
@redirects.each do |r|
|
46
|
+
if r.matches?(request.fullpath)
|
47
|
+
return redirects_response(r)
|
48
|
+
end
|
49
|
+
end
|
50
|
+
not_found_response
|
51
|
+
end
|
52
|
+
|
53
|
+
def public_dir
|
54
|
+
@public_dir ||= 'public'
|
55
|
+
end
|
56
|
+
|
57
|
+
private
|
58
|
+
def env
|
59
|
+
@env
|
60
|
+
end
|
61
|
+
|
62
|
+
def request
|
63
|
+
@request
|
64
|
+
end
|
65
|
+
|
66
|
+
def index_response
|
67
|
+
send_file(index_file.expanded_path)
|
68
|
+
end
|
69
|
+
|
70
|
+
def index_file
|
71
|
+
@index_file ||= StaticFile.new(File.join(public_dir_path, 'index.html'))
|
72
|
+
end
|
73
|
+
|
74
|
+
def public_dir_path
|
75
|
+
@public_dir_path ||= File.expand_path(public_dir)
|
76
|
+
end
|
77
|
+
|
78
|
+
def not_found_response
|
79
|
+
[404, {"Content-Type" => "text/html"}, ["not found"]]
|
80
|
+
end
|
81
|
+
|
82
|
+
def redirects_response(r)
|
83
|
+
puts "Match found for #{r.catch_url}."
|
84
|
+
puts "Redirecting to #{r.redirect_url}"
|
85
|
+
return [r.code, {"Location" => r.redirect_url, "Content-Type" => "text/html"}, ["Redirecting to: #{r.redirect_url}"]]
|
86
|
+
end
|
87
|
+
|
88
|
+
def send_file(path, opts={})
|
89
|
+
# if opts[:type] or not response['Content-Type']
|
90
|
+
# content_type ::File.extname(path), :default => 'application/octet-stream'
|
91
|
+
# end
|
92
|
+
# last_modified opts[:last_modified] if opts[:last_modified]
|
93
|
+
file = Rack::File.new public_dir_path
|
94
|
+
file.path = path
|
95
|
+
file.serving env
|
96
|
+
rescue Errno::ENOENT
|
97
|
+
not_found_response
|
98
|
+
end
|
99
|
+
|
100
|
+
def sitemap_response
|
101
|
+
[200, {"Content-Type" => "text/xml"}, [sitemap(request.host)]]
|
102
|
+
end
|
103
|
+
|
104
|
+
def sitemap(host)
|
105
|
+
%(<?xml version="1.0" encoding="UTF-8"?>\n) +
|
106
|
+
%(<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">\n) +
|
107
|
+
@redirects.select{|r| r.name }.collect { |r|
|
108
|
+
%(<url>\n) +
|
109
|
+
%(<loc>http://#{host}#{r.redirect_url}</loc>\n) +
|
110
|
+
%(</url>\n)}.join +
|
111
|
+
%(</urlset>\n)
|
112
|
+
end
|
113
|
+
|
114
|
+
def static_file
|
115
|
+
@static_file ||= StaticFile.new(public_dir_path + URI.unescape(request.path_info))
|
116
|
+
end
|
117
|
+
|
118
|
+
def static_response
|
119
|
+
send_file static_file.expanded_path
|
120
|
+
end
|
121
|
+
|
122
|
+
end
|
123
|
+
end
|
@@ -0,0 +1,63 @@
|
|
1
|
+
module Redirect
|
2
|
+
|
3
|
+
def self.default_code= default_code
|
4
|
+
@default_code = default_code
|
5
|
+
end
|
6
|
+
|
7
|
+
def self.default_code
|
8
|
+
@default_code ||= 301
|
9
|
+
end
|
10
|
+
|
11
|
+
def self.autorun= autorun
|
12
|
+
@autorun = autorun
|
13
|
+
end
|
14
|
+
|
15
|
+
def self.autorun
|
16
|
+
@autorun = true unless @autorun == false
|
17
|
+
@autorun
|
18
|
+
end
|
19
|
+
|
20
|
+
def self.app= app
|
21
|
+
@app = app
|
22
|
+
end
|
23
|
+
|
24
|
+
def self.app
|
25
|
+
@app
|
26
|
+
end
|
27
|
+
|
28
|
+
class Data
|
29
|
+
attr_reader :catch_url, :code, :match, :name
|
30
|
+
def initialize(catch_url, redirect_url, options = {})
|
31
|
+
@catch_url = catch_url
|
32
|
+
@redirect_url = redirect_url
|
33
|
+
@code = options[:code] || Redirect.default_code
|
34
|
+
@name = options[:name]
|
35
|
+
end
|
36
|
+
|
37
|
+
def matches?(url)
|
38
|
+
matched = url.match(catch_url)
|
39
|
+
@match = $1
|
40
|
+
matched
|
41
|
+
end
|
42
|
+
|
43
|
+
def redirect_url
|
44
|
+
if @match
|
45
|
+
@redirect_url.gsub('$1', @match)
|
46
|
+
else
|
47
|
+
@redirect_url
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
end
|
53
|
+
|
54
|
+
def redirect(*redirects)
|
55
|
+
|
56
|
+
Redirect.app = Redirect::App.new(*redirects)
|
57
|
+
if Redirect.autorun
|
58
|
+
Rack::Handler::WEBrick.run \
|
59
|
+
Rack::ShowExceptions.new(Rack::Lint.new(Redirect.app)),
|
60
|
+
:Port => 3000
|
61
|
+
run Redirect.app
|
62
|
+
end
|
63
|
+
end
|
data/lib/redirect/test.rb
CHANGED
@@ -5,7 +5,8 @@ class Test::Unit::TestCase
|
|
5
5
|
|
6
6
|
def assert_redirects(from, to)
|
7
7
|
res = Rack::MockRequest.new(APP[:redirect_app]).get(from)
|
8
|
-
assert_equal
|
8
|
+
assert_equal to, res.headers['Location' ]
|
9
|
+
assert_equal 'text/html', res.headers['Content-Type']
|
9
10
|
end
|
10
11
|
|
11
12
|
end
|
@@ -14,4 +15,4 @@ APP = {}
|
|
14
15
|
|
15
16
|
def redirect(*redirects)
|
16
17
|
APP[:redirect_app] = Rack::Redirect.new(*redirects)
|
17
|
-
end
|
18
|
+
end
|
data/redirect.gemspec
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
$:.push File.expand_path("../lib", __FILE__)
|
3
|
+
require "redirect/version"
|
4
|
+
|
5
|
+
Gem::Specification.new do |s|
|
6
|
+
s.authors = ["Petrik de Heus"]
|
7
|
+
s.default_executable = %q{redirect_app}
|
8
|
+
s.name = "redirect"
|
9
|
+
s.version = Redirect::VERSION
|
10
|
+
s.email = ["FIX@email.com"]
|
11
|
+
s.homepage = "http://github.com/p8/redirect/tree/master"
|
12
|
+
s.summary = %q{Redirect is a simple Ruby redirect DSL build on Rack}
|
13
|
+
s.description = %q{Redirect is a simple Ruby redirect DSL build on Rack. It's like a simple Ruby mod_rewrite, so you can write and test your redirects in Ruby.}
|
14
|
+
|
15
|
+
s.rubyforge_project = "redirect"
|
16
|
+
s.files = `git ls-files`.split("\n")
|
17
|
+
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
18
|
+
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
19
|
+
s.require_paths = ["lib"]
|
20
|
+
|
21
|
+
s.add_dependency 'rack', '~> 1.3', '>= 1.3.4'
|
22
|
+
s.add_development_dependency "rspec"
|
23
|
+
end
|
@@ -0,0 +1 @@
|
|
1
|
+
hidden
|
data/spec/helper.rb
CHANGED
@@ -1,7 +1,7 @@
|
|
1
|
-
require 'rubygems'
|
2
|
-
require 'test/unit'
|
3
|
-
require 'test/spec'
|
4
|
-
require 'mocha'
|
1
|
+
# require 'rubygems'
|
2
|
+
# require 'test/unit'
|
3
|
+
# require 'test/spec'
|
4
|
+
# require 'mocha'
|
5
5
|
|
6
6
|
$:.unshift File.dirname(File.dirname(__FILE__)) + "/lib"
|
7
|
-
require 'redirect'
|
7
|
+
require 'redirect'
|
data/spec/rack_spec.rb
CHANGED
@@ -1,110 +1,206 @@
|
|
1
1
|
require File.dirname(__FILE__) + '/helper'
|
2
2
|
|
3
|
-
describe "
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
3
|
+
describe "Redirect::App" do
|
4
|
+
|
5
|
+
describe "/" do
|
6
|
+
context "no redirect matches" do
|
7
|
+
it "returns a 404 if no index exists" do
|
8
|
+
@app = Redirect::App.new
|
9
|
+
get '/'
|
10
|
+
status.should == 404
|
11
|
+
res["Content-Type"].should == "text/html"
|
12
|
+
body.should == "not found"
|
13
|
+
end
|
14
|
+
|
15
|
+
it "returns a index.html if it exists" do
|
16
|
+
@app = Redirect::App.new
|
17
|
+
@app.public_dir = 'spec/fixtures/public'
|
18
|
+
get '/'
|
19
|
+
status.should == 200
|
20
|
+
body.should == File.read('spec/fixtures/public/index.html')
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
context "a redirect matches" do
|
25
|
+
it "should redirect '/' if redirect exists" do
|
26
|
+
@app = Redirect::App.new(['/', '/test'])
|
27
|
+
get '/'
|
28
|
+
headers['Location'].should == '/test'
|
29
|
+
headers['Content-Type'].should == 'text/html'
|
30
|
+
body.should == 'Redirecting to: /test'
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
describe "/sitemap.xml" do
|
36
|
+
it "returns the sitemap xml" do
|
37
|
+
@app = Redirect::App.new(['/', '/test', {:name => 'test'}])
|
38
|
+
get '/sitemap.xml'
|
39
|
+
headers['Content-Type'].should == 'text/xml'
|
40
|
+
body.should == %(<?xml version="1.0" encoding="UTF-8"?>\n) +
|
41
|
+
%(<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">\n) +
|
42
|
+
%(<url>\n) +
|
43
|
+
%(<loc>http://example.org/test</loc>\n) +
|
44
|
+
%(</url>\n) +
|
45
|
+
%(</urlset>\n)
|
46
|
+
end
|
47
|
+
|
48
|
+
it "ignores unnamed redirects" do
|
49
|
+
@app = Redirect::App.new(['/a', '/hidden'])
|
50
|
+
get('/sitemap.xml')
|
51
|
+
body.should == %(<?xml version="1.0" encoding="UTF-8"?>\n) +
|
52
|
+
%(<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">\n) +
|
53
|
+
%(</urlset>\n)
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
describe "static files" do
|
58
|
+
before do
|
59
|
+
@app = Redirect::App.new
|
60
|
+
@app.public_dir = 'spec/fixtures/public'
|
61
|
+
end
|
62
|
+
|
63
|
+
it "serves GET requests for files in the public directory" do
|
64
|
+
get "/index.html"
|
65
|
+
status.should == 200
|
66
|
+
body.should == File.read('spec/fixtures/public/index.html')
|
67
|
+
headers['Content-Length'].should == '43'
|
68
|
+
headers.should include('Last-Modified')
|
69
|
+
end
|
70
|
+
|
71
|
+
it "ignores GET request up the public directory" do
|
72
|
+
get "/../private"
|
73
|
+
status.should == 404
|
74
|
+
end
|
75
|
+
|
76
|
+
it "ignores GET request with .." do
|
77
|
+
get "/../public/index.html"
|
78
|
+
status.should == 404
|
79
|
+
end
|
80
|
+
|
81
|
+
it "ignores GET requests for dirs in the public directory" do
|
82
|
+
get "/dir"
|
83
|
+
status.should == 404
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
describe "404" do
|
88
|
+
it "shows 404 not found if no redirect exists" do
|
89
|
+
@app = Redirect::App.new
|
90
|
+
get("/test")
|
91
|
+
res.not_found?.should be_true
|
92
|
+
headers["Content-Type"].should == "text/html"
|
93
|
+
body.should == "not found"
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
describe "redirect" do
|
98
|
+
context "basic redirect" do
|
99
|
+
let(:res) do
|
100
|
+
@app = Redirect::App.new(['/old/2008', '/index.html'])
|
101
|
+
get('/old/2008')
|
102
|
+
end
|
103
|
+
|
104
|
+
it "sets the content-type header to text/html" do
|
105
|
+
headers['Content-Type'].should == 'text/html'
|
106
|
+
end
|
107
|
+
|
108
|
+
it "sets the Location header to text/html" do
|
109
|
+
headers['Location'].should == '/index.html'
|
110
|
+
end
|
111
|
+
|
112
|
+
it "sets the body to redirecting text/html" do
|
113
|
+
body.should == 'Redirecting to: /index.html'
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
117
|
+
it "renders the redirect if available" do
|
118
|
+
@app = Redirect::App.new(['/old/2008', '/index.html'])
|
119
|
+
@app.public_dir = 'spec/fixtures/public'
|
120
|
+
get '/index.html'
|
121
|
+
# status.should == 200
|
122
|
+
body.should == File.read('spec/fixtures/public/index.html')
|
123
|
+
end
|
124
|
+
|
125
|
+
it "redirects a regular_expression" do
|
126
|
+
@app = Redirect::App.new(['^/old', '/new'])
|
127
|
+
@app.public_dir = 'spec/fixtures/public'
|
128
|
+
get '/old/2008'
|
129
|
+
headers['Location'].should == '/new'
|
130
|
+
end
|
131
|
+
|
132
|
+
it "redirects a regular_expression with arguments" do
|
133
|
+
@app = Redirect::App.new([/old\/(.*)/, '/new/$1'])
|
134
|
+
get '/old/2008/02/14'
|
135
|
+
headers['Location'].should == '/new/2008/02/14'
|
136
|
+
end
|
137
|
+
|
138
|
+
it "redirects to the first match" do
|
139
|
+
@app = Redirect::App.new(['^/old2', '/new'], ['^/old2', '/new2'])
|
140
|
+
get '/old2008'
|
141
|
+
headers['Location'].should == '/new'
|
142
|
+
end
|
143
|
+
|
144
|
+
it "should turn redirects array into Redirect Objects" do
|
145
|
+
@app = Redirect::App.new(['^/old3', '/new', {:code => 307}], ['^/old2', '/new2', {:name => 'test'}])
|
146
|
+
get "/test"
|
147
|
+
res.not_found?.should be_true
|
148
|
+
headers["Content-Type"].should == "text/html"
|
149
|
+
body.should == "not found"
|
150
|
+
end
|
88
151
|
end
|
89
152
|
|
153
|
+
describe "#initialize" do
|
154
|
+
it "raises an error if a catch_url matches a redirect_url" #do
|
155
|
+
# Redirect::App.new(['^/old', 'new'], ['^/new', 'old'])
|
156
|
+
# end
|
157
|
+
end
|
158
|
+
|
159
|
+
describe "#public_dir" do
|
160
|
+
it "defaults to public" do
|
161
|
+
Redirect::App.new.public_dir.should == 'public'
|
162
|
+
end
|
163
|
+
end
|
164
|
+
|
165
|
+
def body
|
166
|
+
res.body
|
167
|
+
end
|
168
|
+
|
169
|
+
def get url
|
170
|
+
@res = Rack::MockRequest.new(@app).get(url)
|
171
|
+
end
|
172
|
+
|
173
|
+
def headers
|
174
|
+
res.headers
|
175
|
+
end
|
176
|
+
|
177
|
+
def res
|
178
|
+
@res
|
179
|
+
end
|
180
|
+
|
181
|
+
def status
|
182
|
+
res.status
|
183
|
+
end
|
90
184
|
end
|
91
185
|
|
92
186
|
describe "Redirect::Data" do
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
187
|
+
describe "#initialize" do
|
188
|
+
it "turns an default array into a redirect object" do
|
189
|
+
data = Redirect::Data.new('^/old3', '/new')
|
190
|
+
data.catch_url.should == '^/old3'
|
191
|
+
data.redirect_url.should == '/new'
|
192
|
+
data.code.should == 301
|
193
|
+
data.name.should == nil
|
194
|
+
end
|
195
|
+
|
196
|
+
it "turns an array into a redirect object" do
|
197
|
+
data = Redirect::Data.new('^/old3', '/new', {:code => 307, :name => 'test'})
|
198
|
+
data.catch_url.should == '^/old3'
|
199
|
+
data.redirect_url.should == '/new'
|
200
|
+
data.code.should == 307
|
201
|
+
data.name.should == 'test'
|
202
|
+
end
|
203
|
+
end
|
108
204
|
end
|
109
205
|
|
110
206
|
describe "Redirect" do
|
@@ -113,25 +209,31 @@ describe "Redirect" do
|
|
113
209
|
Redirect.app = nil
|
114
210
|
Redirect.autorun = true
|
115
211
|
end
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
212
|
+
|
213
|
+
describe ".default_code" do
|
214
|
+
it "overwrites default http redirect code" do
|
215
|
+
data = Redirect::Data.new('/a', '/b')
|
216
|
+
data.code.should == 301
|
217
|
+
Redirect.default_code = 307
|
218
|
+
data = Redirect::Data.new('/a', '/b')
|
219
|
+
data.code.should == 307
|
220
|
+
end
|
221
|
+
end
|
222
|
+
|
223
|
+
describe ".app" do
|
224
|
+
it "sets app" do
|
225
|
+
Redirect.app.should == nil
|
226
|
+
Redirect.app = 'a'
|
227
|
+
Redirect.app.should == 'a'
|
228
|
+
end
|
229
|
+
end
|
230
|
+
|
231
|
+
describe ".autorun" do
|
232
|
+
it "sets autorun" do
|
233
|
+
Redirect.autorun.should == true
|
234
|
+
Redirect.autorun = false
|
235
|
+
Redirect.autorun.should == false
|
236
|
+
end
|
237
|
+
end
|
238
|
+
|
239
|
+
end
|
metadata
CHANGED
@@ -1,7 +1,8 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: redirect
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
|
4
|
+
prerelease:
|
5
|
+
version: 0.4.0
|
5
6
|
platform: ruby
|
6
7
|
authors:
|
7
8
|
- Petrik de Heus
|
@@ -9,68 +10,94 @@ autorequire:
|
|
9
10
|
bindir: bin
|
10
11
|
cert_chain: []
|
11
12
|
|
12
|
-
date:
|
13
|
-
default_executable:
|
13
|
+
date: 2011-12-27 00:00:00 +01:00
|
14
|
+
default_executable: redirect_app
|
14
15
|
dependencies:
|
15
16
|
- !ruby/object:Gem::Dependency
|
16
|
-
name:
|
17
|
-
|
18
|
-
|
19
|
-
|
17
|
+
name: rack
|
18
|
+
prerelease: false
|
19
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
20
|
+
none: false
|
21
|
+
requirements:
|
22
|
+
- - ~>
|
23
|
+
- !ruby/object:Gem::Version
|
24
|
+
version: "1.3"
|
25
|
+
- - ">="
|
26
|
+
- !ruby/object:Gem::Version
|
27
|
+
version: 1.3.4
|
28
|
+
type: :runtime
|
29
|
+
version_requirements: *id001
|
30
|
+
- !ruby/object:Gem::Dependency
|
31
|
+
name: rspec
|
32
|
+
prerelease: false
|
33
|
+
requirement: &id002 !ruby/object:Gem::Requirement
|
34
|
+
none: false
|
20
35
|
requirements:
|
21
36
|
- - ">="
|
22
37
|
- !ruby/object:Gem::Version
|
23
|
-
version:
|
24
|
-
|
38
|
+
version: "0"
|
39
|
+
type: :development
|
40
|
+
version_requirements: *id002
|
25
41
|
description: Redirect is a simple Ruby redirect DSL build on Rack. It's like a simple Ruby mod_rewrite, so you can write and test your redirects in Ruby.
|
26
42
|
email:
|
27
|
-
- FIX@
|
43
|
+
- FIX@email.com
|
28
44
|
executables:
|
29
45
|
- redirect_app
|
30
46
|
extensions: []
|
31
47
|
|
32
|
-
extra_rdoc_files:
|
33
|
-
|
34
|
-
- Manifest.txt
|
35
|
-
- README.txt
|
48
|
+
extra_rdoc_files: []
|
49
|
+
|
36
50
|
files:
|
51
|
+
- .gitignore
|
52
|
+
- Gemfile
|
37
53
|
- History.txt
|
38
54
|
- Manifest.txt
|
39
|
-
- README.
|
55
|
+
- README.md
|
40
56
|
- Rakefile
|
57
|
+
- autotest/discover.rb
|
41
58
|
- bin/redirect_app
|
42
59
|
- example.rb
|
43
60
|
- example.ru
|
44
61
|
- lib/redirect.rb
|
62
|
+
- lib/redirect/app.rb
|
63
|
+
- lib/redirect/redirect.rb
|
45
64
|
- lib/redirect/test.rb
|
65
|
+
- lib/redirect/version.rb
|
66
|
+
- redirect.gemspec
|
67
|
+
- spec/fixtures/private
|
68
|
+
- spec/fixtures/public/index.html
|
46
69
|
- spec/helper.rb
|
47
70
|
- spec/rack_spec.rb
|
48
71
|
has_rdoc: true
|
49
72
|
homepage: http://github.com/p8/redirect/tree/master
|
73
|
+
licenses: []
|
74
|
+
|
50
75
|
post_install_message:
|
51
|
-
rdoc_options:
|
52
|
-
|
53
|
-
- README.txt
|
76
|
+
rdoc_options: []
|
77
|
+
|
54
78
|
require_paths:
|
55
79
|
- lib
|
56
80
|
required_ruby_version: !ruby/object:Gem::Requirement
|
81
|
+
none: false
|
57
82
|
requirements:
|
58
83
|
- - ">="
|
59
84
|
- !ruby/object:Gem::Version
|
60
85
|
version: "0"
|
61
|
-
version:
|
62
86
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
87
|
+
none: false
|
63
88
|
requirements:
|
64
89
|
- - ">="
|
65
90
|
- !ruby/object:Gem::Version
|
66
91
|
version: "0"
|
67
|
-
version:
|
68
92
|
requirements: []
|
69
93
|
|
70
94
|
rubyforge_project: redirect
|
71
|
-
rubygems_version: 1.
|
95
|
+
rubygems_version: 1.5.2
|
72
96
|
signing_key:
|
73
|
-
specification_version:
|
97
|
+
specification_version: 3
|
74
98
|
summary: Redirect is a simple Ruby redirect DSL build on Rack
|
75
|
-
test_files:
|
76
|
-
|
99
|
+
test_files:
|
100
|
+
- spec/fixtures/private
|
101
|
+
- spec/fixtures/public/index.html
|
102
|
+
- spec/helper.rb
|
103
|
+
- spec/rack_spec.rb
|
data/README.txt
DELETED
@@ -1,70 +0,0 @@
|
|
1
|
-
= Redirect
|
2
|
-
|
3
|
-
http://github.com/p8/redirect/tree/master
|
4
|
-
|
5
|
-
== DESCRIPTION:
|
6
|
-
|
7
|
-
Redirect is a simple Ruby redirect DSL build on Rack.
|
8
|
-
It's like a simple Ruby mod_rewrite, so you can write and test your redirects in Ruby.
|
9
|
-
|
10
|
-
== GETTING STARTED:
|
11
|
-
|
12
|
-
From the commandline run:
|
13
|
-
|
14
|
-
redirect_app PROJECT_NAME
|
15
|
-
|
16
|
-
This create a directory PROJECT_NAME with the required files and tests.
|
17
|
-
PROJECT_NAME.rb contains the main logic.
|
18
|
-
|
19
|
-
To locally run the app you can do:
|
20
|
-
|
21
|
-
ruby PROJECT_NAME.rb
|
22
|
-
|
23
|
-
== REDIRECTS:
|
24
|
-
|
25
|
-
The first one is evaluated first, then the next one, etc..
|
26
|
-
|
27
|
-
redirect ['/catch_url', '/redirect_url'],
|
28
|
-
['/catch_url2', '/redirect_url2']
|
29
|
-
|
30
|
-
The catch_url can be a regular expression:
|
31
|
-
|
32
|
-
['^/some_regexp', '/all']
|
33
|
-
[/old\/(.*)/, '/new/$1'] # /old/2008/02/01 will be redirected to /new/2008/02/01
|
34
|
-
|
35
|
-
You can pass extra options.
|
36
|
-
:code # Overwrite the http code (defaults is 301) in the options
|
37
|
-
:name # named redirects are public so they'll appear in you sitemap
|
38
|
-
|
39
|
-
['/catch_url', '/redirect_url', {:code => 307, :name => 'redirect link'}]
|
40
|
-
|
41
|
-
The default redirect code can be changed:
|
42
|
-
|
43
|
-
Redirect.default_code = 307
|
44
|
-
|
45
|
-
A sitemap.xml is generated for all redirects that have a name.
|
46
|
-
|
47
|
-
== LICENSE:
|
48
|
-
|
49
|
-
(The MIT License)
|
50
|
-
|
51
|
-
Copyright (c) 2009 Petrik de Heus
|
52
|
-
|
53
|
-
Permission is hereby granted, free of charge, to any person obtaining
|
54
|
-
a copy of this software and associated documentation files (the
|
55
|
-
'Software'), to deal in the Software without restriction, including
|
56
|
-
without limitation the rights to use, copy, modify, merge, publish,
|
57
|
-
distribute, sublicense, and/or sell copies of the Software, and to
|
58
|
-
permit persons to whom the Software is furnished to do so, subject to
|
59
|
-
the following conditions:
|
60
|
-
|
61
|
-
The above copyright notice and this permission notice shall be
|
62
|
-
included in all copies or substantial portions of the Software.
|
63
|
-
|
64
|
-
THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
|
65
|
-
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
66
|
-
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
67
|
-
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
68
|
-
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
69
|
-
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
70
|
-
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|