diff --git a/nilmdb/server/server.py b/nilmdb/server/server.py index 42d17e1..4712ad3 100644 --- a/nilmdb/server/server.py +++ b/nilmdb/server/server.py @@ -227,6 +227,20 @@ class Stream(NilmApp): result[k] = None return result + # Helper for set_metadata and get_metadata + def _metadata_helper(self, function, path, data): + if not isinstance(data, dict): + try: + data = dict(json.loads(data)) + except TypeError as e: + raise NilmDBError("can't parse 'data' parameter: " + e.message) + for key in data: + if not (isinstance(data[key], basestring) or + isinstance(data[key], float) or + isinstance(data[key], int)): + raise NilmDBError("metadata values must be a string or number") + function(path, data) + # /stream/set_metadata?path=/newton/prep&data= @cherrypy.expose @cherrypy.tools.json_in() @@ -235,30 +249,19 @@ class Stream(NilmApp): @cherrypy.tools.CORS_allow(methods = ["POST"]) def set_metadata(self, path, data): """Set metadata for the named stream, replacing any existing - metadata. Data can be json-encoded or a plain dictionary (if - it was sent as application/json to begin with)""" - if not isinstance(data, dict): - try: - data = dict(json.loads(data)) - except TypeError as e: - raise NilmDBError("can't parse 'data' parameter: " + e.message) - self.db.stream_set_metadata(path, data) + metadata. Data can be json-encoded or a plain dictionary.""" + self._metadata_helper(self.db.stream_set_metadata, path, data) # /stream/update_metadata?path=/newton/prep&data= @cherrypy.expose @cherrypy.tools.json_in() @cherrypy.tools.json_out() - @exception_to_httperror(NilmDBError, LookupError) + @exception_to_httperror(NilmDBError, LookupError, ValueError) @cherrypy.tools.CORS_allow(methods = ["POST"]) def update_metadata(self, path, data): - """Update metadata for the named stream. Data - should be a json-encoded dictionary""" - if not isinstance(data, dict): - try: - data = dict(json.loads(data)) - except TypeError as e: - raise NilmDBError("can't parse 'data' parameter: " + e.message) - self.db.stream_update_metadata(path, data) + """Set metadata for the named stream, replacing any existing + metadata. Data can be json-encoded or a plain dictionary.""" + self._metadata_helper(self.db.stream_update_metadata, path, data) # /stream/insert?path=/newton/prep @cherrypy.expose diff --git a/tests/test_client.py b/tests/test_client.py index 8d89bbf..5d4c39e 100644 --- a/tests/test_client.py +++ b/tests/test_client.py @@ -162,6 +162,16 @@ class TestClient(object): client.stream_set_metadata("/newton/prep", [1,2,3]) with assert_raises(ClientError): client.stream_update_metadata("/newton/prep", [1,2,3]) + + # test wrong types (dict of non-strings) + # numbers are OK; they'll get converted to strings + client.stream_set_metadata("/newton/prep", { "hello": 1234 }) + # anything else is not + with assert_raises(ClientError): + client.stream_set_metadata("/newton/prep", { "world": { 1: 2 } }) + with assert_raises(ClientError): + client.stream_set_metadata("/newton/prep", { "world": [ 1, 2 ] }) + client.close() def test_client_04_insert(self):