Matthew Schinckel avatar Matthew Schinckel committed 296c6dd Merge

Merge

Comments (0)

Files changed (2)

tests/test_test.py

 
 
 def external_redirect_demo_app(environ, start_response):
-    response = redirect('http://example.org/')
+    response = redirect('http://example.com/')
+    return response(environ, start_response)
+
+
+def external_subdomain_redirect_demo_app(environ, start_response):
+    if 'test.example.com' in environ['HTTP_HOST']:
+        response = Response('redirected successfully to subdomain')
+    else:
+        response = redirect('http://test.example.com/login')
     return response(environ, start_response)
 
 
 def test_follow_external_redirect():
     env = create_environ('/', base_url='http://localhost')
     c = Client(external_redirect_demo_app)
-    assert_raises(RuntimeError, lambda: c.open(environ_overrides=env, follow_redirects=True))
+    assert_raises(RuntimeError, lambda: c.get(environ_overrides=env, follow_redirects=True))
+
+
+def test_follow_external_redirect_on_same_subdomain():
+    env = create_environ('/', base_url='http://example.com')
+    c = Client(external_subdomain_redirect_demo_app, allow_subdomain_redirects=True)
+    c.get(environ_overrides=env, follow_redirects=True)
+
+    # check that this does not work for real external domains
+    env = create_environ('/', base_url='http://localhost')
+    assert_raises(RuntimeError, lambda: c.get(environ_overrides=env, follow_redirects=True))
+
+    # check that subdomain redirects fail if no `allow_subdomain_redirects` is applied
+    c = Client(external_subdomain_redirect_demo_app)
+    assert_raises(RuntimeError, lambda: c.get(environ_overrides=env, follow_redirects=True))
 
 
 @raises(ClientRedirectError)
     sent for subsequent requests. This is True by default, but passing False
     will disable this behaviour.
 
+    If you want to request some subdomain of your application you may set
+    `allow_subdomain_redirects` to `True` as if not no external redirects
+    are allowed.
+
     .. versionadded:: 0.5
        `use_cookies` is new in this version.  Older versions did not provide
        builtin cookie support.
     """
 
-    def __init__(self, application, response_wrapper=None, use_cookies=True):
+    def __init__(self, application, response_wrapper=None, use_cookies=True,
+                 allow_subdomain_redirects=False):
         self.application = application
         if response_wrapper is None:
             response_wrapper = lambda a, s, h: (a, s, h)
         else:
             self.cookie_jar = None
         self.redirect_client = None
+        self.allow_subdomain_redirects = allow_subdomain_redirects
 
     def open(self, *args, **kwargs):
         """Takes the same arguments as the :class:`EnvironBuilder` class with
                 self.redirect_client.cookie_jar = self.cookie_jar
 
             redirect = dict(rv[2])['Location']
+
             scheme, netloc, script_root, qs, anchor = urlparse.urlsplit(redirect)
             base_url = urlparse.urlunsplit((scheme, netloc, '', '', '')).rstrip('/') + '/'
-            host = get_host(create_environ('/', base_url, query_string=qs)).split(':', 1)[0]
-            if get_host(environ).split(':', 1)[0] != host:
+
+            cur_server_name = netloc.split(':', 1)[0].split('.')
+            real_server_name = get_host(environ).split(':', 1)[0].split('.')
+
+            if self.allow_subdomain_redirects:
+                allowed = cur_server_name[-len(real_server_name):] == real_server_name
+            else:
+                allowed = cur_server_name == real_server_name
+
+            if not allowed:
                 raise RuntimeError('%r does not support redirect to '
                                    'external targets' % self.__class__)
 
 
             # the redirect request should be a new request, and not be based on
             # the old request
+
             redirect_kwargs = {
                 'path':             script_root,
                 'base_url':         base_url,
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.