I am working on a project which uses ThreadedComments in a couple of apps 
(Mezzanine Blog and a discussion forum). All was working fine in the 
development and production environment but from one day to the next posting 
a comment raised an Internal Server Error (500).

My setup: Mezzanine 4.01, Django 1.8.5, Python 2.7.6. The production 
environment is a Ubuntu 14.04 server, Apache webserver. Mezzanine is 
deployed using mod_wsgi-express. Mezzanine is set up using "German" as 
language.

The error log created by the server gives me the following:

Traceback (most recent call last):
[Thu Dec 17 21:08:23.317452 2015] [wsgi:error] [pid 30806:tid 
140269963933440] [remote 95.90.251.8:24357]   File 
"/home/chris/IT/Portal/veportal/local/lib/python2.7/site-packages/mod_wsgi-4.4.15-py2.7-linux-x86_64.egg/mod_wsgi/server/__init__.py"
, line 1346, in handle_request
[Thu Dec 17 21:08:23.317902 2015] [wsgi:error] [pid 30806:tid 
140269963933440] [remote 95.90.251.8:24357]     return self.application(
environ, start_response)
[Thu Dec 17 21:08:23.317919 2015] [wsgi:error] [pid 30806:tid 
140269963933440] [remote 95.90.251.8:24357]   File 
"/home/chris/IT/Portal/veportal/local/lib/python2.7/site-packages/django/core/handlers/wsgi.py"
, line 195, in __call__
[Thu Dec 17 21:08:23.317982 2015] [wsgi:error] [pid 30806:tid 
140269963933440] [remote 95.90.251.8:24357]     response_headers.append((str
('Set-Cookie'), str(c.output(header=''))))
[Thu Dec 17 21:08:23.317993 2015] [wsgi:error] [pid 30806:tid 
140269963933440] [remote 95.90.251.8:24357]   File 
"/usr/lib/python2.7/Cookie.py", line 466, in output
[Thu Dec 17 21:08:23.318106 2015] [wsgi:error] [pid 30806:tid 
140269963933440] [remote 95.90.251.8:24357]     return "%s %s" % ( header, 
self.OutputString(attrs) )
[Thu Dec 17 21:08:23.318116 2015] [wsgi:error] [pid 30806:tid 
140269963933440] [remote 95.90.251.8:24357]   File 
"/usr/lib/python2.7/Cookie.py", line 514, in OutputString
[Thu Dec 17 21:08:23.318128 2015] [wsgi:error] [pid 30806:tid 
140269963933440] [remote 95.90.251.8:24357]     return _semispacejoin(result
)
[Thu Dec 17 21:08:23.318143 2015] [wsgi:error] [pid 30806:tid 
140269963933440] [remote 95.90.251.8:24357] UnicodeDecodeError: 'ascii' 
codec can't decode byte 0xc3 in position 16: ordinal not in range(128)

After some digging I found that this error was caused by the "set_cookie" 
method in mezzanine.utils.views. When creating the "expires" date the 
locale de_DE, utf-8 is used by strftime and the month of March in German 
contains a non ASCII character (i.e. "Umlaut"). Therefore the error only 
pops up if a cookie with expiry "March" is set.

For testing purposes I tried running my project using the Django 
development server in the production environment - strangely enough I did 
NOT get the error there.

As a quick fix I temporarily set the locale back to en_US, utf-8 before 
setting the cookie using this 
<http://stackoverflow.com/questions/18593661/how-do-i-strftime-a-date-object-in-a-different-locale>
 
approach; i.e. mezzanine.utils.views like so:

# This is a hack to avoid unicode decode errors caused on the production 
server
# by a german expiry date

import locale
import threading

from contextlib import contextmanager


LOCALE_LOCK = threading.Lock()

@contextmanager
def setlocale(name):
    with LOCALE_LOCK:
        saved = locale.setlocale(locale.LC_ALL)
        try:
            yield locale.setlocale(locale.LC_ALL, name)
        finally:
            locale.setlocale(locale.LC_ALL, saved)


# End of hack


def set_cookie(response, name, value, expiry_seconds=None, secure=False):
    """
    Set cookie wrapper that allows number of seconds to be given as the
    expiry time, and ensures values are correctly encoded.
    """
    if expiry_seconds is None:
        expiry_seconds = 90 * 24 * 60 * 60  # Default to 90 days.
    # Set back locale to avoid UnicodeDecodeError
    with setlocale(('en', 'utf-8')):
        expires = datetime.strftime(datetime.utcnow() +
                                timedelta(seconds=expiry_seconds),
                                "%a, %d-%b-%Y %H:%M:%S GMT")
    # Django doesn't seem to support unicode cookie keys correctly on
    # Python 2. Work around by encoding it. See
    # https://code.djangoproject.com/ticket/19802
    try:
        response.set_cookie(name, value, expires=expires, secure=secure)
    except (KeyError, TypeError):
        response.set_cookie(name.encode('utf-8'), value, expires=expires,
                            secure=secure)

Although things seem to be working now I do not think fiddling with core 
code  is a good idea. I am not even sure whether this is really a Mezzanine 
issue or whether it has something todo with Apache, mod_wsgi or an issue 
with the setup of the production server as such.

Any thoughts welcome.

Regards

Chris




-- 
You received this message because you are subscribed to the Google Groups 
"Mezzanine Users" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to mezzanine-users+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to