[Checkins] SVN: zope.publisher/trunk/src/zope/publisher/ Fix for https://bugs.launchpad.net/zope3/+bug/98337

Albertas Agejevas alga at pov.lt
Fri Jul 3 12:02:00 EDT 2009


Log message for revision 101467:
  Fix for https://bugs.launchpad.net/zope3/+bug/98337
  
  Previously, when the Accept-Charset specified a charset that could not encode
  the result, a system error appeared, now we fall back to UTF-8, as per
  RFC 2616 section 10.4.7.
  

Changed:
  U   zope.publisher/trunk/src/zope/publisher/http.py
  U   zope.publisher/trunk/src/zope/publisher/tests/test_http.py

-=-
Modified: zope.publisher/trunk/src/zope/publisher/http.py
===================================================================
--- zope.publisher/trunk/src/zope/publisher/http.py	2009-07-03 16:00:51 UTC (rev 101466)
+++ zope.publisher/trunk/src/zope/publisher/http.py	2009-07-03 16:02:00 UTC (rev 101467)
@@ -814,11 +814,20 @@
 
             if 'charset' in params:
                 encoding = params['charset']
-            else:
-                content_type += ';charset=%s' %encoding
 
-            body = body.encode(encoding)
+            try:
+                body = body.encode(encoding)
+            except UnicodeEncodeError:
+                # RFC 2616 section 10.4.7 allows us to return an
+                # unacceptable encoding instead of 406 Not Acceptable
+                # response.
+                encoding = 'utf-8'
+                body = body.encode(encoding)
 
+            params['charset'] = encoding
+            content_type = "%s/%s;" % (major, minor)
+            content_type += ";".join(k + "=" + v for k, v in params.items())
+
         if content_type:
             headers = [('content-type', content_type),
                        ('content-length', str(len(body)))]
@@ -827,7 +836,6 @@
 
         return body, headers
 
-
     def handleException(self, exc_info):
         """
         Calls self.setBody() with an error response.

Modified: zope.publisher/trunk/src/zope/publisher/tests/test_http.py
===================================================================
--- zope.publisher/trunk/src/zope/publisher/tests/test_http.py	2009-07-03 16:00:51 UTC (rev 101466)
+++ zope.publisher/trunk/src/zope/publisher/tests/test_http.py	2009-07-03 16:02:00 UTC (rev 101467)
@@ -24,6 +24,7 @@
 
 import zope.event
 import zope.testing.cleanup
+from zope.component import provideAdapter
 from zope.testing import doctest
 from zope.i18n.interfaces.locales import ILocale
 from zope.interface.verify import verifyObject
@@ -31,7 +32,7 @@
 from zope.interface import implements
 from zope.publisher.interfaces.logginginfo import ILoggingInfo
 from zope.publisher.http import HTTPRequest, HTTPResponse
-from zope.publisher.http import HTTPInputStream, DirectResult
+from zope.publisher.http import HTTPInputStream, DirectResult, HTTPCharsets
 from zope.publisher.publish import publish
 from zope.publisher.base import DefaultPublication
 from zope.publisher.interfaces import NotFound
@@ -321,7 +322,6 @@
         eq = self.assertEqual
         unless = self.failUnless
 
-        from zope.component import provideAdapter
         from zope.publisher.browser import BrowserLanguages
         from zope.publisher.interfaces.http import IHTTPRequest
         from zope.i18n.interfaces import IUserPreferredLanguages
@@ -590,7 +590,24 @@
         request = self._createRequest({'PATH_INFO': '/test '})
         self.assertEqual(['test '], request.getTraversalStack())
 
+    def test_unacceptable_charset(self):
+        # Regression test for https://bugs.launchpad.net/zope3/+bug/98337
+        request = self._createRequest({'HTTP_ACCEPT_CHARSET': 'ISO-8859-1'})
+        result = u"Latin a with ogonek\u0105 Cyrillic ya \u044f"
+        provideAdapter(HTTPCharsets)
+        request.response.setHeader('Content-Type', 'text/plain')
 
+        # Instead of failing with HTTP code 406 we ignore the
+        # Accept-Charset header and return a response in UTF-8.
+        request.response.setResult(result)
+
+        body = request.response.consumeBody()
+        self.assertEquals(request.response.getStatus(), 200)
+        self.assertEquals(request.response.getHeader('Content-Type'),
+                          'text/plain;charset=utf-8')
+        self.assertEquals(body,
+                          'Latin a with ogonek\xc4\x85 Cyrillic ya \xd1\x8f')
+
 class ConcreteHTTPTests(HTTPTests):
     """Tests that we don't have to worry about subclasses inheriting and
     breaking.



More information about the Checkins mailing list