Code

Opened 8 years ago

Closed 8 years ago

Last modified 4 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 Triage Stage: Unreviewed
Has patch: yes Needs documentation: no
Needs tests: no Patch needs improvement: no
Easy pickings: UI/UX:

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'):

Attachments (0)

Change History (5)

comment:1 Changed 8 years ago by hugo

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 Changed 8 years ago by Sune Kirkeby <sune.kirkeby@…>

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 Changed 8 years ago by hugo

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 Changed 8 years ago by adrian

  • Resolution set to fixed
  • Status changed from new to closed

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

comment:5 Changed 4 years ago by forest

  • Cc forest added

Add Comment

Modify Ticket

Change Properties
<Author field>
Action
as closed
as The resolution will be set. Next status will be 'closed'
The resolution will be deleted. Next status will be 'new'
Author


E-mail address and user name can be saved in the Preferences.

 
Note: See TracTickets for help on using tickets.