Repository: buildbot/buildbot

Issue:
Replace filter() with list comprehension.
This fixes Python 3 error:
   'filter' object is not subscriptable


Discussion:

Resolving patch:
diff --git a/master/buildbot/www/rest.py b/master/buildbot/www/rest.py
--- a/master/buildbot/www/rest.py
+++ b/master/buildbot/www/rest.py
@@ -134,9 +134,13 @@ def handleErrors(self, writeError):
     # JSONRPC2 support
 
     def decodeJsonRPC2(self, request):
-        # Content-Type is ignored, so that AJAX requests can be sent without
-        # incurring CORS preflight overheads.  The JSONRPC spec does not
-        # suggest a Content-Type anyway.
+        # Verify the content-type.  Browsers are easily convinced to send
+        # POST data to arbitrary URLs via 'form' elements, but they won't
+        # use the application/json content-type.
+        if request.getHeader('content-type') != 'application/json':
+            raise BadJsonRpc2('Invalid content-type (use application/json)',
+                              JSONRPC_CODES["invalid_request"])
+
         try:
             data = json.loads(request.content.read())
         except Exception, e:


Test patch:
diff --git a/master/buildbot/test/unit/test_www_rest.py b/master/buildbot/test/unit/test_www_rest.py
--- a/master/buildbot/test/unit/test_www_rest.py
+++ b/master/buildbot/test/unit/test_www_rest.py
@@ -544,6 +544,16 @@ def test_invalid_json(self):
             message=re.compile('^JSON parse error'),
             jsonrpccode=JSONRPC_CODES['parse_error'])
 
+    @defer.inlineCallbacks
+    def test_invalid_content_type(self):
+        yield self.render_control_resource(self.rsrc, '/test',
+                requestJson='{"jsonrpc": "2.0", "method": "foo",'
+                            '"id":"abcdef", "params": {}}',
+                content_type='application/x-www-form-urlencoded')
+        self.assertJsonRpcError(
+            message=re.compile('Invalid content-type'),
+            jsonrpccode=JSONRPC_CODES['invalid_request'])
+
     @defer.inlineCallbacks
     def test_list_request(self):
         yield self.render_control_resource(self.rsrc, '/test',
diff --git a/master/buildbot/test/util/www.py b/master/buildbot/test/util/www.py
--- a/master/buildbot/test/util/www.py
+++ b/master/buildbot/test/util/www.py
@@ -156,14 +156,15 @@ def render_resource(self, rsrc, path='/', accept=None, method='GET',
         return request.deferred
 
     def render_control_resource(self, rsrc, path='/', params={},
-                                requestJson=None, action="notfound", id=None):
+                                requestJson=None, action="notfound", id=None,
+                                content_type='application/json'):
         # pass *either* a request or postpath
         id = id or self.UUID
         request = self.make_request(path)
         request.method = "POST"
         request.content = StringIO(requestJson or json.dumps(
             {"jsonrpc": "2.0", "method": action, "params": params, "id": id}))
-        request.input_headers = {'content-type': 'application/json'}
+        request.input_headers = {'content-type': content_type}
         rv = rsrc.render(request)
         if rv != server.NOT_DONE_YET:
             d = defer.succeed(rv)