Opened 18 years ago

Closed 18 years ago

Last modified 14 years ago

#920 closed defect (fixed)

[patch] patch_response_headers breaks when response.content is unicode

Reported by: Sune Kirkeby <sune.kirkeby@…> Owned by: Jacob
Component: Core (Cache system) Version:
Severity: normal Keywords:
Cc: Forest Bond Triage Stage: Unreviewed
Has patch: yes Needs documentation: no
Needs tests: no Patch needs improvement: no
Easy pickings: no UI/UX: no

Description

It's because hexdigest is not unicode-safe, so when a non-ascii unicode response.content is encoded with the default ascii encoding things break. A fix:

--- django/utils/cache.py       (revision 3523)
+++ django/utils/cache.py       (local)
@@ -75,7 +75,7 @@
     now = datetime.datetime.utcnow()
     expires = now + datetime.timedelta(0, cache_timeout)
     if not response.has_header('ETag'):
-        response['ETag'] = md5.new(response.content).hexdigest()
+        response['ETag'] = md5.new(response.content.encode('utf8')).hexdigest()
     if not response.has_header('Last-Modified'):
         response['Last-Modified'] = now.strftime('%a, %d %b %Y %H:%M:%S GMT')
     if not response.has_header('Expires'):

Change History (5)

comment:1 by hugo, 18 years ago

Uhm - your patch will break if content is _not_ unicode :-)

Best to put an "if type(response.content) is unicode" switch in there.

comment:2 by Sune Kirkeby <sune.kirkeby@…>, 18 years ago

Ooops.. I tried ' '.encode which works just fine, and assumed that str.encode was an identity-mapping :( Here's a more appropriate patch:

--- cache.py    (/mirror/django/trunk/django/utils/cache.py)    (revision 3596)
+++ cache.py    (/mirror/private/django/django/utils/cache.py)  (local)
@@ -75,7 +75,10 @@
     now = datetime.datetime.utcnow()
     expires = now + datetime.timedelta(0, cache_timeout)
     if not response.has_header('ETag'):
-        response['ETag'] = md5.new(response.content).hexdigest()
+        if isinstance(response.content, unicode):
+            response['ETag'] = md5.new(response.content.encode('utf8')).hexdigest()
+        else:
+            response['ETag'] = md5.new(response.content).hexdigest()
     if not response.has_header('Last-Modified'):
         response['Last-Modified'] = now.strftime('%a, %d %b %Y %H:%M:%S GMT')
     if not response.has_header('Expires'):

comment:3 by hugo, 18 years ago

yeah, 'xxxx'.encode('utf-8') works for xxxxx that itself doesn't use 8bit chars in the non-unicode string. As soon as there is some 8bit stuff in there, it will break. It's only logical: the system can't know for bytestrings what charset they are in, except if it is the default encoding (ascii).

comment:4 by Adrian Holovaty, 18 years ago

Resolution: fixed
Status: newclosed

(In [1980]) Fixed #920 -- Fixed patch_response_headers() behavior when content is Unicode. Thanks, Sune Kirkeby

comment:5 by Forest Bond, 14 years ago

Cc: Forest Bond added
Note: See TracTickets for help on using tickets.
Back to Top