joshbuddy-rack-rewrite 0.0.2

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 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
+