joshbuddy-rack-rewrite 0.0.2 → 0.0.3

Sign up to get free protection for your applications and to get access to all the features.
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 :uri => %r{/(api|test)} do
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 :uri => %r{/google.*} do
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 URI starts with /valid_place, it strips it off and keeps on truckin'
24
+ # If a PATH_INFO starts with /valid_place, it strips it off and keeps on truckin'
25
25
  #
26
- on :uri => %r{/valid_place/.*} do
27
- set(:uri) { uri[%r{/valid_place(/.*)}, 1] }
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 URI starts with /hello_kitty, add a kitty header equal to your query string
31
+ # If a PATH_INFO starts with /hello_kitty, add a kitty header equal to your query string
32
32
  #
33
- on :uri => %r{/hello_kitty/.*} do
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
@@ -1,4 +1,4 @@
1
1
  ---
2
2
  :major: 0
3
3
  :minor: 0
4
- :patch: 2
4
+ :patch: 3
@@ -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 uri
6
- @env['PATH_INFO']
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 port=(port)
49
- @env['SERVER_PORT'] = port.to_s
12
+ def respond_to?(method)
13
+ @request.respond_to?(method) || super
50
14
  end
51
15
 
52
- def scheme
53
- @env['rack.url_scheme']
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
- @env['rack.url_scheme'] = scheme
29
+ env = @request.env
30
+ env['rack.url_scheme'] = scheme
31
+ @request = Rack::Request.new(env)
58
32
  end
59
33
 
60
- def setup(env)
61
- @env = env
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 :"#{@variable}=", case @action
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
- @caller.send(method, *args, &block)
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
- case @action
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 = [ 302, {'Location'=> case @action
96
+ @caller.redirect = [ @status, {'Location'=> case @action
128
97
  when Proc
129
98
  instance_eval(&@action)
130
99
  else
131
- instance_eval(@action)
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
- attr_accessor :path, :redirect, :headers
9
+ FailError = Class.new(RuntimeError)
8
10
 
9
- class ConditionSet
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(pattern = nil, &block)
73
- @current_condition_set.actions << Action::Redirect.new(self, pattern || block)
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
@@ -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
@@ -12,11 +12,19 @@ describe "Rack::Rewrite Conditions" do
12
12
  end
13
13
  end
14
14
 
15
- it "should detect a simple uri" do
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(:uri => '/test') { pass } }.call(env)
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.2
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