Index: django/core/handlers/base.py
===================================================================
--- django/core/handlers/base.py	(revision 6094)
+++ django/core/handlers/base.py	(working copy)
@@ -3,7 +3,19 @@
 from django import http
 import sys
 
+class BaseRequiredProcesses(object):
+    def process_response(self, request, response):
+        # Absolute URI redirects: Ensures that any redirect attempt (which uses
+        # the HTTP Location header) to a relative location is converted to an
+        # absolute URI, as required by RFC 2616, section 14.30.
+        # This is only possible if the host name can be gleaned from request.
+        if 'Location' in response.headers and http.get_host(request):
+            response['Location'] = request.build_absolute_uri(response['Location'])
+        return response
+
 class BaseHandler(object):
+    required_processes = BaseRequiredProcesses
+
     def __init__(self):
         self._request_middleware = self._view_middleware = self._response_middleware = self._exception_middleware = None
 
@@ -15,10 +27,8 @@
         """
         from django.conf import settings
         from django.core import exceptions
-        self._request_middleware = []
-        self._view_middleware = []
-        self._response_middleware = []
-        self._exception_middleware = []
+
+        middleware_classes = [self.required_processes]
         for middleware_path in settings.MIDDLEWARE_CLASSES:
             try:
                 dot = middleware_path.rindex('.')
@@ -30,15 +40,19 @@
             except ImportError, e:
                 raise exceptions.ImproperlyConfigured, 'Error importing middleware %s: "%s"' % (mw_module, e)
             try:
-                mw_class = getattr(mod, mw_classname)
+                middleware_classes.append(getattr(mod, mw_classname))
             except AttributeError:
                 raise exceptions.ImproperlyConfigured, 'Middleware module "%s" does not define a "%s" class' % (mw_module, mw_classname)
 
+        self._request_middleware = []
+        self._view_middleware = []
+        self._response_middleware = []
+        self._exception_middleware = []
+        for mw_class in middleware_classes:
             try:
                 mw_instance = mw_class()
             except exceptions.MiddlewareNotUsed:
                 continue
-
             if hasattr(mw_instance, 'process_request'):
                 self._request_middleware.append(mw_instance.process_request)
             if hasattr(mw_instance, 'process_view'):
Index: django/http/__init__.py
===================================================================
--- django/http/__init__.py	(revision 6094)
+++ django/http/__init__.py	(working copy)
@@ -1,7 +1,8 @@
 import os
 from Cookie import SimpleCookie
 from pprint import pformat
-from urllib import urlencode
+from urllib import urlencode, quote
+from urlparse import urljoin
 from django.utils.datastructures import MultiValueDict, FileDict
 from django.utils.encoding import smart_str, iri_to_uri, force_unicode
 
@@ -44,6 +45,20 @@
     def get_full_path(self):
         return ''
 
+    def build_absolute_uri(self, location=None):
+        """
+        Builds an absolute URI from the location and the variables available in
+        this request. If no location is specified, the absolute URI is built on
+        ``request.get_full_path()``.
+        """
+        if not location:
+            location = request.get_full_path()
+        if not ':' in location:
+            current_uri = '%s://%s%s' % (self.is_secure() and 'https' or 'http',
+                                         get_host(self), self.path)
+            location = urljoin(current_uri, location)
+        return location
+
     def is_secure(self):
         return os.environ.get("HTTPS") == "on"
 
Index: django/test/testcases.py
===================================================================
--- django/test/testcases.py	(revision 6094)
+++ django/test/testcases.py	(working copy)
@@ -84,12 +84,8 @@
         self.assertEqual(response.status_code, status_code,
             ("Response didn't redirect as expected: Response code was %d"
              " (expected %d)" % (response.status_code, status_code)))
-        scheme, netloc, path, query, fragment = urlsplit(response['Location'])
-        url = path
-        if query:
-            url += '?' + query
-        if fragment:
-            url += '#' + fragment
+        url = response['Location']
+        scheme, netloc, path, query, fragment = urlsplit(url)
         self.assertEqual(url, expected_url,
             "Response redirected to '%s', expected '%s'" % (url, expected_url))
 
Index: docs/request_response.txt
===================================================================
--- docs/request_response.txt	(revision 6094)
+++ docs/request_response.txt	(working copy)
@@ -161,6 +161,16 @@
 
    Example: ``"/music/bands/the_beatles/?print=true"``
 
+``build_absolute_uri(location)``
+   Returns an absolute URI from the location. If no location is provided, the
+   location will be set to ``request.get_full_path()``.
+
+   If the location is already an absolute URI, it will not be altered,
+   otherwise the absolute URI is built using the server variables available in
+   this request.
+
+   Example: ``"http://example.com/music/bands/the_beatles/?print=true"``
+
 ``is_secure()``
    Returns ``True`` if the request is secure; that is, if it was made with
    HTTPS.
Index: tests/modeltests/test_client/models.py
===================================================================
--- tests/modeltests/test_client/models.py	(revision 6094)
+++ tests/modeltests/test_client/models.py	(working copy)
@@ -83,9 +83,13 @@
     def test_redirect(self):
         "GET a URL that redirects elsewhere"
         response = self.client.get('/test_client/redirect_view/')
-        
         # Check that the response was a 302 (redirect)
         self.assertRedirects(response, '/test_client/get_view/')
+        
+        client_providing_host = Client(HTTP_HOST='django.testserver')
+        response = client_providing_host.get('/test_client/redirect_view/')
+        # Check that the response was a 302 (redirect) with absolute URI
+        self.assertRedirects(response, 'http://django.testserver/test_client/get_view/')
     
     def test_redirect_with_query(self):
         "GET a URL that redirects with given GET parameters"
@@ -97,10 +101,14 @@
     def test_permanent_redirect(self):
         "GET a URL that redirects permanently elsewhere"
         response = self.client.get('/test_client/permanent_redirect_view/')
-        
         # Check that the response was a 301 (permanent redirect)
         self.assertRedirects(response, '/test_client/get_view/', status_code=301)
 
+        client_providing_host = Client(HTTP_HOST='django.testserver')
+        response = client_providing_host.get('/test_client/permanent_redirect_view/')
+        # Check that the response was a 301 (permanent redirect) with absolute URI
+        self.assertRedirects(response, 'http://django.testserver/test_client/get_view/', status_code=301)
+
     def test_redirect_to_strange_location(self):
         "GET a URL that redirects to a non-200 page"
         response = self.client.get('/test_client/double_redirect_view/')
