rewritten 0.3.3 → 0.4.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 ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 0c3f8baf622f9b4ce4351475c13fc1dc0eb73d86
4
+ data.tar.gz: 0afcf0f5c164bbae531c82692702305818cee956
5
+ SHA512:
6
+ metadata.gz: efb7ccf5dfa9d2b060c97960a677da421651dcc7ed6ba91f12d8373754d7bd6e4c682e8234106ea3ac4fd91af0dbab92bc950e7d44de08b8067d4afb2440d2a6
7
+ data.tar.gz: 0380009037fce092fabab01e3fbf902521513fe52470f8f0158313ba4c4c118c57eb88735db61d6b35c5e3fbe7d6b46ec5fc203bbc383be3ffaf0c50e44a0202
data/lib/rack/url.rb CHANGED
@@ -6,8 +6,10 @@ module Rack
6
6
 
7
7
  class Url
8
8
 
9
- def initialize(app, options = {})
9
+ def initialize(app, &block)
10
10
  @app = app
11
+
12
+ self.instance_eval(&block) if block_given?
11
13
  end
12
14
 
13
15
  def call(env)
@@ -15,9 +17,10 @@ module Rack
15
17
 
16
18
  subdomain = env["SUBDOMAIN"] ? "#{env["SUBDOMAIN"]}:" : ""
17
19
 
18
- if to = ::Rewritten.redis.get("from:#{subdomain}#{req.path_info}")
19
- current_path = ::Rewritten.list_range("to:#{to}", -1, 1)
20
+ if to = ::Rewritten.includes?("#{subdomain}#{req.path_info}")
21
+ current_path = ::Rewritten.get_current_translation(to)
20
22
  current_path = current_path.split(":").last
23
+
21
24
  if current_path == req.path_info
22
25
  # if this is the current path, rewrite path and parameters
23
26
  tpath, tparams = split_to_path_params(to)
@@ -26,13 +29,15 @@ module Rack
26
29
  @app.call(req.env)
27
30
  else
28
31
  # if this is not the current path, redirect to current path
29
- r = Rack::Response.new
30
32
  # NOTE: assuming redirection is always to non-subdomain-path
31
33
 
34
+ r = Rack::Response.new
35
+
32
36
  new_path = env["rack.url_scheme"].dup
33
37
  new_path << "://"
34
38
  new_path << env["HTTP_HOST"].dup.sub(/^#{subdomain.chomp(':')}\./, '')
35
39
  new_path << current_path
40
+ new_path << '?' << env["QUERY_STRING"] unless (env["QUERY_STRING"]||'').empty?
36
41
 
37
42
  r.redirect(new_path, 301)
38
43
  a = r.finish
@@ -47,6 +52,16 @@ module Rack
47
52
  [path, Rack::Utils.parse_query(query_string)]
48
53
  end
49
54
 
55
+
56
+ private
57
+
58
+ def add_translation(from,to)
59
+ ::Rewritten.redis = :test unless ::Rewritten.redis == :test
60
+ ::Rewritten.add_translation(from, to)
61
+ end
62
+
63
+
64
+
50
65
  end
51
66
  end
52
67
 
@@ -1,4 +1,4 @@
1
1
  module Rewritten
2
- VERSION = "0.3.3"
2
+ VERSION = "0.4.0"
3
3
  end
4
4
 
data/lib/rewritten.rb CHANGED
@@ -34,6 +34,9 @@ module Rewritten
34
34
  @redis = Redis::Namespace.new(namespace, :redis => redis)
35
35
  when Redis::Namespace
36
36
  @redis = server
37
+ when :test
38
+ @redis = :test
39
+ @static_translations = {}
37
40
  else
38
41
  @redis = Redis::Namespace.new(:rewritten, :redis => server)
39
42
  end
@@ -126,10 +129,14 @@ module Rewritten
126
129
  #
127
130
 
128
131
  def add_translation(from, to)
129
- redis.set("from:#{from}", to)
130
- redis.lpush(:froms, from)
131
- redis.lpush(:tos, to)
132
- redis.rpush("to:#{to}", from)
132
+ if @redis == :test
133
+ @static_translations[from] = to
134
+ else
135
+ redis.set("from:#{from}", to)
136
+ redis.lpush(:froms, from)
137
+ redis.lpush(:tos, to)
138
+ redis.rpush("to:#{to}", from)
139
+ end
133
140
  end
134
141
 
135
142
  def add_translations(to, froms)
@@ -158,9 +165,21 @@ module Rewritten
158
165
  end
159
166
 
160
167
  def get_current_translation(path)
161
- translation = Rewritten.list_range("to:#{path}", -1)
162
- return translation if translation
163
- return path
168
+ if @redis == :test
169
+
170
+ translations = @static_translations.select{|k,v| v == path}
171
+
172
+ if translations.size > 0
173
+ return translations.keys.last
174
+ else
175
+ return path
176
+ end
177
+
178
+ else
179
+ translation = Rewritten.list_range("to:#{path}", -1)
180
+ return translation if translation
181
+ return path
182
+ end
164
183
  end
165
184
 
166
185
 
@@ -174,8 +193,12 @@ module Rewritten
174
193
  Rewritten.redis.smembers("hits").map{|e| decode(e)}
175
194
  end
176
195
 
177
- def include?(path)
178
- Rewritten.redis.get("from:#{path}")
196
+ def includes?(path)
197
+ if @redis == :test
198
+ @static_translations[path]
199
+ else
200
+ Rewritten.redis.get("from:#{path}")
201
+ end
179
202
  end
180
203
 
181
204
  #
data/rewritten.gemspec CHANGED
@@ -22,6 +22,10 @@ Gem::Specification.new do |s|
22
22
  s.add_dependency "sinatra", ">= 0.9.2"
23
23
  s.add_dependency "multi_json", "~> 1.0"
24
24
 
25
+ s.add_development_dependency "rake"
26
+ s.add_development_dependency "minitest"
27
+ s.add_development_dependency "pry"
28
+
25
29
  s.description = <<description
26
30
  Rewritten is a lookup-based rewriting engine that rewrites requested
27
31
  URLs on the fly. The URL manipulations depend on translations found in
@@ -0,0 +1,89 @@
1
+ require 'rewritten'
2
+ require 'rack/mock'
3
+ require 'minitest/autorun'
4
+ require 'pry'
5
+
6
+ describe Rack::Rewritten::Url do
7
+
8
+ def call_args(overrides={})
9
+ {'HTTP_HOST' => 'www.example.org',
10
+ 'REQUEST_URI' => '/foo/with/params',
11
+ 'SCRIPT_INFO'=> '',
12
+ 'PATH_INFO' => '/foo/with/params',
13
+ 'QUERY_STRING' => '',
14
+ 'rack.input' => '',
15
+ 'rack.url_scheme' => 'http'}.merge(overrides)
16
+ end
17
+
18
+ describe "redirection behavior" do
19
+
20
+ before {
21
+ @app = MiniTest::Mock.new
22
+
23
+ @rack = Rack::Rewritten::Url.new(@app) do
24
+ add_translation '/foo/bar', '/products/1'
25
+ add_translation '/foo/baz', '/products/1'
26
+ add_translation '/foo/with/params', '/products/2?w=1'
27
+ end
28
+ }
29
+
30
+ it "must not redirect if there are no entries" do
31
+ @app.expect :call, [200, {'Content-Type' => 'text/plain'},[""]], [Hash]
32
+ @rack.call(call_args)
33
+ @app.verify
34
+ end
35
+
36
+ it "must 301 redirect to latest translation" do
37
+ ret = @rack.call( call_args.merge('REQUEST_URI' => '/foo/bar', 'PATH_INFO' => '/foo/bar' ))
38
+ @app.verify
39
+ ret[0].must_equal 301
40
+ ret[1]['Location'].must_equal "http://www.example.org/foo/baz"
41
+ end
42
+
43
+ it "must keep the query parameters in the 301 redirect" do
44
+ ret = @rack.call( call_args.merge('REQUEST_URI' => '/foo/bar', 'PATH_INFO' => '/foo/bar', 'QUERY_STRING' => 'w=1' ))
45
+ @app.verify
46
+ ret[0].must_equal 301
47
+ ret[1]['Location'].must_equal "http://www.example.org/foo/baz?w=1"
48
+ end
49
+
50
+
51
+ it "must stay on latest translation" do
52
+ @app.expect :call, [200, {'Content-Type' => 'text/plain'},[""]], [Hash]
53
+ ret = @rack.call( call_args.merge('REQUEST_URI' => '/foo/baz', 'PATH_INFO' => '/foo/baz' ))
54
+ @app.verify
55
+ ret[0].must_equal 200
56
+ end
57
+
58
+ end
59
+
60
+
61
+ describe "the env" do
62
+
63
+ before {
64
+ @initial_args = call_args.dup
65
+ @rack = Rack::Rewritten::Url.new(lambda{|env| [200, {}, [""]]})
66
+ }
67
+
68
+ it "must set PATH_INFO to /products/2" do
69
+ @rack.call(@initial_args)
70
+ @initial_args['PATH_INFO'].must_equal "/products/2"
71
+ end
72
+
73
+ it "must set QUERY_STRING to w=1" do
74
+ @rack.call(@initial_args)
75
+ @initial_args['QUERY_STRING'].must_equal 'w=1'
76
+ end
77
+
78
+ it "must merge QUERY parameters" do
79
+ @initial_args.merge!('QUERY_STRING' => 's=1')
80
+ @rack.call(@initial_args)
81
+ @initial_args['QUERY_STRING'].split('&').sort.must_equal ['s=1', 'w=1']
82
+ end
83
+
84
+ end
85
+
86
+
87
+
88
+ end
89
+
metadata CHANGED
@@ -1,36 +1,32 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rewritten
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.3
5
- prerelease:
4
+ version: 0.4.0
6
5
  platform: ruby
7
6
  authors:
8
7
  - Kai Rubarth
9
8
  autorequire:
10
9
  bindir: bin
11
10
  cert_chain: []
12
- date: 2013-02-03 00:00:00.000000000 Z
11
+ date: 2013-05-03 00:00:00.000000000 Z
13
12
  dependencies:
14
13
  - !ruby/object:Gem::Dependency
15
14
  name: redis-namespace
16
15
  requirement: !ruby/object:Gem::Requirement
17
- none: false
18
16
  requirements:
19
- - - ! '>='
17
+ - - '>='
20
18
  - !ruby/object:Gem::Version
21
19
  version: '0'
22
20
  type: :runtime
23
21
  prerelease: false
24
22
  version_requirements: !ruby/object:Gem::Requirement
25
- none: false
26
23
  requirements:
27
- - - ! '>='
24
+ - - '>='
28
25
  - !ruby/object:Gem::Version
29
26
  version: '0'
30
27
  - !ruby/object:Gem::Dependency
31
28
  name: vegas
32
29
  requirement: !ruby/object:Gem::Requirement
33
- none: false
34
30
  requirements:
35
31
  - - ~>
36
32
  - !ruby/object:Gem::Version
@@ -38,7 +34,6 @@ dependencies:
38
34
  type: :runtime
39
35
  prerelease: false
40
36
  version_requirements: !ruby/object:Gem::Requirement
41
- none: false
42
37
  requirements:
43
38
  - - ~>
44
39
  - !ruby/object:Gem::Version
@@ -46,23 +41,20 @@ dependencies:
46
41
  - !ruby/object:Gem::Dependency
47
42
  name: sinatra
48
43
  requirement: !ruby/object:Gem::Requirement
49
- none: false
50
44
  requirements:
51
- - - ! '>='
45
+ - - '>='
52
46
  - !ruby/object:Gem::Version
53
47
  version: 0.9.2
54
48
  type: :runtime
55
49
  prerelease: false
56
50
  version_requirements: !ruby/object:Gem::Requirement
57
- none: false
58
51
  requirements:
59
- - - ! '>='
52
+ - - '>='
60
53
  - !ruby/object:Gem::Version
61
54
  version: 0.9.2
62
55
  - !ruby/object:Gem::Dependency
63
56
  name: multi_json
64
57
  requirement: !ruby/object:Gem::Requirement
65
- none: false
66
58
  requirements:
67
59
  - - ~>
68
60
  - !ruby/object:Gem::Version
@@ -70,22 +62,69 @@ dependencies:
70
62
  type: :runtime
71
63
  prerelease: false
72
64
  version_requirements: !ruby/object:Gem::Requirement
73
- none: false
74
65
  requirements:
75
66
  - - ~>
76
67
  - !ruby/object:Gem::Version
77
68
  version: '1.0'
78
- description: ! " Rewritten is a lookup-based rewriting engine that rewrites requested\n
79
- \ URLs on the fly. The URL manipulations depend on translations found in\n a
80
- redis database.\n\n If a matching translation is found, the result of a request
81
- is either a\n redirection or a modification of path and request parameters. For
82
- URLs\n without translation entries the request is left unmodified.\n\n Rewritten
83
- takes larges parts from the Resque codebase (which rocks). The\n gem is compromised
84
- of four parts:\n\n 1. A Ruby library for creating, modifying and querying translations\n
85
- \ 2. A Sinatra app for displaying and managing translations\n 3. A Rack app
86
- for rewriting and redirecting request (Rack::Rewritten::Url)\n 4. A Rack app
87
- for substituting URLs in HTML pages with their current translation (Rack::Rewritten::Html)\n
88
- \ 5. A Rack app for recording successful request (Rack::Rewritten::Record)\n"
69
+ - !ruby/object:Gem::Dependency
70
+ name: rake
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - '>='
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - '>='
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ - !ruby/object:Gem::Dependency
84
+ name: minitest
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - '>='
88
+ - !ruby/object:Gem::Version
89
+ version: '0'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - '>='
95
+ - !ruby/object:Gem::Version
96
+ version: '0'
97
+ - !ruby/object:Gem::Dependency
98
+ name: pry
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - '>='
102
+ - !ruby/object:Gem::Version
103
+ version: '0'
104
+ type: :development
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - '>='
109
+ - !ruby/object:Gem::Version
110
+ version: '0'
111
+ description: |2
112
+ Rewritten is a lookup-based rewriting engine that rewrites requested
113
+ URLs on the fly. The URL manipulations depend on translations found in
114
+ a redis database.
115
+
116
+ If a matching translation is found, the result of a request is either a
117
+ redirection or a modification of path and request parameters. For URLs
118
+ without translation entries the request is left unmodified.
119
+
120
+ Rewritten takes larges parts from the Resque codebase (which rocks). The
121
+ gem is compromised of four parts:
122
+
123
+ 1. A Ruby library for creating, modifying and querying translations
124
+ 2. A Sinatra app for displaying and managing translations
125
+ 3. A Rack app for rewriting and redirecting request (Rack::Rewritten::Url)
126
+ 4. A Rack app for substituting URLs in HTML pages with their current translation (Rack::Rewritten::Html)
127
+ 5. A Rack app for recording successful request (Rack::Rewritten::Record)
89
128
  email:
90
129
  - kai@doxter.de
91
130
  executables:
@@ -137,29 +176,29 @@ files:
137
176
  - lib/rewritten/version.rb
138
177
  - lib/test.ru
139
178
  - rewritten.gemspec
179
+ - test/rewritten_url_test.rb
140
180
  - test/test_rewritten.rb
141
181
  homepage: ''
142
182
  licenses: []
183
+ metadata: {}
143
184
  post_install_message:
144
185
  rdoc_options: []
145
186
  require_paths:
146
187
  - lib
147
188
  required_ruby_version: !ruby/object:Gem::Requirement
148
- none: false
149
189
  requirements:
150
- - - ! '>='
190
+ - - '>='
151
191
  - !ruby/object:Gem::Version
152
192
  version: '0'
153
193
  required_rubygems_version: !ruby/object:Gem::Requirement
154
- none: false
155
194
  requirements:
156
- - - ! '>='
195
+ - - '>='
157
196
  - !ruby/object:Gem::Version
158
197
  version: '0'
159
198
  requirements: []
160
199
  rubyforge_project: rewritten
161
- rubygems_version: 1.8.23
200
+ rubygems_version: 2.0.0
162
201
  signing_key:
163
- specification_version: 3
202
+ specification_version: 4
164
203
  summary: A redis-based URL rewriting engine
165
204
  test_files: []