404 with non-/ WSGI, script prefix not removed in core/urlresolvers.py: resolve()
|Reported by:||Owned by:||nobody|
|Severity:||Normal||Keywords:||404, WSGIScriptAlias, wsgi, resolve, url, prefix|
|Has patch:||yes||Needs documentation:||no|
|Needs tests:||no||Patch needs improvement:||no|
I've just had a nasty WSGI bug with Django 1.4 while using a non-/ WSGIScriptAlias with apache2. I tracked down the bug and found a cause so here is a patch for review, if you like.
Sorry in advance if this is a known and fixed bug, but then please consider patching 1.4 stable release?
urlpatterns = patterns('', r'^bug/$', 'app.views.Bug')
Django runserver => everything OK
apache2 + WSGIScriptAlias / => everything OK
apache2 + WSGIScriptAlias /test => breaks
Details: request URL
'^bug/$' did not match current URL
'bug/' - silly right? :) obviously this is not reporting the actual URL it was checked against, maybe something to fix to have a more meaningful error message.
A quick debug of WSGI reveals apache is properly giving all the info to Django:
After a quick search it seems to be a known bug on the interwebs but solutions I've seen were ugly (write the prefix statically in the app).
Diving into Django I found core/urlresolvers.py with:
class RegexURLResolver(LocaleRegexProvider): [...] def resolve(self, path): [...] new_path = path[match.end():] for pattern in self.url_patterns:
With request path
'test/bug/', and this obviously does not match against
Proposed fix: if present, remove
new_path (after applying the same regexp).
new_path = path[match.end():] + # Get script prefix, apply regexp and remove from path if present. + prefix = get_script_prefix() + if prefix: + match = self.regex.search(prefix) + if match: + prefix = prefix[match.end():] + if new_path.startswith(prefix): + new_path = new_path[len(prefix):] for pattern in self.url_patterns:
Now everything works as expected, I hope I did not miss anything.
Let me know if you have any questions and thanks for providing this great framework :)