Created
December 7, 2013 17:48
-
-
Save eezis/7846063 to your computer and use it in GitHub Desktop.
A Django Middleware Redirection class that provides a "last chance" to grab a developing 404 response and redirect it to a new URL.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
""" | |
This piece of middleware grabs onto the tail end of process_response hook | |
and allows for redirects to be applied using regex matches. | |
Use Case: A legacy website with many old urls will have accumulated SEO mojo based | |
on external links. When the site is converted to a new fromat (say, drops the cruft like '.html') | |
or goes from abbreviated forms /art/id/t/234234 to /article/2014/january/technology/get-a-better-job | |
the old urls are at risk of breakage and could lose SEO mojo unless preserved | |
Best preservation comes from redirecting old content to new, which is easily accomplished | |
using 'django.contrib.redirects.middleware.RedirectFallbackMiddleware'. This class catches | |
the stuff that falls through the cracks; it gives the developer a last chance effort to | |
catch and redirect. Say that "t" stood for technology in this url: /art/id/t/234234 | |
it might be a good idea to redirect unmatched /art/id/t/foobard to /article/2014/technology | |
where the latter page lists an index of all articles by title | |
While you can perform a regex redirect in your http server, in urls.py, and in the django middleware, | |
that would miss the opportunity to preserve specific redirects that should live in the django Redirect table | |
nginx --> urls --> 'django.contrib.redirects.middleware.RedirectFallbackMiddleware' -> LastChanceRedirect | |
*** NOTE WELL *** order is important this should be the last load in the middleware stack in settings.py | |
if you are using 'django.contrib.redirects.middleware.RedirectFallbackMiddleware' it must come after that! | |
MIDDLEWARE_CLASSES = ( | |
'django.middleware.common.CommonMiddleware', | |
... | |
# put the redirectfallbackmiddleware end of list; order matters | |
'django.contrib.redirects.middleware.RedirectFallbackMiddleware', | |
'<yourmoduledir>.redirectmiddleware.LastChanceRedirect', | |
) | |
https://docs.djangoproject.com/en/1.6/topics/http/middleware/ | |
""" | |
from django import http | |
import re | |
redir_checks = { | |
# 'regexpattern_for_old_path' : 'new/path/redirect' | |
'^/test/([\w\.]{2,20})$': '/newurl', | |
} | |
class LastChanceRedirect(object): | |
# Defined as class-level attributes to be subclassing-friendly (from contrib.middlware.py) | |
response_gone_class = http.HttpResponseGone | |
response_redirect_class = http.HttpResponsePermanentRedirect | |
def process_response(self, request, response): | |
# only check 404 responses, all others should pass unmolested | |
if response.status_code != 404: | |
return response | |
sought_url = request.get_full_path() | |
matched = False | |
try: | |
for key, value in redir_checks.items(): | |
if re.match(key,sought_url,re.I): | |
matched = True | |
new_path = value | |
except: | |
pass | |
if matched: | |
if new_path == '': | |
return self.response_gone_class() | |
else: | |
return self.response_redirect_class(new_path) | |
# Return the 'normal' response if a redirection was not found | |
return response | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment