We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
UnicodeDecodeError ('ascii' codec can't decode) when memcached enabled
I can reproduce this on Ubuntu 12 and CentOS 6.   

memcached installed and enabled.  

Install new virtualenv and activate
~/venv/workingvirtualenv
source ~/venv/workingvirtulaenv/bin/activate

pip install mezzanine
pip install python-memcached
mezzanine-project testproject

add the live_settings.py cache settings to local_settings.py

Now create the DB
python manage.py createdb

Select all defaults and answer yes to questions including creating demo data..
Can browse demo pages including /gallery with no errors and caching appears to be working.

Now create and activate a new virtualenv and install everything exactly the same only this time install mezzanine from github.
git clone https://github.com/stephenmcd/mezzanine.git
cd mezzanine
python setup.py install

Now when you try browse the pages they will work until you go to /gallery/ and you will get the following error.

The error is:
"UnicodeDecodeError: 'ascii' codec can't decode byte 0xcc in position 31: ordinal not in range(128)"

If I install the DB with caching not configured in local_settings.py I can browse to /gallery with no error.  Then when I try enable caching and browse to /gallery I get the error again.  I also tried recreating the DB in the new virtualenv with the newer version of mezzanine.  The problem still occurs.

I can reproduce all this when I use MySQL instead of SQLite as well.  Also occurs on blogposts.  My live site is using this github version of Mezzanine because my theme uses bootstrap3.  Just want to get caching working now.


--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `mezzanine/core/middleware.py`
Content:
```
1 from __future__ import unicode_literals
2 
3 from future.utils import native_str
4 
5 from django.contrib import admin
6 from django.contrib.auth import logout
7 from django.contrib.redirects.models import Redirect
8 from django.core.exceptions import MiddlewareNotUsed
9 from django.core.urlresolvers import reverse
10 from django.http import (HttpResponse, HttpResponseRedirect,
11                          HttpResponsePermanentRedirect, HttpResponseGone)
12 from django.utils.cache import get_max_age
13 from django.template import Template, RequestContext
14 from django.middleware.csrf import CsrfViewMiddleware, get_token
15 
16 from mezzanine.conf import settings
17 from mezzanine.core.models import SitePermission
18 from mezzanine.utils.cache import (cache_key_prefix, nevercache_token,
19                                    cache_get, cache_set, cache_installed)
20 from mezzanine.utils.device import templates_for_device
21 from mezzanine.utils.sites import current_site_id, templates_for_host
22 from mezzanine.utils.urls import next_url
23 
24 
25 _deprecated = {
26     "AdminLoginInterfaceSelector": "AdminLoginInterfaceSelectorMiddleware",
27     "DeviceAwareUpdateCacheMiddleware": "UpdateCacheMiddleware",
28     "DeviceAwareFetchFromCacheMiddleware": "FetchFromCacheMiddleware",
29 }
30 
31 
32 class _Deprecated(object):
33     def __init__(self, *args, **kwargs):
34         from warnings import warn
35         msg = "mezzanine.core.middleware.%s is deprecated." % self.old
36         if self.new:
37             msg += (" Please change the MIDDLEWARE_CLASSES setting to use "
38                     "mezzanine.core.middleware.%s" % self.new)
39         warn(msg)
40 
41 for old, new in _deprecated.items():
42     globals()[old] = type(native_str(old),
43                           (_Deprecated,),
44                           {"old": old, "new": new})
45 
46 
47 class AdminLoginInterfaceSelectorMiddleware(object):
48     """
49     Checks for a POST from the admin login view and if authentication is
50     successful and the "site" interface is selected, redirect to the site.
51     """
52     def process_view(self, request, view_func, view_args, view_kwargs):
53         login_type = request.POST.get("mezzanine_login_interface")
54         if login_type and not request.user.is_authenticated():
55             response = view_func(request, *view_args, **view_kwargs)
56             if request.user.is_authenticated():
57                 if login_type == "admin":
58                     next = request.get_full_path()
59                 else:
60                     next = next_url(request) or "/"
61                 return HttpResponseRedirect(next)
62             else:
63                 return response
64         return None
65 
66 
67 class SitePermissionMiddleware(object):
68     """
69     Marks the current user with a ``has_site_permission`` which is
70     used in place of ``user.is_staff`` to achieve per-site staff
71     access.
72     """
73     def process_view(self, request, view_func, view_args, view_kwargs):
74         has_site_permission = False
75         if request.user.is_superuser:
76             has_site_permission = True
77         elif request.user.is_staff:
78             lookup = {"user": request.user, "sites": current_site_id()}
79             try:
80                 SitePermission.objects.get(**lookup)
81             except SitePermission.DoesNotExist:
82                 admin_index = reverse("admin:index")
83                 if request.path.startswith(admin_index):
84                     logout(request)
85                     view_func = admin.site.login
86                     extra_context = {"no_site_permission": True}
87                     return view_func(request, extra_context=extra_context)
88             else:
89                 has_site_permission = True
90         request.user.has_site_permission = has_site_permission
91 
92 
93 class TemplateForDeviceMiddleware(object):
94     """
95     Inserts device-specific templates to the template list.
96     """
97     def process_template_response(self, request, response):
98         if hasattr(response, "template_name"):
99             if not isinstance(response.template_name, Template):
100                 templates = templates_for_device(request,
101                     response.template_name)
102                 response.template_name = templates
103         return response
104 
105 
106 class TemplateForHostMiddleware(object):
107     """
108     Inserts host-specific templates to the template list.
109     """
110     def process_template_response(self, request, response):
111         if hasattr(response, "template_name"):
112             if not isinstance(response.template_name, Template):
113                 templates = templates_for_host(request,
114                     response.template_name)
115                 response.template_name = templates
116         return response
117 
118 
119 class UpdateCacheMiddleware(object):
120     """
121     Response phase for Mezzanine's cache middleware. Handles caching
122     the response, and then performing the second phase of rendering,
123     for content enclosed by the ``nevercache`` tag.
124     """
125 
126     def process_response(self, request, response):
127 
128         # Cache the response if all the required conditions are met.
129         # Response must be marked for updating by the
130         # ``FetchFromCacheMiddleware`` having a cache get miss, the
131         # user must not be authenticated, the HTTP status must be OK
132         # and the response mustn't include an expiry age, incicating it
133         # shouldn't be cached.
134         marked_for_update = getattr(request, "_update_cache", False)
135         anon = hasattr(request, "user") and not request.user.is_authenticated()
136         valid_status = response.status_code == 200
137         timeout = get_max_age(response)
138         if timeout is None:
139             timeout = settings.CACHE_MIDDLEWARE_SECONDS
140         if anon and valid_status and marked_for_update and timeout:
141             cache_key = cache_key_prefix(request) + request.get_full_path()
142             _cache_set = lambda r: cache_set(cache_key, r.content, timeout)
143             if callable(getattr(response, "render", None)):
144                 response.add_post_render_callback(_cache_set)
145             else:
146                 _cache_set(response)
147 
148         # Second phase rendering for non-cached template code and
149         # content. Split on the delimiter the ``nevercache`` tag
150         # wrapped its contents in, and render only the content
151         # enclosed by it, to avoid possible template code injection.
152         parts = response.content.split(nevercache_token())
153         content_type = response.get("content-type", "")
154         if content_type.startswith("text") and len(parts) > 1:
155             # Restore csrf token from cookie - check the response
156             # first as it may be being set for the first time.
157             csrf_token = None
158             try:
159                 csrf_token = response.cookies[settings.CSRF_COOKIE_NAME].value
160             except KeyError:
161                 try:
162                     csrf_token = request.COOKIES[settings.CSRF_COOKIE_NAME]
163                 except KeyError:
164                     pass
165             if csrf_token:
166                 request.META["CSRF_COOKIE"] = csrf_token
167             context = RequestContext(request)
168             for i, part in enumerate(parts):
169                 if i % 2:
170                     part = Template(part).render(context).encode("utf-8")
171                 parts[i] = part
172             response.content = "".join(parts)
173             response["Content-Length"] = len(response.content)
174             if hasattr(request, '_messages'):
175                 # Required to clear out user messages.
176                 request._messages.update(response)
177         return response
178 
179 
180 class FetchFromCacheMiddleware(object):
181     """
182     Request phase for Mezzanine cache middleware. Return a response
183     from cache if found, othwerwise mark the request for updating
184     the cache in ``UpdateCacheMiddleware``.
185     """
186 
187     def process_request(self, request):
188         if (cache_installed() and request.method == "GET" and
189             not request.user.is_authenticated()):
190             cache_key = cache_key_prefix(request) + request.get_full_path()
191             response = cache_get(cache_key)
192             # We need to force a csrf token here, as new sessions
193             # won't receieve one on their first request, with cache
194             # middleware running.
195             csrf_mw_name = "django.middleware.csrf.CsrfViewMiddleware"
196             if csrf_mw_name in settings.MIDDLEWARE_CLASSES:
197                 csrf_mw = CsrfViewMiddleware()
198                 csrf_mw.process_view(request, lambda x: None, None, None)
199                 get_token(request)
200             if response is None:
201                 request._update_cache = True
202             else:
203                 return HttpResponse(response)
204 
205 
206 class SSLRedirectMiddleware(object):
207     """
208     Handles redirections required for SSL when ``SSL_ENABLED`` is ``True``.
209 
210     If ``SSL_FORCE_HOST`` is ``True``, and is not the current host,
211     redirect to it.
212 
213     Also ensure URLs defined by ``SSL_FORCE_URL_PREFIXES`` are redirect
214     to HTTPS, and redirect all other URLs to HTTP if on HTTPS.
215     """
216     def process_request(self, request):
217         settings.use_editable()
218         force_host = settings.SSL_FORCE_HOST
219         if force_host and request.get_host().split(":")[0] != force_host:
220             url = "http://%s%s" % (force_host, request.get_full_path())
221             return HttpResponsePermanentRedirect(url)
222         if settings.SSL_ENABLED and not settings.DEV_SERVER:
223             url = "%s%s" % (request.get_host(), request.get_full_path())
224             if request.path.startswith(settings.SSL_FORCE_URL_PREFIXES):
225                 if not request.is_secure():
226                     return HttpResponseRedirect("https://%s" % url)
227             elif request.is_secure() and settings.SSL_FORCED_PREFIXES_ONLY:
228                 return HttpResponseRedirect("http://%s" % url)
229 
230 
231 class RedirectFallbackMiddleware(object):
232     """
233     Port of Django's ``RedirectFallbackMiddleware`` that uses
234     Mezzanine's approach for determining the current site.
235     """
236 
237     def __init__(self):
238         if "django.contrib.redirects" not in settings.INSTALLED_APPS:
239             raise MiddlewareNotUsed
240 
241     def process_response(self, request, response):
242         if response.status_code == 404:
243             lookup = {
244                 "site_id": current_site_id(),
245                 "old_path": request.get_full_path(),
246             }
247             try:
248                 redirect = Redirect.objects.get(**lookup)
249             except Redirect.DoesNotExist:
250                 pass
251             else:
252                 if not redirect.new_path:
253                     response = HttpResponseGone()
254                 else:
255                     response = HttpResponseRedirect(redirect.new_path)
256         return response
257
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/mezzanine/core/middleware.py b/mezzanine/core/middleware.py
--- a/mezzanine/core/middleware.py
+++ b/mezzanine/core/middleware.py
@@ -149,7 +149,12 @@
         # content. Split on the delimiter the ``nevercache`` tag
         # wrapped its contents in, and render only the content
         # enclosed by it, to avoid possible template code injection.
-        parts = response.content.split(nevercache_token())
+        token = nevercache_token()
+        try:
+            token = token.encode('utf-8')
+        except AttributeError:
+            pass
+        parts = response.content.split(token)
         content_type = response.get("content-type", "")
         if content_type.startswith("text") and len(parts) > 1:
             # Restore csrf token from cookie - check the response
@@ -169,7 +174,7 @@
                 if i % 2:
                     part = Template(part).render(context).encode("utf-8")
                 parts[i] = part
-            response.content = "".join(parts)
+            response.content = b"".join(parts)
             response["Content-Length"] = len(response.content)
             if hasattr(request, '_messages'):
                 # Required to clear out user messages.

{"golden_diff": "diff --git a/mezzanine/core/middleware.py b/mezzanine/core/middleware.py\n--- a/mezzanine/core/middleware.py\n+++ b/mezzanine/core/middleware.py\n@@ -149,7 +149,12 @@\n         # content. Split on the delimiter the ``nevercache`` tag\n         # wrapped its contents in, and render only the content\n         # enclosed by it, to avoid possible template code injection.\n-        parts = response.content.split(nevercache_token())\n+        token = nevercache_token()\n+        try:\n+            token = token.encode('utf-8')\n+        except AttributeError:\n+            pass\n+        parts = response.content.split(token)\n         content_type = response.get(\"content-type\", \"\")\n         if content_type.startswith(\"text\") and len(parts) > 1:\n             # Restore csrf token from cookie - check the response\n@@ -169,7 +174,7 @@\n                 if i % 2:\n                     part = Template(part).render(context).encode(\"utf-8\")\n                 parts[i] = part\n-            response.content = \"\".join(parts)\n+            response.content = b\"\".join(parts)\n             response[\"Content-Length\"] = len(response.content)\n             if hasattr(request, '_messages'):\n                 # Required to clear out user messages.\n", "issue": "UnicodeDecodeError ('ascii' codec can't decode) when memcached enabled\nI can reproduce this on Ubuntu 12 and CentOS 6.   \n\nmemcached installed and enabled.  \n\nInstall new virtualenv and activate\n~/venv/workingvirtualenv\nsource ~/venv/workingvirtulaenv/bin/activate\n\npip install mezzanine\npip install python-memcached\nmezzanine-project testproject\n\nadd the live_settings.py cache settings to local_settings.py\n\nNow create the DB\npython manage.py createdb\n\nSelect all defaults and answer yes to questions including creating demo data..\nCan browse demo pages including /gallery with no errors and caching appears to be working.\n\nNow create and activate a new virtualenv and install everything exactly the same only this time install mezzanine from github.\ngit clone https://github.com/stephenmcd/mezzanine.git\ncd mezzanine\npython setup.py install\n\nNow when you try browse the pages they will work until you go to /gallery/ and you will get the following error.\n\nThe error is:\n\"UnicodeDecodeError: 'ascii' codec can't decode byte 0xcc in position 31: ordinal not in range(128)\"\n\nIf I install the DB with caching not configured in local_settings.py I can browse to /gallery with no error.  Then when I try enable caching and browse to /gallery I get the error again.  I also tried recreating the DB in the new virtualenv with the newer version of mezzanine.  The problem still occurs.\n\nI can reproduce all this when I use MySQL instead of SQLite as well.  Also occurs on blogposts.  My live site is using this github version of Mezzanine because my theme uses bootstrap3.  Just want to get caching working now.\n\n", "before_files": [{"content": "from __future__ import unicode_literals\n\nfrom future.utils import native_str\n\nfrom django.contrib import admin\nfrom django.contrib.auth import logout\nfrom django.contrib.redirects.models import Redirect\nfrom django.core.exceptions import MiddlewareNotUsed\nfrom django.core.urlresolvers import reverse\nfrom django.http import (HttpResponse, HttpResponseRedirect,\n                         HttpResponsePermanentRedirect, HttpResponseGone)\nfrom django.utils.cache import get_max_age\nfrom django.template import Template, RequestContext\nfrom django.middleware.csrf import CsrfViewMiddleware, get_token\n\nfrom mezzanine.conf import settings\nfrom mezzanine.core.models import SitePermission\nfrom mezzanine.utils.cache import (cache_key_prefix, nevercache_token,\n                                   cache_get, cache_set, cache_installed)\nfrom mezzanine.utils.device import templates_for_device\nfrom mezzanine.utils.sites import current_site_id, templates_for_host\nfrom mezzanine.utils.urls import next_url\n\n\n_deprecated = {\n    \"AdminLoginInterfaceSelector\": \"AdminLoginInterfaceSelectorMiddleware\",\n    \"DeviceAwareUpdateCacheMiddleware\": \"UpdateCacheMiddleware\",\n    \"DeviceAwareFetchFromCacheMiddleware\": \"FetchFromCacheMiddleware\",\n}\n\n\nclass _Deprecated(object):\n    def __init__(self, *args, **kwargs):\n        from warnings import warn\n        msg = \"mezzanine.core.middleware.%s is deprecated.\" % self.old\n        if self.new:\n            msg += (\" Please change the MIDDLEWARE_CLASSES setting to use \"\n                    \"mezzanine.core.middleware.%s\" % self.new)\n        warn(msg)\n\nfor old, new in _deprecated.items():\n    globals()[old] = type(native_str(old),\n                          (_Deprecated,),\n                          {\"old\": old, \"new\": new})\n\n\nclass AdminLoginInterfaceSelectorMiddleware(object):\n    \"\"\"\n    Checks for a POST from the admin login view and if authentication is\n    successful and the \"site\" interface is selected, redirect to the site.\n    \"\"\"\n    def process_view(self, request, view_func, view_args, view_kwargs):\n        login_type = request.POST.get(\"mezzanine_login_interface\")\n        if login_type and not request.user.is_authenticated():\n            response = view_func(request, *view_args, **view_kwargs)\n            if request.user.is_authenticated():\n                if login_type == \"admin\":\n                    next = request.get_full_path()\n                else:\n                    next = next_url(request) or \"/\"\n                return HttpResponseRedirect(next)\n            else:\n                return response\n        return None\n\n\nclass SitePermissionMiddleware(object):\n    \"\"\"\n    Marks the current user with a ``has_site_permission`` which is\n    used in place of ``user.is_staff`` to achieve per-site staff\n    access.\n    \"\"\"\n    def process_view(self, request, view_func, view_args, view_kwargs):\n        has_site_permission = False\n        if request.user.is_superuser:\n            has_site_permission = True\n        elif request.user.is_staff:\n            lookup = {\"user\": request.user, \"sites\": current_site_id()}\n            try:\n                SitePermission.objects.get(**lookup)\n            except SitePermission.DoesNotExist:\n                admin_index = reverse(\"admin:index\")\n                if request.path.startswith(admin_index):\n                    logout(request)\n                    view_func = admin.site.login\n                    extra_context = {\"no_site_permission\": True}\n                    return view_func(request, extra_context=extra_context)\n            else:\n                has_site_permission = True\n        request.user.has_site_permission = has_site_permission\n\n\nclass TemplateForDeviceMiddleware(object):\n    \"\"\"\n    Inserts device-specific templates to the template list.\n    \"\"\"\n    def process_template_response(self, request, response):\n        if hasattr(response, \"template_name\"):\n            if not isinstance(response.template_name, Template):\n                templates = templates_for_device(request,\n                    response.template_name)\n                response.template_name = templates\n        return response\n\n\nclass TemplateForHostMiddleware(object):\n    \"\"\"\n    Inserts host-specific templates to the template list.\n    \"\"\"\n    def process_template_response(self, request, response):\n        if hasattr(response, \"template_name\"):\n            if not isinstance(response.template_name, Template):\n                templates = templates_for_host(request,\n                    response.template_name)\n                response.template_name = templates\n        return response\n\n\nclass UpdateCacheMiddleware(object):\n    \"\"\"\n    Response phase for Mezzanine's cache middleware. Handles caching\n    the response, and then performing the second phase of rendering,\n    for content enclosed by the ``nevercache`` tag.\n    \"\"\"\n\n    def process_response(self, request, response):\n\n        # Cache the response if all the required conditions are met.\n        # Response must be marked for updating by the\n        # ``FetchFromCacheMiddleware`` having a cache get miss, the\n        # user must not be authenticated, the HTTP status must be OK\n        # and the response mustn't include an expiry age, incicating it\n        # shouldn't be cached.\n        marked_for_update = getattr(request, \"_update_cache\", False)\n        anon = hasattr(request, \"user\") and not request.user.is_authenticated()\n        valid_status = response.status_code == 200\n        timeout = get_max_age(response)\n        if timeout is None:\n            timeout = settings.CACHE_MIDDLEWARE_SECONDS\n        if anon and valid_status and marked_for_update and timeout:\n            cache_key = cache_key_prefix(request) + request.get_full_path()\n            _cache_set = lambda r: cache_set(cache_key, r.content, timeout)\n            if callable(getattr(response, \"render\", None)):\n                response.add_post_render_callback(_cache_set)\n            else:\n                _cache_set(response)\n\n        # Second phase rendering for non-cached template code and\n        # content. Split on the delimiter the ``nevercache`` tag\n        # wrapped its contents in, and render only the content\n        # enclosed by it, to avoid possible template code injection.\n        parts = response.content.split(nevercache_token())\n        content_type = response.get(\"content-type\", \"\")\n        if content_type.startswith(\"text\") and len(parts) > 1:\n            # Restore csrf token from cookie - check the response\n            # first as it may be being set for the first time.\n            csrf_token = None\n            try:\n                csrf_token = response.cookies[settings.CSRF_COOKIE_NAME].value\n            except KeyError:\n                try:\n                    csrf_token = request.COOKIES[settings.CSRF_COOKIE_NAME]\n                except KeyError:\n                    pass\n            if csrf_token:\n                request.META[\"CSRF_COOKIE\"] = csrf_token\n            context = RequestContext(request)\n            for i, part in enumerate(parts):\n                if i % 2:\n                    part = Template(part).render(context).encode(\"utf-8\")\n                parts[i] = part\n            response.content = \"\".join(parts)\n            response[\"Content-Length\"] = len(response.content)\n            if hasattr(request, '_messages'):\n                # Required to clear out user messages.\n                request._messages.update(response)\n        return response\n\n\nclass FetchFromCacheMiddleware(object):\n    \"\"\"\n    Request phase for Mezzanine cache middleware. Return a response\n    from cache if found, othwerwise mark the request for updating\n    the cache in ``UpdateCacheMiddleware``.\n    \"\"\"\n\n    def process_request(self, request):\n        if (cache_installed() and request.method == \"GET\" and\n            not request.user.is_authenticated()):\n            cache_key = cache_key_prefix(request) + request.get_full_path()\n            response = cache_get(cache_key)\n            # We need to force a csrf token here, as new sessions\n            # won't receieve one on their first request, with cache\n            # middleware running.\n            csrf_mw_name = \"django.middleware.csrf.CsrfViewMiddleware\"\n            if csrf_mw_name in settings.MIDDLEWARE_CLASSES:\n                csrf_mw = CsrfViewMiddleware()\n                csrf_mw.process_view(request, lambda x: None, None, None)\n                get_token(request)\n            if response is None:\n                request._update_cache = True\n            else:\n                return HttpResponse(response)\n\n\nclass SSLRedirectMiddleware(object):\n    \"\"\"\n    Handles redirections required for SSL when ``SSL_ENABLED`` is ``True``.\n\n    If ``SSL_FORCE_HOST`` is ``True``, and is not the current host,\n    redirect to it.\n\n    Also ensure URLs defined by ``SSL_FORCE_URL_PREFIXES`` are redirect\n    to HTTPS, and redirect all other URLs to HTTP if on HTTPS.\n    \"\"\"\n    def process_request(self, request):\n        settings.use_editable()\n        force_host = settings.SSL_FORCE_HOST\n        if force_host and request.get_host().split(\":\")[0] != force_host:\n            url = \"http://%s%s\" % (force_host, request.get_full_path())\n            return HttpResponsePermanentRedirect(url)\n        if settings.SSL_ENABLED and not settings.DEV_SERVER:\n            url = \"%s%s\" % (request.get_host(), request.get_full_path())\n            if request.path.startswith(settings.SSL_FORCE_URL_PREFIXES):\n                if not request.is_secure():\n                    return HttpResponseRedirect(\"https://%s\" % url)\n            elif request.is_secure() and settings.SSL_FORCED_PREFIXES_ONLY:\n                return HttpResponseRedirect(\"http://%s\" % url)\n\n\nclass RedirectFallbackMiddleware(object):\n    \"\"\"\n    Port of Django's ``RedirectFallbackMiddleware`` that uses\n    Mezzanine's approach for determining the current site.\n    \"\"\"\n\n    def __init__(self):\n        if \"django.contrib.redirects\" not in settings.INSTALLED_APPS:\n            raise MiddlewareNotUsed\n\n    def process_response(self, request, response):\n        if response.status_code == 404:\n            lookup = {\n                \"site_id\": current_site_id(),\n                \"old_path\": request.get_full_path(),\n            }\n            try:\n                redirect = Redirect.objects.get(**lookup)\n            except Redirect.DoesNotExist:\n                pass\n            else:\n                if not redirect.new_path:\n                    response = HttpResponseGone()\n                else:\n                    response = HttpResponseRedirect(redirect.new_path)\n        return response\n", "path": "mezzanine/core/middleware.py"}], "after_files": [{"content": "from __future__ import unicode_literals\n\nfrom future.utils import native_str\n\nfrom django.contrib import admin\nfrom django.contrib.auth import logout\nfrom django.contrib.redirects.models import Redirect\nfrom django.core.exceptions import MiddlewareNotUsed\nfrom django.core.urlresolvers import reverse\nfrom django.http import (HttpResponse, HttpResponseRedirect,\n                         HttpResponsePermanentRedirect, HttpResponseGone)\nfrom django.utils.cache import get_max_age\nfrom django.template import Template, RequestContext\nfrom django.middleware.csrf import CsrfViewMiddleware, get_token\n\nfrom mezzanine.conf import settings\nfrom mezzanine.core.models import SitePermission\nfrom mezzanine.utils.cache import (cache_key_prefix, nevercache_token,\n                                   cache_get, cache_set, cache_installed)\nfrom mezzanine.utils.device import templates_for_device\nfrom mezzanine.utils.sites import current_site_id, templates_for_host\nfrom mezzanine.utils.urls import next_url\n\n\n_deprecated = {\n    \"AdminLoginInterfaceSelector\": \"AdminLoginInterfaceSelectorMiddleware\",\n    \"DeviceAwareUpdateCacheMiddleware\": \"UpdateCacheMiddleware\",\n    \"DeviceAwareFetchFromCacheMiddleware\": \"FetchFromCacheMiddleware\",\n}\n\n\nclass _Deprecated(object):\n    def __init__(self, *args, **kwargs):\n        from warnings import warn\n        msg = \"mezzanine.core.middleware.%s is deprecated.\" % self.old\n        if self.new:\n            msg += (\" Please change the MIDDLEWARE_CLASSES setting to use \"\n                    \"mezzanine.core.middleware.%s\" % self.new)\n        warn(msg)\n\nfor old, new in _deprecated.items():\n    globals()[old] = type(native_str(old),\n                          (_Deprecated,),\n                          {\"old\": old, \"new\": new})\n\n\nclass AdminLoginInterfaceSelectorMiddleware(object):\n    \"\"\"\n    Checks for a POST from the admin login view and if authentication is\n    successful and the \"site\" interface is selected, redirect to the site.\n    \"\"\"\n    def process_view(self, request, view_func, view_args, view_kwargs):\n        login_type = request.POST.get(\"mezzanine_login_interface\")\n        if login_type and not request.user.is_authenticated():\n            response = view_func(request, *view_args, **view_kwargs)\n            if request.user.is_authenticated():\n                if login_type == \"admin\":\n                    next = request.get_full_path()\n                else:\n                    next = next_url(request) or \"/\"\n                return HttpResponseRedirect(next)\n            else:\n                return response\n        return None\n\n\nclass SitePermissionMiddleware(object):\n    \"\"\"\n    Marks the current user with a ``has_site_permission`` which is\n    used in place of ``user.is_staff`` to achieve per-site staff\n    access.\n    \"\"\"\n    def process_view(self, request, view_func, view_args, view_kwargs):\n        has_site_permission = False\n        if request.user.is_superuser:\n            has_site_permission = True\n        elif request.user.is_staff:\n            lookup = {\"user\": request.user, \"sites\": current_site_id()}\n            try:\n                SitePermission.objects.get(**lookup)\n            except SitePermission.DoesNotExist:\n                admin_index = reverse(\"admin:index\")\n                if request.path.startswith(admin_index):\n                    logout(request)\n                    view_func = admin.site.login\n                    extra_context = {\"no_site_permission\": True}\n                    return view_func(request, extra_context=extra_context)\n            else:\n                has_site_permission = True\n        request.user.has_site_permission = has_site_permission\n\n\nclass TemplateForDeviceMiddleware(object):\n    \"\"\"\n    Inserts device-specific templates to the template list.\n    \"\"\"\n    def process_template_response(self, request, response):\n        if hasattr(response, \"template_name\"):\n            if not isinstance(response.template_name, Template):\n                templates = templates_for_device(request,\n                    response.template_name)\n                response.template_name = templates\n        return response\n\n\nclass TemplateForHostMiddleware(object):\n    \"\"\"\n    Inserts host-specific templates to the template list.\n    \"\"\"\n    def process_template_response(self, request, response):\n        if hasattr(response, \"template_name\"):\n            if not isinstance(response.template_name, Template):\n                templates = templates_for_host(request,\n                    response.template_name)\n                response.template_name = templates\n        return response\n\n\nclass UpdateCacheMiddleware(object):\n    \"\"\"\n    Response phase for Mezzanine's cache middleware. Handles caching\n    the response, and then performing the second phase of rendering,\n    for content enclosed by the ``nevercache`` tag.\n    \"\"\"\n\n    def process_response(self, request, response):\n\n        # Cache the response if all the required conditions are met.\n        # Response must be marked for updating by the\n        # ``FetchFromCacheMiddleware`` having a cache get miss, the\n        # user must not be authenticated, the HTTP status must be OK\n        # and the response mustn't include an expiry age, incicating it\n        # shouldn't be cached.\n        marked_for_update = getattr(request, \"_update_cache\", False)\n        anon = hasattr(request, \"user\") and not request.user.is_authenticated()\n        valid_status = response.status_code == 200\n        timeout = get_max_age(response)\n        if timeout is None:\n            timeout = settings.CACHE_MIDDLEWARE_SECONDS\n        if anon and valid_status and marked_for_update and timeout:\n            cache_key = cache_key_prefix(request) + request.get_full_path()\n            _cache_set = lambda r: cache_set(cache_key, r.content, timeout)\n            if callable(getattr(response, \"render\", None)):\n                response.add_post_render_callback(_cache_set)\n            else:\n                _cache_set(response)\n\n        # Second phase rendering for non-cached template code and\n        # content. Split on the delimiter the ``nevercache`` tag\n        # wrapped its contents in, and render only the content\n        # enclosed by it, to avoid possible template code injection.\n        token = nevercache_token()\n        try:\n            token = token.encode('utf-8')\n        except AttributeError:\n            pass\n        parts = response.content.split(token)\n        content_type = response.get(\"content-type\", \"\")\n        if content_type.startswith(\"text\") and len(parts) > 1:\n            # Restore csrf token from cookie - check the response\n            # first as it may be being set for the first time.\n            csrf_token = None\n            try:\n                csrf_token = response.cookies[settings.CSRF_COOKIE_NAME].value\n            except KeyError:\n                try:\n                    csrf_token = request.COOKIES[settings.CSRF_COOKIE_NAME]\n                except KeyError:\n                    pass\n            if csrf_token:\n                request.META[\"CSRF_COOKIE\"] = csrf_token\n            context = RequestContext(request)\n            for i, part in enumerate(parts):\n                if i % 2:\n                    part = Template(part).render(context).encode(\"utf-8\")\n                parts[i] = part\n            response.content = b\"\".join(parts)\n            response[\"Content-Length\"] = len(response.content)\n            if hasattr(request, '_messages'):\n                # Required to clear out user messages.\n                request._messages.update(response)\n        return response\n\n\nclass FetchFromCacheMiddleware(object):\n    \"\"\"\n    Request phase for Mezzanine cache middleware. Return a response\n    from cache if found, othwerwise mark the request for updating\n    the cache in ``UpdateCacheMiddleware``.\n    \"\"\"\n\n    def process_request(self, request):\n        if (cache_installed() and request.method == \"GET\" and\n            not request.user.is_authenticated()):\n            cache_key = cache_key_prefix(request) + request.get_full_path()\n            response = cache_get(cache_key)\n            # We need to force a csrf token here, as new sessions\n            # won't receieve one on their first request, with cache\n            # middleware running.\n            csrf_mw_name = \"django.middleware.csrf.CsrfViewMiddleware\"\n            if csrf_mw_name in settings.MIDDLEWARE_CLASSES:\n                csrf_mw = CsrfViewMiddleware()\n                csrf_mw.process_view(request, lambda x: None, None, None)\n                get_token(request)\n            if response is None:\n                request._update_cache = True\n            else:\n                return HttpResponse(response)\n\n\nclass SSLRedirectMiddleware(object):\n    \"\"\"\n    Handles redirections required for SSL when ``SSL_ENABLED`` is ``True``.\n\n    If ``SSL_FORCE_HOST`` is ``True``, and is not the current host,\n    redirect to it.\n\n    Also ensure URLs defined by ``SSL_FORCE_URL_PREFIXES`` are redirect\n    to HTTPS, and redirect all other URLs to HTTP if on HTTPS.\n    \"\"\"\n    def process_request(self, request):\n        settings.use_editable()\n        force_host = settings.SSL_FORCE_HOST\n        if force_host and request.get_host().split(\":\")[0] != force_host:\n            url = \"http://%s%s\" % (force_host, request.get_full_path())\n            return HttpResponsePermanentRedirect(url)\n        if settings.SSL_ENABLED and not settings.DEV_SERVER:\n            url = \"%s%s\" % (request.get_host(), request.get_full_path())\n            if request.path.startswith(settings.SSL_FORCE_URL_PREFIXES):\n                if not request.is_secure():\n                    return HttpResponseRedirect(\"https://%s\" % url)\n            elif request.is_secure() and settings.SSL_FORCED_PREFIXES_ONLY:\n                return HttpResponseRedirect(\"http://%s\" % url)\n\n\nclass RedirectFallbackMiddleware(object):\n    \"\"\"\n    Port of Django's ``RedirectFallbackMiddleware`` that uses\n    Mezzanine's approach for determining the current site.\n    \"\"\"\n\n    def __init__(self):\n        if \"django.contrib.redirects\" not in settings.INSTALLED_APPS:\n            raise MiddlewareNotUsed\n\n    def process_response(self, request, response):\n        if response.status_code == 404:\n            lookup = {\n                \"site_id\": current_site_id(),\n                \"old_path\": request.get_full_path(),\n            }\n            try:\n                redirect = Redirect.objects.get(**lookup)\n            except Redirect.DoesNotExist:\n                pass\n            else:\n                if not redirect.new_path:\n                    response = HttpResponseGone()\n                else:\n                    response = HttpResponseRedirect(redirect.new_path)\n        return response\n", "path": "mezzanine/core/middleware.py"}]}