joshbuddy-rack-rewrite 0.0.2 → 0.0.3
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/README.rdoc +14 -7
- data/VERSION.yml +1 -1
- data/lib/rack_rewrite/actions.rb +36 -67
- data/lib/rack_rewrite/condition_set.rb +40 -0
- data/lib/rack_rewrite.rb +9 -36
- data/spec/action_spec.rb +80 -0
- data/spec/conditions_spec.rb +10 -2
- metadata +3 -2
- data/spec/rewrite_spec.rb +0 -24
data/README.rdoc
CHANGED
@@ -10,31 +10,38 @@ Rack middleware for request rewriting.
|
|
10
10
|
|
11
11
|
# When it sees /api or /test, it calls whatever is in the act block
|
12
12
|
#
|
13
|
-
on :
|
13
|
+
on :path_info => %r{/(api|test)} do
|
14
14
|
act { puts "hey way to go!" }
|
15
15
|
pass
|
16
16
|
end
|
17
17
|
|
18
18
|
# When it sees /google, it makes a redirect to google with the value of the query string as the search
|
19
19
|
#
|
20
|
-
on :
|
20
|
+
on :path_info => %r{/google.*} do
|
21
21
|
redirect { "http://google.com/search?q=#{CGI.escape(query_string)}" }
|
22
22
|
end
|
23
23
|
|
24
|
-
# If a
|
24
|
+
# If a PATH_INFO starts with /valid_place, it strips it off and keeps on truckin'
|
25
25
|
#
|
26
|
-
on :
|
27
|
-
set(:
|
26
|
+
on :path_info => %r{/valid_place/.*} do
|
27
|
+
set(:path_info) { path_info[%r{/valid_place(/.*)}, 1] }
|
28
28
|
pass
|
29
29
|
end
|
30
30
|
|
31
|
-
# If a
|
31
|
+
# If a PATH_INFO starts with /hello_kitty, add a kitty header equal to your query string
|
32
32
|
#
|
33
|
-
on :
|
33
|
+
on :path_info => %r{/hello_kitty/.*} do
|
34
34
|
act { header['kitty'] = query_string }
|
35
35
|
pass
|
36
36
|
end
|
37
37
|
|
38
|
+
# If the request has a has a param of kitten=cute or kitten=happy, lets log it and pass it on!
|
39
|
+
#
|
40
|
+
on :params => {:kitten => /cute|happy/} do
|
41
|
+
act { log('what a nice cat') }
|
42
|
+
pass
|
43
|
+
end
|
44
|
+
|
38
45
|
fail
|
39
46
|
end
|
40
47
|
|
data/VERSION.yml
CHANGED
data/lib/rack_rewrite/actions.rb
CHANGED
@@ -1,64 +1,38 @@
|
|
1
|
+
require 'rack'
|
2
|
+
require 'cgi'
|
3
|
+
|
1
4
|
module Rack
|
2
5
|
class Rewrite
|
3
6
|
class Action
|
4
7
|
|
5
|
-
def
|
6
|
-
@env
|
7
|
-
end
|
8
|
-
|
9
|
-
def uri=(uri)
|
10
|
-
@env['PATH_INFO'] = uri
|
11
|
-
update_uri_qs
|
12
|
-
end
|
13
|
-
|
14
|
-
def query_string
|
15
|
-
@env['QUERY_STRING']
|
16
|
-
end
|
17
|
-
|
18
|
-
def query_string=(query_string)
|
19
|
-
@env['QUERY_STRING'] = query_string
|
20
|
-
update_uri_qs
|
21
|
-
end
|
22
|
-
|
23
|
-
def update_uri_qs
|
24
|
-
@env['REQUEST_PATH'] = uri
|
25
|
-
@env['REQUEST_URI'] = query_string.empty? ? uri : "#{uri}?#{query_string}"
|
26
|
-
end
|
27
|
-
|
28
|
-
def method
|
29
|
-
@env['REQUEST_METHOD']
|
30
|
-
end
|
31
|
-
|
32
|
-
def method=(method)
|
33
|
-
@env['REQUEST_METHOD'] = method.to_s.upcase
|
34
|
-
end
|
35
|
-
|
36
|
-
def host
|
37
|
-
@env['HTTP_HOST']
|
38
|
-
end
|
39
|
-
|
40
|
-
def host=(host)
|
41
|
-
@env['HTTP_HOST'] = host
|
42
|
-
end
|
43
|
-
|
44
|
-
def port
|
45
|
-
@env['SERVER_PORT']
|
8
|
+
def setup(env)
|
9
|
+
@request = Rack::Request.new(env)
|
46
10
|
end
|
47
11
|
|
48
|
-
def
|
49
|
-
@
|
12
|
+
def respond_to?(method)
|
13
|
+
@request.respond_to?(method) || super
|
50
14
|
end
|
51
15
|
|
52
|
-
def
|
53
|
-
@env
|
16
|
+
def query_string=(params)
|
17
|
+
env = @request.env
|
18
|
+
env['QUERY_STRING'] = case params
|
19
|
+
when Hash
|
20
|
+
params.inject([]) { |qs, (k, v)| qs << "#{CGI.escape(k.to_s)}=#{CGI.escape(v.to_s)}"} * '&'
|
21
|
+
else
|
22
|
+
params
|
23
|
+
end
|
24
|
+
|
25
|
+
@request = Rack::Request.new(env)
|
54
26
|
end
|
55
27
|
|
56
28
|
def scheme=(scheme)
|
57
|
-
|
29
|
+
env = @request.env
|
30
|
+
env['rack.url_scheme'] = scheme
|
31
|
+
@request = Rack::Request.new(env)
|
58
32
|
end
|
59
33
|
|
60
|
-
def
|
61
|
-
@
|
34
|
+
def method_missing(method, *args, &block)
|
35
|
+
@request.send(method, *args, &block)
|
62
36
|
end
|
63
37
|
|
64
38
|
class Pass < Action
|
@@ -69,7 +43,7 @@ module Rack
|
|
69
43
|
|
70
44
|
class Fail < Action
|
71
45
|
def call(env)
|
72
|
-
raise
|
46
|
+
raise Rack::Rewrite::FailError.new
|
73
47
|
end
|
74
48
|
end
|
75
49
|
|
@@ -82,12 +56,7 @@ module Rack
|
|
82
56
|
|
83
57
|
def call(env)
|
84
58
|
setup(env)
|
85
|
-
self.send
|
86
|
-
when Proc
|
87
|
-
instance_eval(&@action)
|
88
|
-
else
|
89
|
-
instance_eval(@action)
|
90
|
-
end
|
59
|
+
self.send(:"#{@variable}=", instance_eval(&@action))
|
91
60
|
env
|
92
61
|
end
|
93
62
|
|
@@ -98,37 +67,37 @@ module Rack
|
|
98
67
|
@caller = caller
|
99
68
|
@action = action
|
100
69
|
end
|
101
|
-
|
70
|
+
|
102
71
|
def method_missing(method, *args, &block)
|
103
|
-
|
72
|
+
if respond_to?(method)
|
73
|
+
super
|
74
|
+
else
|
75
|
+
@caller.send(method, *args, &block)
|
76
|
+
end
|
104
77
|
end
|
105
|
-
|
78
|
+
|
106
79
|
def call(env)
|
107
80
|
setup(env)
|
108
|
-
|
109
|
-
when Proc
|
110
|
-
instance_eval(&@action)
|
111
|
-
else
|
112
|
-
instance_eval(@action)
|
113
|
-
end
|
81
|
+
instance_eval(&@action)
|
114
82
|
env
|
115
83
|
end
|
116
84
|
|
117
85
|
end
|
118
86
|
|
119
87
|
class Redirect < Action
|
120
|
-
def initialize(caller, action)
|
88
|
+
def initialize(caller, action, status)
|
121
89
|
@caller = caller
|
122
90
|
@action = action
|
91
|
+
@status = status
|
123
92
|
end
|
124
93
|
|
125
94
|
def call(env)
|
126
95
|
setup(env)
|
127
|
-
@caller.redirect = [
|
96
|
+
@caller.redirect = [ @status, {'Location'=> case @action
|
128
97
|
when Proc
|
129
98
|
instance_eval(&@action)
|
130
99
|
else
|
131
|
-
|
100
|
+
@action
|
132
101
|
end}, []]
|
133
102
|
throw :pass
|
134
103
|
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
module Rack
|
2
|
+
class Rewrite
|
3
|
+
class ConditionSet
|
4
|
+
|
5
|
+
attr_reader :parent_set, :actions, :conditions
|
6
|
+
|
7
|
+
def initialize(parent_set, conditions = nil)
|
8
|
+
@parent_set = parent_set
|
9
|
+
@conditions = conditions
|
10
|
+
@actions = []
|
11
|
+
end
|
12
|
+
|
13
|
+
def satisfied?(env)
|
14
|
+
if conditions
|
15
|
+
|
16
|
+
uri_ok = conditions.key?(:uri) ? conditions[:uri] === env['PATH_INFO'] : true
|
17
|
+
method_ok = conditions.key?(:method) ? conditions[:method] === env['REQUEST_METHOD'].downcase : true
|
18
|
+
host_ok = conditions.key?(:host) ? conditions[:host] === env['HTTP_HOST'] : true
|
19
|
+
port_ok = conditions.key?(:port) ? conditions[:port] === env['SERVER_PORT'].to_i : true
|
20
|
+
scheme_ok = conditions.key?(:scheme) ? conditions[:scheme] === env['rack.url_scheme'] : true
|
21
|
+
if conditions.key?(:params)
|
22
|
+
req = Rack::Request.new(env)
|
23
|
+
params_ok = true
|
24
|
+
conditions[:params].each do |key, test|
|
25
|
+
params_ok = test === req.params[key.to_s]
|
26
|
+
break unless params_ok
|
27
|
+
end
|
28
|
+
else
|
29
|
+
params_ok = true
|
30
|
+
end
|
31
|
+
|
32
|
+
uri_ok && method_ok && host_ok && port_ok && scheme_ok && params_ok
|
33
|
+
else
|
34
|
+
true
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
data/lib/rack_rewrite.rb
CHANGED
@@ -1,43 +1,14 @@
|
|
1
1
|
$:.unshift(File.dirname(__FILE__))
|
2
|
+
require 'rack'
|
2
3
|
require 'rack_rewrite/actions'
|
4
|
+
require 'rack_rewrite/condition_set'
|
3
5
|
|
4
6
|
module Rack
|
5
7
|
class Rewrite
|
6
8
|
|
7
|
-
|
9
|
+
FailError = Class.new(RuntimeError)
|
8
10
|
|
9
|
-
|
10
|
-
|
11
|
-
attr_reader :parent_set, :actions, :conditions
|
12
|
-
|
13
|
-
def initialize(parent_set, conditions = nil)
|
14
|
-
@parent_set = parent_set
|
15
|
-
@conditions = conditions
|
16
|
-
@actions = []
|
17
|
-
end
|
18
|
-
|
19
|
-
def satisfied?(env)
|
20
|
-
if conditions
|
21
|
-
|
22
|
-
uri_ok = conditions.key?(:uri) ? conditions[:uri] === env['PATH_INFO'] : true
|
23
|
-
method_ok = conditions.key?(:method) ? conditions[:method] === env['REQUEST_METHOD'].downcase : true
|
24
|
-
host_ok = conditions.key?(:host) ? conditions[:host] === env['HTTP_HOST'] : true
|
25
|
-
port_ok = conditions.key?(:port) ? conditions[:port] === env['SERVER_PORT'].to_i : true
|
26
|
-
scheme_ok = conditions.key?(:scheme) ? conditions[:scheme] === env['rack.url_scheme'] : true
|
27
|
-
|
28
|
-
#puts "uri_ok: #{uri_ok} method_ok #{method_ok} host_ok #{host_ok} port_ok #{port_ok} scheme_ok #{scheme_ok} for conditions #{conditions.inspect}"
|
29
|
-
|
30
|
-
uri_ok && method_ok && host_ok && port_ok && scheme_ok
|
31
|
-
else
|
32
|
-
true
|
33
|
-
end
|
34
|
-
end
|
35
|
-
|
36
|
-
def inspect
|
37
|
-
"#{id} .. conditions=#{conditions.inspect}\nactions=#{actions.inspect}"
|
38
|
-
end
|
39
|
-
|
40
|
-
end
|
11
|
+
attr_accessor :path, :redirect, :headers
|
41
12
|
|
42
13
|
def initialize(app, options = {}, &block)
|
43
14
|
@app = app
|
@@ -69,15 +40,17 @@ module Rack
|
|
69
40
|
@current_condition_set.actions << Action::Fail.new
|
70
41
|
end
|
71
42
|
|
72
|
-
def redirect(
|
73
|
-
|
43
|
+
def redirect(*args, &block)
|
44
|
+
options = args.last.is_a?(Hash) ? args.pop : {}
|
45
|
+
pattern = args.first
|
46
|
+
@current_condition_set.actions << Action::Redirect.new(self, pattern || block, options[:status] || 302)
|
74
47
|
end
|
75
48
|
|
76
49
|
def call(env)
|
77
50
|
@headers = {}
|
78
51
|
catch(:pass) {
|
79
52
|
env = call_conditions(env, @root)
|
80
|
-
raise
|
53
|
+
raise FailError.new
|
81
54
|
}
|
82
55
|
if @redirect
|
83
56
|
redirect = @redirect
|
data/spec/action_spec.rb
ADDED
@@ -0,0 +1,80 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe "Rack::Rewrite Rewriting" do
|
4
|
+
|
5
|
+
it "should rewrite a path_info" do
|
6
|
+
env = Rack::MockRequest.env_for('/test', :method => 'get')
|
7
|
+
app = mock('app')
|
8
|
+
app.should_receive(:call) { |resp|
|
9
|
+
resp['PATH_INFO'].should == '/test/test'
|
10
|
+
[200, {}, ["body"]]
|
11
|
+
}
|
12
|
+
|
13
|
+
Rack::Rewrite.new(app) { on(:path_info => '/test') { set(:path_info) { "/test#{path_info}" }; pass } }.call(env)
|
14
|
+
end
|
15
|
+
|
16
|
+
it "should rewrite a scheme" do
|
17
|
+
env = Rack::MockRequest.env_for('/test', :method => 'get')
|
18
|
+
app = mock('app')
|
19
|
+
app.should_receive(:call) { |resp|
|
20
|
+
resp['rack.url_scheme'].should == 'https'
|
21
|
+
[200, {}, ["body"]]
|
22
|
+
}
|
23
|
+
|
24
|
+
Rack::Rewrite.new(app) { on(:path_info => '/test') { set(:scheme) { "https" }; pass } }.call(env)
|
25
|
+
end
|
26
|
+
|
27
|
+
it "should arbitrarily add a new header" do
|
28
|
+
env = Rack::MockRequest.env_for('/test?Happy-Land', :method => 'get')
|
29
|
+
app = mock('app')
|
30
|
+
app.should_receive(:call).and_return([200, {'Content-type' => 'text/html'}, ['mybody']])
|
31
|
+
response = Rack::Rewrite.new(app) { on(:path_info => '/test') { act{ headers['My-special-header'] = query_string }; pass } }.call(env)
|
32
|
+
response[1]['My-special-header'].should == 'Happy-Land'
|
33
|
+
end
|
34
|
+
|
35
|
+
it "should let you create a new querystring from a hash" do
|
36
|
+
env = Rack::MockRequest.env_for('/test?Happy=Land', :method => 'get')
|
37
|
+
app = mock('app')
|
38
|
+
app.should_receive(:call) { |resp|
|
39
|
+
['Happy=Land&more=query_goodness', 'more=query_goodness&Happy=Land'].should include(resp['QUERY_STRING'])
|
40
|
+
[200, {}, ["body"]]
|
41
|
+
}
|
42
|
+
response = Rack::Rewrite.new(app) { on(:path_info => '/test') { set(:query_string) { params.merge(:more => :query_goodness)}; pass } }.call(env)
|
43
|
+
end
|
44
|
+
|
45
|
+
it "should let you create a new querystring from a string" do
|
46
|
+
env = Rack::MockRequest.env_for('/test?Happy=Land', :method => 'get')
|
47
|
+
app = mock('app')
|
48
|
+
app.should_receive(:call) { |resp|
|
49
|
+
resp['QUERY_STRING'].should == 'this_is_my_query_string'
|
50
|
+
[200, {}, ["body"]]
|
51
|
+
}
|
52
|
+
response = Rack::Rewrite.new(app) { on(:path_info => '/test') { set(:query_string) { "this_is_my_query_string" }; pass } }.call(env)
|
53
|
+
|
54
|
+
end
|
55
|
+
|
56
|
+
it "should fail" do
|
57
|
+
env = Rack::MockRequest.env_for('/test', :method => 'get')
|
58
|
+
app = mock('app')
|
59
|
+
proc { Rack::Rewrite.new(app) { on(:path_info => '/test') { fail }; pass }.call(env) }.should raise_error Rack::Rewrite::FailError
|
60
|
+
end
|
61
|
+
|
62
|
+
it "should redirect from a proc" do
|
63
|
+
env = Rack::MockRequest.env_for('/test', :method => 'get')
|
64
|
+
app = mock('app')
|
65
|
+
Rack::Rewrite.new(app) { on(:path_info => '/test') { redirect {"/another/place"} }; fail }.call(env).should == [302, {'Location' => '/another/place'}, []]
|
66
|
+
end
|
67
|
+
|
68
|
+
it "should redirect from a proc (with a special status)" do
|
69
|
+
env = Rack::MockRequest.env_for('/test', :method => 'get')
|
70
|
+
app = mock('app')
|
71
|
+
Rack::Rewrite.new(app) { on(:path_info => '/test') { redirect(:status => 304) {"/another/place"} }; fail }.call(env).should == [304, {'Location' => '/another/place'}, []]
|
72
|
+
end
|
73
|
+
|
74
|
+
it "should redirect from a string" do
|
75
|
+
env = Rack::MockRequest.env_for('/test', :method => 'get')
|
76
|
+
app = mock('app')
|
77
|
+
Rack::Rewrite.new(app) { on(:path_info => '/test') { redirect "/another/place" }; fail }.call(env).should == [302, {'Location' => '/another/place'}, []]
|
78
|
+
end
|
79
|
+
|
80
|
+
end
|
data/spec/conditions_spec.rb
CHANGED
@@ -12,11 +12,19 @@ describe "Rack::Rewrite Conditions" do
|
|
12
12
|
end
|
13
13
|
end
|
14
14
|
|
15
|
-
it "should detect a simple
|
15
|
+
it "should detect a simple path_info" do
|
16
16
|
env = Rack::MockRequest.env_for('/test', :method => 'get')
|
17
17
|
app = mock('app')
|
18
18
|
app.should_receive(:call).with(env).and_return([200, {}, ["body"]])
|
19
|
-
Rack::Rewrite.new(app) { on(:
|
19
|
+
Rack::Rewrite.new(app) { on(:path_info => '/test') { pass } }.call(env)
|
20
20
|
end
|
21
21
|
|
22
|
+
it "should detect a param in the query string" do
|
23
|
+
env = Rack::MockRequest.env_for('/test?test=helpme', :method => 'get')
|
24
|
+
app = mock('app')
|
25
|
+
app.should_receive(:call).with(env).and_return([200, {}, ["body"]])
|
26
|
+
Rack::Rewrite.new(app) { on(:params => {:test => 'helpme'}) { pass } }.call(env)
|
27
|
+
proc { Rack::Rewrite.new(app) { on(:params => {:test => 'helpme2'}) { pass } }.call(env) }.should raise_error
|
28
|
+
end
|
29
|
+
|
22
30
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: joshbuddy-rack-rewrite
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Joshua Hull
|
@@ -26,9 +26,10 @@ files:
|
|
26
26
|
- VERSION.yml
|
27
27
|
- lib/rack_rewrite
|
28
28
|
- lib/rack_rewrite/actions.rb
|
29
|
+
- lib/rack_rewrite/condition_set.rb
|
29
30
|
- lib/rack_rewrite.rb
|
31
|
+
- spec/action_spec.rb
|
30
32
|
- spec/conditions_spec.rb
|
31
|
-
- spec/rewrite_spec.rb
|
32
33
|
- spec/spec_helper.rb
|
33
34
|
has_rdoc: true
|
34
35
|
homepage: http://github.com/joshbuddy/rack-rewrite
|
data/spec/rewrite_spec.rb
DELETED
@@ -1,24 +0,0 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
|
3
|
-
describe "Rack::Rewrite Rewriting" do
|
4
|
-
|
5
|
-
it "should rewrite a uri" do
|
6
|
-
env = Rack::MockRequest.env_for('/test', :method => 'get')
|
7
|
-
app = mock('app')
|
8
|
-
app.should_receive(:call) { |resp|
|
9
|
-
resp['PATH_INFO'].should == '/test/test'
|
10
|
-
[200, {}, ["body"]]
|
11
|
-
}
|
12
|
-
|
13
|
-
Rack::Rewrite.new(app) { on(:uri => '/test') { set(:uri) { "/test#{uri}" }; pass } }.call(env)
|
14
|
-
end
|
15
|
-
|
16
|
-
it "should arbitrarily add a new header" do
|
17
|
-
env = Rack::MockRequest.env_for('/test?Happy-Land', :method => 'get')
|
18
|
-
app = mock('app')
|
19
|
-
app.should_receive(:call).and_return([200, {'Content-type' => 'text/html'}, ['mybody']])
|
20
|
-
response = Rack::Rewrite.new(app) { on(:uri => '/test') { act{ headers['My-special-header'] = query_string }; pass } }.call(env)
|
21
|
-
response[1]['My-special-header'].should == 'Happy-Land'
|
22
|
-
end
|
23
|
-
|
24
|
-
end
|