joshbuddy-rack-rewrite 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
data/README.rdoc ADDED
@@ -0,0 +1,41 @@
1
+ = rack-rewrite
2
+
3
+ Rack middleware for request rewriting.
4
+
5
+ == Example
6
+
7
+ use Rack::Rewrite do
8
+
9
+ on :method => 'get' do
10
+
11
+ # When it sees /api or /test, it calls whatever is in the act block
12
+ #
13
+ on :uri => %r{/(api|test)} do
14
+ act { puts "hey way to go!" }
15
+ pass
16
+ end
17
+
18
+ # When it sees /google, it makes a redirect to google with the value of the query string as the search
19
+ #
20
+ on :uri => %r{/google.*} do
21
+ redirect { "http://google.com/search?q=#{CGI.escape(query_string)}" }
22
+ end
23
+
24
+ # If a URI starts with /valid_place, it strips it off and keeps on truckin'
25
+ #
26
+ on :uri => %r{/valid_place/.*} do
27
+ set(:uri) { uri[%r{/valid_place(/.*)}, 1] }
28
+ pass
29
+ end
30
+
31
+ # If a URI starts with /hello_kitty, add a kitty header equal to your query string
32
+ #
33
+ on :uri => %r{/hello_kitty/.*} do
34
+ act { header['kitty'] = query_string }
35
+ pass
36
+ end
37
+
38
+ fail
39
+ end
40
+
41
+ end
data/VERSION.yml ADDED
@@ -0,0 +1,4 @@
1
+ ---
2
+ :major: 0
3
+ :minor: 0
4
+ :patch: 2
@@ -0,0 +1,142 @@
1
+ module Rack
2
+ class Rewrite
3
+ class Action
4
+
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']
46
+ end
47
+
48
+ def port=(port)
49
+ @env['SERVER_PORT'] = port.to_s
50
+ end
51
+
52
+ def scheme
53
+ @env['rack.url_scheme']
54
+ end
55
+
56
+ def scheme=(scheme)
57
+ @env['rack.url_scheme'] = scheme
58
+ end
59
+
60
+ def setup(env)
61
+ @env = env
62
+ end
63
+
64
+ class Pass < Action
65
+ def call(env)
66
+ throw :pass
67
+ end
68
+ end
69
+
70
+ class Fail < Action
71
+ def call(env)
72
+ raise
73
+ end
74
+ end
75
+
76
+ class Set < Action
77
+
78
+ def initialize(variable, action)
79
+ @variable = variable
80
+ @action = action
81
+ end
82
+
83
+ def call(env)
84
+ setup(env)
85
+ self.send :"#{@variable}=", case @action
86
+ when Proc
87
+ instance_eval(&@action)
88
+ else
89
+ instance_eval(@action)
90
+ end
91
+ env
92
+ end
93
+
94
+ end
95
+
96
+ class Do < Action
97
+ def initialize(caller, action)
98
+ @caller = caller
99
+ @action = action
100
+ end
101
+
102
+ def method_missing(method, *args, &block)
103
+ @caller.send(method, *args, &block)
104
+ end
105
+
106
+ def call(env)
107
+ setup(env)
108
+ case @action
109
+ when Proc
110
+ instance_eval(&@action)
111
+ else
112
+ instance_eval(@action)
113
+ end
114
+ env
115
+ end
116
+
117
+ end
118
+
119
+ class Redirect < Action
120
+ def initialize(caller, action)
121
+ @caller = caller
122
+ @action = action
123
+ end
124
+
125
+ def call(env)
126
+ setup(env)
127
+ @caller.redirect = [ 302, {'Location'=> case @action
128
+ when Proc
129
+ instance_eval(&@action)
130
+ else
131
+ instance_eval(@action)
132
+ end}, []]
133
+ throw :pass
134
+ end
135
+ end
136
+
137
+ end
138
+
139
+ end
140
+ end
141
+
142
+
@@ -0,0 +1,108 @@
1
+ $:.unshift(File.dirname(__FILE__))
2
+ require 'rack_rewrite/actions'
3
+
4
+ module Rack
5
+ class Rewrite
6
+
7
+ attr_accessor :path, :redirect, :headers
8
+
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
41
+
42
+ def initialize(app, options = {}, &block)
43
+ @app = app
44
+ @options = []
45
+ @current_condition_set = @root = ConditionSet.new(nil)
46
+ instance_eval(&block)
47
+ end
48
+
49
+ def on(conditions = {}, &block)
50
+ @current_condition_set.actions << ConditionSet.new(@current_condition_set, conditions)
51
+ @current_condition_set = @current_condition_set.actions.last
52
+ instance_eval(&block)
53
+ @current_condition_set = @current_condition_set.parent_set
54
+ end
55
+
56
+ def set(variable, pattern = nil, &block)
57
+ @current_condition_set.actions << Action::Set.new(variable, pattern || block)
58
+ end
59
+
60
+ def act(&block)
61
+ @current_condition_set.actions << Action::Do.new(self, block)
62
+ end
63
+
64
+ def pass
65
+ @current_condition_set.actions << Action::Pass.new
66
+ end
67
+
68
+ def fail
69
+ @current_condition_set.actions << Action::Fail.new
70
+ end
71
+
72
+ def redirect(pattern = nil, &block)
73
+ @current_condition_set.actions << Action::Redirect.new(self, pattern || block)
74
+ end
75
+
76
+ def call(env)
77
+ @headers = {}
78
+ catch(:pass) {
79
+ env = call_conditions(env, @root)
80
+ raise
81
+ }
82
+ if @redirect
83
+ redirect = @redirect
84
+ @redirect = nil
85
+ redirect
86
+ else
87
+ (status, headers, body) = @app.call(env)
88
+ [status, headers.merge(@headers), body]
89
+ end
90
+ end
91
+
92
+ def call_conditions(env, conditions_set)
93
+ if conditions_set.satisfied?(env)
94
+ conditions_set.actions.each_with_index do |act, index|
95
+ break if @done
96
+ case act
97
+ when ConditionSet
98
+ call_conditions(env, act)
99
+ else
100
+ env = act.call(env)
101
+ end
102
+ end
103
+ end
104
+
105
+ end
106
+
107
+ end
108
+ end
@@ -0,0 +1,22 @@
1
+ require 'spec_helper'
2
+
3
+ describe "Rack::Rewrite Conditions" do
4
+
5
+ ['get', 'post', 'put', 'delete'].each do |method|
6
+
7
+ it "should detect method #{method}" do
8
+ env = Rack::MockRequest.env_for('/test', :method => method)
9
+ app = mock('app')
10
+ app.should_receive(:call).with(env).and_return([200, {}, ["body"]])
11
+ Rack::Rewrite.new(app) { on(:method => method) { pass } }.call(env)
12
+ end
13
+ end
14
+
15
+ it "should detect a simple uri" do
16
+ env = Rack::MockRequest.env_for('/test', :method => 'get')
17
+ app = mock('app')
18
+ app.should_receive(:call).with(env).and_return([200, {}, ["body"]])
19
+ Rack::Rewrite.new(app) { on(:uri => '/test') { pass } }.call(env)
20
+ end
21
+
22
+ end
@@ -0,0 +1,24 @@
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
@@ -0,0 +1,11 @@
1
+ require 'spec'
2
+ require 'rubygems'
3
+ require 'rack'
4
+
5
+ $LOAD_PATH.unshift(File.dirname(__FILE__))
6
+ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
7
+ require 'rack_rewrite'
8
+
9
+ Spec::Runner.configure do |config|
10
+
11
+ end
metadata ADDED
@@ -0,0 +1,61 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: joshbuddy-rack-rewrite
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.2
5
+ platform: ruby
6
+ authors:
7
+ - Joshua Hull
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2009-05-04 00:00:00 -07:00
13
+ default_executable:
14
+ dependencies: []
15
+
16
+ description:
17
+ email: joshbuddy@gmail.com
18
+ executables: []
19
+
20
+ extensions: []
21
+
22
+ extra_rdoc_files:
23
+ - README.rdoc
24
+ files:
25
+ - README.rdoc
26
+ - VERSION.yml
27
+ - lib/rack_rewrite
28
+ - lib/rack_rewrite/actions.rb
29
+ - lib/rack_rewrite.rb
30
+ - spec/conditions_spec.rb
31
+ - spec/rewrite_spec.rb
32
+ - spec/spec_helper.rb
33
+ has_rdoc: true
34
+ homepage: http://github.com/joshbuddy/rack-rewrite
35
+ post_install_message:
36
+ rdoc_options:
37
+ - --inline-source
38
+ - --charset=UTF-8
39
+ require_paths:
40
+ - lib
41
+ required_ruby_version: !ruby/object:Gem::Requirement
42
+ requirements:
43
+ - - ">="
44
+ - !ruby/object:Gem::Version
45
+ version: "0"
46
+ version:
47
+ required_rubygems_version: !ruby/object:Gem::Requirement
48
+ requirements:
49
+ - - ">="
50
+ - !ruby/object:Gem::Version
51
+ version: "0"
52
+ version:
53
+ requirements: []
54
+
55
+ rubyforge_project:
56
+ rubygems_version: 1.2.0
57
+ signing_key:
58
+ specification_version: 2
59
+ summary: TODO
60
+ test_files: []
61
+