diff --git a/master/buildbot/test/unit/test_www_rest.py b/master/buildbot/test/unit/test_www_rest.py index a94b64dcb56..c4f9beab3a1 100644 --- a/master/buildbot/test/unit/test_www_rest.py +++ b/master/buildbot/test/unit/test_www_rest.py @@ -669,3 +669,16 @@ def test_valid_fails(self): responseCode=500) # the error gets logged, too: self.assertEqual(len(self.flushLoggedErrors(RuntimeError)), 1) + + +class ContentTypeParser(unittest.TestCase): + + def test_simple(self): + self.assertEqual(rest.ContentTypeParser("application/json").gettype(), "application/json") + + def test_complex(self): + self.assertEqual(rest.ContentTypeParser("application/json; Charset=UTF-8").gettype(), + "application/json") + + def test_text(self): + self.assertEqual(rest.ContentTypeParser("text/plain; Charset=UTF-8").gettype(), "text/plain") diff --git a/master/buildbot/www/rest.py b/master/buildbot/www/rest.py index ed3b83056fd..8263190706e 100644 --- a/master/buildbot/www/rest.py +++ b/master/buildbot/www/rest.py @@ -17,6 +17,7 @@ import datetime import fnmatch +import mimetools import re import types @@ -43,6 +44,18 @@ def __init__(self, message, jsonrpccode): self.jsonrpccode = jsonrpccode +class ContentTypeParser(mimetools.Message): + + def __init__(self, contenttype): + self.typeheader = contenttype + self.encodingheader = None + self.parsetype() + self.parseplist() + +URL_ENCODED = "application/x-www-form-urlencoded" +JSON_ENCODED = "application/json" + + class RestRootResource(resource.Resource): version_classes = {} @@ -65,7 +78,7 @@ def __init__(self, master): self.putChild('latest', child) def render(self, request): - request.setHeader("content-type", 'application/json') + request.setHeader("content-type", JSON_ENCODED) min_vers = self.master.config.www.get('rest_minimum_version', 0) api_versions = dict(('v%d' % v, '%sapi/v%d' % (self.base_url, v)) for v in self.version_classes @@ -73,8 +86,6 @@ def render(self, request): return json.dumps(dict(api_versions=api_versions)) -URL_ENCODED = "application/x-www-form-urlencoded" -JSON_ENCODED = "application/json" JSONRPC_CODES = dict(parse_error=-32700, invalid_request=-32600, method_not_found=-32601, @@ -137,7 +148,7 @@ def decodeJsonRPC2(self, request): # 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': + if ContentTypeParser(request.getHeader('content-type')).gettype() != JSON_ENCODED: raise BadJsonRpc2('Invalid content-type (use application/json)', JSONRPC_CODES["invalid_request"]) @@ -204,7 +215,6 @@ def writeError(msg, errcode=399, request.write(data) # JSONAPI support - def decodeResultSpec(self, request, endpoint): reqArgs = request.args