public
Description: Webrat - Ruby Acceptance Testing for Web applications
Homepage: http://gitrdoc.com/brynary/webrat/tree/master/
Clone URL: git://github.com/brynary/webrat.git
Don't follow external redirects
joshknowles (author)
Sun Jan 04 20:56:52 -0800 2009
commit  9825aee47efa7c3ef438db5ce10f410d3f8938c8
tree    bdaa28523bd575a4816d1549d7e3ecafe44b9dd5
parent  4565a3cea641b79a77661b4bda6d3b21f7644886
...
110
111
112
113
 
114
115
116
...
118
119
120
121
 
122
123
124
125
 
 
 
 
126
127
128
...
222
223
224
 
 
 
 
 
 
 
 
 
 
 
 
225
226
227
...
110
111
112
 
113
114
115
116
...
118
119
120
 
121
122
123
124
125
126
127
128
129
130
131
132
...
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
0
@@ -110,7 +110,7 @@ For example:
0
       @http_method  = http_method
0
       @data         = data
0
 
0
-      request_page(response.headers["Location"], :get, data) if redirect?
0
+      request_page(response_location, :get, data) if internal_redirect?
0
 
0
       return response
0
     end
0
@@ -118,11 +118,15 @@ For example:
0
     def success_code? #:nodoc:
0
       (200..499).include?(response_code)
0
     end
0
-    
0
+
0
     def redirect? #:nodoc:
0
       response_code / 100 == 3
0
     end
0
 
0
+    def internal_redirect? #:nodoc:
0
+      redirect? && current_host == response_location_host
0
+    end
0
+
0
     def exception_caught? #:nodoc:
0
       response_body =~ /Exception caught/
0
     end
0
@@ -222,6 +226,18 @@ For example:
0
 
0
   private
0
 
0
+    def response_location
0
+      response.headers["Location"]
0
+    end
0
+
0
+    def current_host
0
+      URI.parse(current_url).host || "www.example.com"
0
+    end
0
+
0
+    def response_location_host
0
+      URI.parse(response_location).host || "www.example.com"
0
+    end
0
+
0
     def reset
0
       @elements     = {}
0
       @_scopes      = nil
...
7
8
9
10
 
11
12
13
 
 
 
 
14
15
...
7
8
9
 
10
11
12
13
14
15
16
17
18
19
0
@@ -7,8 +7,12 @@ class Testing < Application
0
   def submit_form
0
   end
0
   
0
-  def redirect_to_root
0
+  def internal_redirect
0
     redirect "/"
0
   end
0
   
0
+  def external_redirect
0
+    redirect "http://google.com"
0
+  end
0
+  
0
 end
0
\ No newline at end of file
...
28
29
30
31
 
 
32
33
...
28
29
30
 
31
32
33
34
0
@@ -28,5 +28,6 @@
0
 Merb.logger.info("Compiling routes...")
0
 Merb::Router.prepare do
0
   match("/").to(:controller => "testing", :action => "show_form")
0
-  match("/redirect").to(:controller => "testing", :action => "redirect_to_root")
0
+  match("/internal_redirect").to(:controller => "testing", :action => "internal_redirect")
0
+  match("/external_redirect").to(:controller => "testing", :action => "external_redirect")
0
 end
0
\ No newline at end of file
...
14
15
16
17
18
 
 
 
19
20
 
 
 
 
 
21
22
...
14
15
16
 
 
17
18
19
20
21
22
23
24
25
26
27
28
0
@@ -14,8 +14,14 @@ describe "Webrat" do
0
     click_button "Test"
0
   end
0
 
0
-  it "should follow redirects" do
0
-    response = visit "/redirect"
0
+  it "should follow internal redirects" do
0
+    response = visit "/internal_redirect"
0
+    response.status.should == 200
0
     response.should contain("Webrat Form")
0
   end
0
+
0
+  it "should not follow external redirects" do
0
+    response = visit "/external_redirect"
0
+    response.status.should == 302
0
+  end
0
 end
0
\ No newline at end of file
...
7
8
9
10
 
11
12
 
 
 
 
13
14
15
...
7
8
9
 
10
11
12
13
14
15
16
17
18
19
0
@@ -7,8 +7,12 @@ class WebratController < ApplicationController
0
     render :text => "OK"
0
   end
0
 
0
-  def redirect
0
+  def internal_redirect
0
     redirect_to :submit
0
   end
0
+  
0
+  def external_redirect
0
+    redirect_to "http://google.com"
0
+  end
0
 
0
 end
0
\ No newline at end of file
...
1
2
3
4
 
 
 
5
6
7
...
1
2
 
 
3
4
5
6
7
8
0
@@ -1,7 +1,8 @@
0
 ActionController::Routing::Routes.draw do |map|
0
   map.with_options :controller => "webrat" do |webrat|
0
-    webrat.submit   "/submit",    :action => "submit"
0
-    webrat.redirect "/redirect",  :action => "redirect"
0
+    webrat.submit             "/submit",            :action => "submit"
0
+    webrat.internal_redirect  "/internal_redirect", :action => "internal_redirect"
0
+    webrat.external_redirect  "/external_redirect", :action => "external_redirect"
0
 
0
     webrat.root :action => "form"
0
   end
...
15
16
17
18
19
 
 
20
21
 
 
 
 
 
22
...
15
16
17
 
 
18
19
20
21
22
23
24
25
26
27
0
@@ -15,8 +15,13 @@ class WebratTest < ActionController::IntegrationTest
0
     click_button "Test"
0
   end
0
 
0
-  test "should follow redirects" do
0
-    visit redirect_path
0
+  test "should follow internal redirects" do
0
+    visit internal_redirect_path
0
     assert response.body.include?("OK")
0
   end
0
+  
0
+  test "should not follow external redirects" do
0
+    visit external_redirect_path
0
+    assert response.redirect?
0
+  end
0
 end
...
1
2
3
 
4
5
 
6
7
8
9
 
10
11
12
13
14
 
15
16
17
 
 
 
 
 
18
19
20
21
22
23
 
24
25
26
...
31
32
33
34
 
35
36
37
 
38
39
40
...
47
48
49
50
 
51
52
53
54
...
1
2
 
3
4
 
5
6
7
8
 
9
10
11
12
13
 
14
15
16
 
17
18
19
20
21
22
23
24
25
26
 
27
28
29
30
...
35
36
37
 
38
39
40
 
41
42
43
44
...
51
52
53
 
54
55
56
57
58
0
@@ -1,26 +1,30 @@
0
 require "rubygems"
0
 require "sinatra"
0
- 
0
+
0
 use_in_file_templates!
0
- 
0
+
0
 get "/" do
0
   erb :home
0
 end
0
- 
0
+
0
 get "/go" do
0
   erb :go
0
 end
0
 
0
-get "/redirect" do
0
+get "/internal_redirect" do
0
   redirect "/"
0
 end
0
0
+
0
+get "/external_redirect" do
0
+  redirect "http://google.com"
0
+end
0
+
0
 post "/go" do
0
   @user = params[:name]
0
   @email = params[:email]
0
   erb :hello
0
 end
0
- 
0
+
0
 __END__
0
 
0
 @@ layout
0
@@ -31,10 +35,10 @@ __END__
0
     <%= yield %>
0
   </body>
0
 </html>
0
- 
0
+
0
 @@ home
0
 <p> visit <a href="/go">there</a></p>
0
- 
0
+
0
 @@ go
0
 <form method="post" action="/go">
0
   <div>
0
@@ -47,7 +51,7 @@ __END__
0
   </div>
0
   <input type="submit" value="Submit" />
0
 </form>
0
- 
0
+
0
 @@ hello
0
 <p>Hello, <%= @user %></p>
0
 <p>Your email is: <%= @email %></p>
0
\ No newline at end of file
...
8
9
10
11
 
12
13
14
15
16
17
 
18
19
20
21
22
23
 
 
 
24
25
 
 
 
 
 
26
...
8
9
10
 
11
12
13
14
15
16
 
17
18
19
20
 
 
 
21
22
23
24
25
26
27
28
29
30
31
0
@@ -8,19 +8,24 @@ class WebratTest < Test::Unit::TestCase
0
     click_link "there"
0
     assert response_body.include?('<form method="post" action="/go">')
0
   end
0
-  
0
+
0
   def test_submits_form
0
     visit "/go"
0
     fill_in "Name", :with => "World"
0
     fill_in "Email", :with => "world@example.org"
0
     click_button "Submit"
0
-    
0
+
0
     assert response_body.include?("Hello, World")
0
     assert response_body.include?("Your email is: world@example.org")
0
   end
0
-  
0
-  def test_follows_redirects
0
-    visit "/redirect"
0
+
0
+  def test_follows_internal_redirects
0
+    visit "/internal_redirect"
0
     assert response_body.include?("visit")
0
   end
0
+
0
+  def test_does_not_follow_external_redirects
0
+    visit "/external_redirect"
0
+    assert response_code == 302
0
+  end
0
 end
...
113
114
115
116
117
 
 
118
119
120
121
122
123
 
 
 
 
 
 
 
 
124
125
126
...
138
139
140
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
141
142
...
113
114
115
 
 
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
...
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
0
@@ -113,14 +113,22 @@ describe Webrat::Session do
0
       lambda { webrat_session.request_page('some url', :get, {}) }.should raise_error(Webrat::PageLoadError)
0
     end
0
 
0
-    it "should follow redirects" do
0
-      webrat_session.should_receive(:redirect?).twice.and_return(true, false)
0
+    it "should follow internal redirects" do
0
+      webrat_session.should_receive(:internal_redirect?).twice.and_return(true, false)
0
       webrat_session.response.should_receive(:headers).once.and_return({ "Location" => "/newurl" })
0
 
0
       webrat_session.request_page("/oldurl", :get, {})
0
 
0
       webrat_session.current_url.should == "/newurl"
0
     end
0
+
0
+    it "should now follow external redirects" do
0
+      webrat_session.should_receive(:internal_redirect?).and_return(false)
0
+
0
+      webrat_session.request_page("/oldurl", :get, {})
0
+
0
+      webrat_session.current_url.should == "/oldurl"
0
+    end
0
   end
0
 
0
   describe "#redirect?" do
0
@@ -138,4 +146,29 @@ describe Webrat::Session do
0
       webrat_session.redirect?.should be_false
0
     end
0
   end
0
+  
0
+  describe "#internal_redirect?" do
0
+    before(:each) do
0
+      webrat_session = Webrat::Session.new
0
+    end
0
+
0
+    it "should return true if the last response was a redirect and the host of the current_url matches that of the response location" do
0
+      webrat_session.stub!(:redirect?         => true)
0
+      webrat_session.stub!(:current_url       => "http://example.com")
0
+      webrat_session.stub!(:response_location => "http://example.com")
0
+      webrat_session.internal_redirect?.should be_true
0
+    end
0
+    
0
+    it "should return false if the last response was not a redirect" do
0
+      webrat_session.stub!(:redirect? => false)
0
+      webrat_session.internal_redirect?.should be_false
0
+    end
0
+    
0
+    it "should return false if the last response was a redirect but the host of the current_url doesn't matches that of the response location" do
0
+      webrat_session.stub!(:redirect?         => true)
0
+      webrat_session.stub!(:current_url       => "http://example.com")
0
+      webrat_session.stub!(:response_location => "http://google.com")
0
+      webrat_session.internal_redirect?.should be_false
0
+    end
0
+  end
0
 end
0
\ No newline at end of file
...
31
32
33
34
35
 
 
36
37
38
39
40
41
 
 
 
 
 
 
 
 
42
43
44
...
31
32
33
 
 
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
0
@@ -31,14 +31,22 @@ describe "visit" do
0
     lambda { fill_in "foo", :with => "blah" }.should raise_error(Webrat::WebratError)
0
   end
0
 
0
-  it "should follow redirects" do
0
-    webrat_session.should_receive(:redirect?).twice.and_return(true, false)
0
+  it "should follow internal redirects" do
0
+    webrat_session.should_receive(:internal_redirect?).twice.and_return(true, false)
0
     webrat_session.response.should_receive(:headers).once.and_return({ "Location" => "/newurl" })
0
 
0
     visit("/oldurl")
0
 
0
     current_url.should == "/newurl"
0
   end
0
+
0
+  it "should not follow external redirects" do
0
+    webrat_session.should_receive(:internal_redirect?).and_return(false)
0
+
0
+    visit("/oldurl")
0
+
0
+    current_url.should == "/oldurl"
0
+  end
0
 end
0
 
0
 describe "visit with referer" do

Comments

gaffo Mon Jan 05 08:57:19 -0800 2009

Hey, did you ever add a way to get a hold of the redirect location in a platform independent way?