[PATCH 1 of 2 rqlcontroller] [py3] Decode content of multipart requests before JSON loading

Denis Laxalde denis.laxalde at logilab.fr
Mon Jun 11 14:09:18 CEST 2018


# HG changeset patch
# User Denis Laxalde <denis.laxalde at logilab.fr>
# Date 1528718631 -7200
#      Mon Jun 11 14:03:51 2018 +0200
# Node ID 15247c11de9dd43273b5615141f589a5b8836b0b
# Parent  2b159b2651c9900f76309b4462e6d2321d8babd8
# Available At http://hg.logilab.org/review/cubes/rqlcontroller
#              hg pull http://hg.logilab.org/review/cubes/rqlcontroller -r 15247c11de9d
# EXP-Topic py3
[py3] Decode content of multipart requests before JSON loading

This is the same logic as in 59eab509372e which handled the
non-multipart case. Since this multipart requests mode had no test
coverage, we add a test for it. Notice that this is the mode used by
cwclientlib's rqlio().

diff --git a/test/unittest_rqlcontroller.py b/test/unittest_rqlcontroller.py
--- a/test/unittest_rqlcontroller.py
+++ b/test/unittest_rqlcontroller.py
@@ -87,6 +87,27 @@ class RqlIOTC(CubicWebWsgiTC):
         self.assertEqual(2, len(output[2]))
         self.assertEqual([output[0][0], output[1][0]], output[2])
 
+    def test_queries_multipart(self):
+        queries = [
+            ('INSERT CWUser U: U login %(l)s, U upassword %(p)s',
+             {'l': 'Babar', 'p': 'cubicweb rulez & 42'}),
+            ('INSERT CWGroup G: G name "pachyderms"', {}),
+            ('SET U in_group G WHERE U eid %(u)s, G eid %(g)s',
+             {'u': '__r0', 'g': '__r1'}),
+        ]
+        rsession = self.connectedRQLIOSession()
+        url = urlparse.urljoin(self.config['base-url'], 'rqlio/1.0')
+        files = {
+            'json': ('json', json.dumps(queries), 'application/json'),
+        }
+        response = rsession.post(
+            url, files=files,
+            headers={
+                'Accept': 'application/json',
+            },
+        )
+        self.assertEqual(response.status_code, 200, response.text)
+
     def test_rewrite_args_errors(self):
         rql1 = 'Any U WHERE U login %(l)s'
         rql2 = 'SET U in_group G WHERE G name "managers", U eid %(u)s'
diff --git a/views.py b/views.py
--- a/views.py
+++ b/views.py
@@ -107,11 +107,14 @@ class RqlIOController(Controller):
             contenttype = self._cw.get_header('Content-Type', raw=False)
             if (contenttype.mediaType, contenttype.mediaSubtype) == ('application', 'json'):  # noqa: E501
                 encoding = contenttype.params.get('charset', 'utf-8')
-                content = self._cw.content.getvalue().decode(encoding)
-                args = json.loads(content)
+                content = self._cw.content
             else:
-                args = json.load(self._cw.form['json'][1])
-
+                # Multipart content is usually built by
+                # cubicweb.multipart.parse_form_data() which encodes using
+                # "utf-8" by default.
+                encoding = 'utf-8'
+                content = self._cw.form['json'][1]
+            args = json.loads(content.getvalue().decode(encoding))
         except ValueError as exc:
             raise RemoteCallFailed(exc_message(exc, self._cw.encoding))
         if not isinstance(args, (list, tuple)):


More information about the cubicweb-devel mailing list