title: fix_location_header in Django causes wrong redirection to LOGIN_URL
body: <p>I am trying to send an oauth request from another application to Django. Django is hosted on 8000 port and the application on 8080. Here is the URL called from the application:</p>
  
  <pre><code>http://localhost:8000/o/authorize/?client_id=MM8i27ROetg3OQv60tDcJwp7JKXi28FqkuQgetyG&amp;response_type=token&amp;redirect_url=http://localhost:8080/auth/add_token
  </code></pre>
  
  <p>This will get redirected to a wrong location:</p>
  
  <pre><code>http://192.168.56.101:8000/o/authorize/accounts/login/?next=/o/authorize/%3Fclient_id%3DMM8i27ROetg3OQv60tDcJwp7JKXi28FqkuQgetyG%26response_type%3Dtoken%26redirect_url%3Dhttp%3A//192.168.56.101%3A8080/auth/add_token
  </code></pre>
  
  <p>when I expect it to be without the prefix <code>/o/authorize</code> which is is generated by WSGI handler using HTTP header called <a href="https://docs.djangoproject.com/en/1.9/ref/request-response/#django.http.HttpRequest.path_info" rel="nofollow">PATH_INFO</a>:</p>
  
  <pre><code>http://192.168.56.101:8000/accounts/login/?next=/o/authorize/%3Fclient_id%3DMM8i27ROetg3OQv60tDcJwp7JKXi28FqkuQgetyG%26response_type%3Dtoken%26redirect_url%3Dhttp%3A//192.168.56.101%3A8080/auth/add_token
  </code></pre>
  
  <p>I have following routes in urls.py and they work properly if it is not for the weird redirection I am facing.</p>
  
  <pre><code>url(r'^o/', include('oauth2_provider.urls', namespace='oauth2_provider')),
  # OAuth User Info
  url(r'^o/api/get_userinfo/$', oauth2.GetuserInfoView.as_view(), name="get-userinfo"),
  </code></pre>
  
  <p>In settings.py I have:</p>
  
  <pre><code>LOGIN_URL = "/accounts/login"
  </code></pre>
  
  <p>Now here are the lines of Django code that I find problematic. </p>
  
  <p>django/core/handlers/base.py:220</p>
  
  <pre><code>        # Apply response middleware, regardless of the response
          for middleware_method in self._response_middleware:
              response = middleware_method(request, response)
              # Complain if the response middleware returned None (a common error).
              if response is None:
                  raise ValueError(
                      "%s.process_response didn't return an "
                      "HttpResponse object. It returned None instead."
                      % (middleware_method.__self__.__class__.__name__))
          response = self.apply_response_fixes(request, response)
                     # ^^^------------this will lead to fix_location_header being called.
  </code></pre>
  
  <p>django/http/utils.py</p>
  
  <pre><code>def fix_location_header(request, response):
      """
      Ensures that we always use an absolute URI in any location header in the
      response. This is required by RFC 2616, section 14.30.
  
      Code constructing response objects is free to insert relative paths, as
      this function converts them to absolute paths.
      """
      if 'Location' in response:
          response['Location'] = request.build_absolute_uri(response['Location'])
      return response
  </code></pre>
  
  <p>django/request.py</p>
  
  <pre><code>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()``. Anyway, if the location is
      absolute, it is simply converted to an RFC 3987 compliant URI and
      returned and if location is relative or is scheme-relative (i.e.,
      ``//example.com/``), it is urljoined to a base URL constructed from the
      request variables.
      """
      if location is None:
          # Make it an absolute url (but schemeless and domainless) for the
          # edge case that the path starts with '//'.
          location = '//%s' % self.get_full_path()
      bits = urlsplit(location)
      if not (bits.scheme and bits.netloc):
          current_uri = '{scheme}://{host}{path}'.format(scheme=self.scheme,
                                                         host=self.get_host(),
                                                         path=self.path)
          # ^^^---The location URL forming logic that I find problematic.
          # Join the constructed URL with the provided location, which will
          # allow the provided ``location`` to apply query strings to the
          # base path as well as override the host, if it begins with //
          location = urljoin(current_uri, location)
      return iri_to_uri(location)
  </code></pre>
  
  <p>I included the comments from the source file so the reader could know there are use cases for them. </p>
  
  <p>So what is the proper way of getting around <code>apply_reponse_fix</code>? 1) inherit and rewrite the function 2) modify HTTP header PATH_INFO... somehow 3) change the logic for <code>Location</code> header in response so that it is a full URI with <code>http://</code> prefix so that <code>bits.scheme</code> is not None. None of them seem like a proper fix for me, so I am wondering if I overlooked a convention. Any insight will be very helpful.</p>