diff --git a/wsme/exc.py b/wsme/exc.py index 7445a75..5f793a2 100644 --- a/wsme/exc.py +++ b/wsme/exc.py @@ -5,7 +5,8 @@ if '_' not in __builtin__.__dict__: class ClientSideError(RuntimeError): - pass + def __str__(self): + return unicode(self).encode('utf8', 'ignore') class InvalidInput(ClientSideError): @@ -18,9 +19,6 @@ class InvalidInput(ClientSideError): return _(u"Invalid input for field/attribute %s. Value: '%s'. %s") % ( self.fieldname, self.value, self.msg) - def __str__(self): - return unicode(self).encode('utf8', 'ignore') - class MissingArgument(ClientSideError): def __init__(self, argname, msg=''): @@ -31,8 +29,15 @@ class MissingArgument(ClientSideError): return _(u'Missing argument: "%s"%s') % ( self.argname, self.msg and ": " + self.msg or "") - def __str__(self): - return unicode(self).encode('utf8', 'ignore') + +class UnknownArgument(ClientSideError): + def __init__(self, argname, msg=''): + self.argname = argname + self.msg = msg + + def __unicode__(self): + return _(u'Unknown argument: "%s"%s') % ( + self.argname, self.msg and ": " + self.msg or "") class UnknownFunction(ClientSideError): @@ -42,5 +47,3 @@ class UnknownFunction(ClientSideError): def __unicode__(self): return _(u"Unknown function name: %s") % (self.name) - def __str__(self): - return unicode(self).encode('utf8', 'ignore') diff --git a/wsme/rest.py b/wsme/rest.py index 5ac3bb0..f237c0b 100644 --- a/wsme/rest.py +++ b/wsme/rest.py @@ -1,7 +1,7 @@ import webob import sys -from wsme.exc import UnknownFunction +from wsme.exc import UnknownFunction, MissingArgument, UnknownArgument html_body = """ @@ -24,6 +24,39 @@ class RestProtocol(object): return True return request.headers.get('Content-Type') in self.content_types + def read_arguments(self, request, arguments): + if len(request.params) and request.body: + raise ClientSideError( + "Cannot read parameters from both a body and GET/POST params") + + body = None + if 'body' in request.params: + body = request.params['body'] + + if body is None and len(request.params): + parsed_args = {} + for key, value in request.params.items(): + parsed_args[key] = self.parse_arg(value) + else: + if body is None: + body = request.body + parsed_args = self.parse_args(body) + + kw = {} + + for arg in arguments: + if arg.name not in parsed_args: + if arg.mandatory: + raise MissingArgument(arg.name) + continue + + value = parsed_args.pop(arg.name) + kw[arg.name] = self.decode_arg(value, arg) + + if parsed_args: + raise UnknownArgument(parsed_args.keys()[0]) + return kw + def handle(self, root, request): path = request.path.strip('/').split('/') @@ -34,7 +67,7 @@ class RestProtocol(object): try: func, funcdef = root._lookup_function(path) - kw = self.decode_args(request, funcdef.arguments) + kw = self.read_arguments(request, funcdef.arguments) result = func(**kw) # TODO make sure result type == a._wsme_definition.return_type res.body = self.encode_result(result, funcdef.return_type) diff --git a/wsme/restjson.py b/wsme/restjson.py index a87443b..169d075 100644 --- a/wsme/restjson.py +++ b/wsme/restjson.py @@ -92,17 +92,15 @@ class RestJsonProtocol(RestProtocol): dataformat = 'json' content_types = ['application/json', 'text/json', '', None] - def decode_args(self, req, arguments): - if not req.body: - return {} - raw_args = json.loads(req.body) - kw = {} - for farg in arguments: - if farg.mandatory and farg.name not in raw_args: - raise MissingArgument(farg.name) - value = raw_args[farg.name] - kw[farg.name] = fromjson(farg.datatype, value) - return kw + def decode_arg(self, value, arg): + return fromjson(arg.datatype, value) + + def parse_arg(self, value): + return json.loads(value) + + def parse_args(self, body): + raw_args = json.loads(body) + return raw_args def encode_result(self, result, return_type): r = tojson(return_type, result) diff --git a/wsme/restxml.py b/wsme/restxml.py index 5c1334f..1381dcb 100644 --- a/wsme/restxml.py +++ b/wsme/restxml.py @@ -116,26 +116,14 @@ class RestXmlProtocol(RestProtocol): dataformat = 'xml' content_types = ['text/xml'] - def decode_args(self, req, arguments): - if req.body: - try: - el = et.fromstring(req.body) - except Exception, e: - raise ClientSideError(str(e)) - else: - el = et.Element('parameters') + def decode_arg(self, value, arg): + return fromxml(arg.datatype, value) - if el.tag != 'parameters': - raise ClientSideError("Input should be a 'parameters' xml tag") + def parse_arg(self, value): + return et.fromstring(value) - kw = {} - for farg in arguments: - sub = el.find(farg.name) - if farg.mandatory and sub is None: - raise MissingArgument(farg.name) - if sub is not None: - kw[farg.name] = fromxml(farg.datatype, sub) - return kw + def parse_args(self, body): + return dict((sub.tag, sub) for sub in et.fromstring(body)) def encode_result(self, result, return_type): return et.tostring(toxml(return_type, 'result', result))