django.views.static.serve() redirects (HTTP code 302) to the wrong location when the path to the static file is "normalized"
|Reported by:||Owned by:||nobody|
|Has patch:||no||Needs documentation:||no|
|Needs tests:||no||Patch needs improvement:||no|
For instance, if I have a URL hook for static files set up at
/collection/, and I enter a URL like
django.views.static.serve() will normalize the
/path/to/file.mp3 path down to
path/to/file.mp3 and return an
HttpResponseRedirect with the redirect path set to the normalized path
path/to/file.mp3; that is, it's missing the
/collection/ prefix that needs to be passed back to the Web browser.
Unfortunately, I see no clean way to fix this. The most obvious solution would require passing the URL prefix (
/collection/, in this case) to the
django.views.static.serve() function. That would be pretty ugly. It might be best to disable the redirect feature (?).
For whatever reason, when using Firefox (I didn't try any other browsers), this leads to some odd loop, which causes Django to send 302 forward messages with continuously longer paths (e.g.,
/collection//path/to/path/to/path/to/...). ...Actually, I think I just figured out why: It's because Firefox is trying to do the forward, and it tacks on the
path/to/file.mp3 relative to the current location, so you end up with
path/to/path/to/file.mp3; then, Django normalizes that again and sends another 302. Actually, this problem of infinite redirections (it eventually stops, because of some limit, but anyway) may only occur when you're dealing with filenames that have spaces; I'm not sure, but it may be the case because the spaces will be
%20's in the original path and then normalized to spaces... Yeesh!
Oh, and, I believe this is the problem that the folks on #1291 were seeing. I opened a new ticket because I thought that'd be easier to understand.
By the way, I'm not sure but, I believe I read, somewhere, that HTTP Location headers should always contain a full URL, rather than a simple path. So, instead of saying
Location: /path/to, Django should say
Location: http://appserver/path/to. It doesn't seem to include the full URL, judging from my Firefox Live HTTP Headers extension; I see something like
Location: path/to (exactly what is specified in the creation of the
HttpResponseRedirect object, I believe). Maybe I should file another bug about this (?).