| 1 | from django.conf import settings |
|---|
| 2 | from django import http |
|---|
| 3 | from django.core.urlresolvers import resolve |
|---|
| 4 | |
|---|
| 5 | class 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 | |
|---|
| 43 | def _resolves(url): |
|---|
| 44 | try: |
|---|
| 45 | resolve(url) |
|---|
| 46 | return True |
|---|
| 47 | except http.Http404: |
|---|
| 48 | return False |
|---|