root / trunk / middleware / common.py

Revision 173, 1.9 kB (checked in by akaihola, 6 months ago)

[middleware] Added the smart append slash middleware.

  • Property svn:eol-style set to native
Line 
1from django.conf import settings
2from django import http
3from django.core.urlresolvers import resolve
4
5class SmartAppendSlashMiddleware(object):
6    """
7    "SmartAppendSlash" middleware for taking care of URL rewriting.
8
9    This middleware appends a missing slash, if:
10    * the SMART_APPEND_SLASH setting is True
11    * the URL without the slash does not exist
12    * the URL with an appended slash does exist.
13    Otherwise it won't touch the URL.
14    """
15
16    def process_request(self, request):
17        """
18        Rewrite the URL based on settings.SMART_APPEND_SLASH
19        """
20
21        # Check for a redirect based on settings.SMART_APPEND_SLASH
22        host = http.get_host(request)
23        old_url = [host, request.path]
24        new_url = old_url[:]
25        # Append a slash if SMART_APPEND_SLASH is set and the resulting URL
26        # resolves.
27        if settings.SMART_APPEND_SLASH and (not old_url[1].endswith('/')) and not _resolves(old_url[1]) and _resolves(old_url[1] + '/'):
28            new_url[1] = new_url[1] + '/'
29            if settings.DEBUG and request.method == 'POST':
30                raise RuntimeError, "You called this URL via POST, but the URL doesn't end in a slash and you have SMART_APPEND_SLASH set. Django can't redirect to the slash URL while maintaining POST data. Change your form to point to %s%s (note the trailing slash), or set SMART_APPEND_SLASH=False in your Django settings." % (new_url[0], new_url[1])
31        if new_url != old_url:
32            # Redirect
33            if new_url[0]:
34                newurl = "%s://%s%s" % (request.is_secure() and 'https' or 'http', new_url[0], new_url[1])
35            else:
36                newurl = new_url[1]
37            if request.GET:
38                newurl += '?' + request.GET.urlencode()
39            return http.HttpResponsePermanentRedirect(newurl)
40
41        return None
42
43def _resolves(url):
44    try:
45        resolve(url)
46        return True
47    except http.Http404:
48        return False
Note: See TracBrowser for help on using the browser.