On Mon, 2009-01-19 at 18:42 -0800, csingley wrote:
> I've got a Django project set up behind an Apache SSL listener on port
> 443. Unfortunately, this seems to break HTTP redirects.
>
> For example, I have one view like this:
> """
> @login_required
> def home(request):
> return HttpResponseRedirect('/user/%s/' % request.user)
> """
>
> When a user hits this view, HTTP request/response headers go like
> this:
> """
> https://www.${DOMAIN}.com/user/home/
>
> GET /user/home/ HTTP/1.1
> Host: www.${DOMAIN}.com:443
> User-Agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.0.5) Gecko/
> 2009011218 Gentoo Firefox/3.0.5
> Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/
> *;q=0.8
> Accept-Language: en-us,en;q=0.5
> Accept-Encoding: gzip,deflate
> Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7
> Keep-Alive: 300
> Connection: keep-alive
> Cookie: sessionid=e81f501da88277eb901df1aa3d3aa454
>
> HTTP/1.x 302 Found
> Date: Mon, 19 Jan 2009 23:37:18 GMT
> Server: JWS 1.3
> Served-By: Joyent
> Vary: Cookie,Accept-Encoding
> Content-Type: text/html; charset=utf-8
> Location: http://www.${DOMAIN}.com:443/user/${USER}/
> Via: 1.1 ${DOMAIN}.com
> Content-Encoding: gzip
> Content-Length: 20
> Connection: close
> """
>
> Now, all the other browsers I've tried seem to be smart enough to
> guess that if it's port 443, then maybe they should try SSL,
Which means all the other browsers you tried are broken. If the URL says
the schema is "http", that's what they should be using.
> but for
> some reason Firefox gets its panties all in a bunch, sits down in a
> huff, and throws this error:
> """
> Bad Request
Correctly so, too.
So the solution here is going to depend a bit upon what your particular
setup is, and this kind of stuff is always very hard to debug without
specific knowledge and a lot of time. If your hosting provider has
support forums, that could well be a good place to search for clues,
since it's not unlikely somebody will have come across this problem
before. Here's the general background...
When you return something like HttpResponseRedirect("/foo/bar") from
Django, it has to turn that into an absolute URL, since Location headers
must be absolute, not relative. Part of an absolute URL is the schema
(the "http://" or "https://" part). Django works that out by looking at
the incoming request. See django/http/__init__.py in the
HttpRequest.build_absolute_uri() method for the details.
If the web server handling the Django requests is not the external web
server, but is proxied for by some other server (e.g. Apache facing the
outside world, passing off requests to a particular URL prefix to some
other webserver that is doing the Django work), it might be that the
internal connection between external web server and django-handling
webserver is only HTTP, not HTTPS. In that case, Django thinks the
request is an HTTP request and constructs the absolute URL
appropriately.
This situation isn't uncommon when using fastcgi, for example.
In that sort of situation, it is the responsibility of the external
webserver to rewrite any outgoing URLs correctly for the external world.
Thus, it should know that it is converting an incoming HTTPS request to
an HTTP request and thus convert any URLs for the local hostname back
again before replying. In Apache, for example, this is often done with
the ProxyPassReverse directive in the mod_proxy module. The
ProxyPassReverseCookieDomain and related directives also need to be at
considered, depending upon how much rewriting is done.
Now, all of this might have absolutely no bearing on your situation. I
don't know. I don't know the details of how your setup at Joyent is
configured. But it looks a lot like the request is reaching the server
handling your Django requests as an HTTP request, in which case, Django
is doing the right thing, as is Firefox, and the problem then reduces to
working out why an incoming HTTPS request is being converted to an HTTP
request. It's not inconceivable that for some reason the
HttpRequest.is_secure() method isn't returning the right thing,
although, again, that would suggest a bug in the WSGI wrapper that
you're using (most likely).
That should at least give you some ideas about how to start tracking
down the root cause of the problem. Work out why the incoming HTTPS
request looks like HTTP once it reaches Django. If it's converted by
some reverse proxy server (e.g. an external facing webserver), that
server is must be configured to do the reverse conversion for outgoing
requests as well. If it's something else, well... you'd need to work out
what it is, then we can start investigating possible solutions.
Regards,
Malcolm
--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups
"Django users" group.
To post to this group, send email to [email protected]
To unsubscribe from this group, send email to
[email protected]
For more options, visit this group at
http://groups.google.com/group/django-users?hl=en
-~----------~----~----~----~------~----~------~--~---