diff --git a/docs/api/api.rst b/docs/api/api.rst --- a/docs/api/api.rst +++ b/docs/api/api.rst @@ -7,7 +7,8 @@ API Starting from RhodeCode version 1.2 a simple API was implemented. There's one schema for calling all api methods. API is implemented -with JSON protocol both ways. +with JSON protocol both ways. An url to send API request in RhodeCode is +/_admin/api Clients need to send JSON data in such format:: @@ -50,7 +51,7 @@ remote repos upto date. This command can api_key :: - + api_key:"" method: "pull" args: {"repo":} diff --git a/rhodecode/controllers/api/__init__.py b/rhodecode/controllers/api/__init__.py --- a/rhodecode/controllers/api/__init__.py +++ b/rhodecode/controllers/api/__init__.py @@ -39,7 +39,7 @@ from pylons.controllers.util import Resp from webob.exc import HTTPNotFound, HTTPForbidden, HTTPInternalServerError, \ HTTPBadRequest, HTTPError -from rhodecode.model.user import User +from rhodecode.model.db import User from rhodecode.lib.auth import AuthUser log = logging.getLogger('JSONRPC') @@ -85,10 +85,9 @@ class JSONRPCController(WSGIController): Parse the request body as JSON, look up the method on the controller and if it exists, dispatch to it. """ - if 'CONTENT_LENGTH' not in environ: log.debug("No Content-Length") - return jsonrpc_error(0, "No Content-Length") + return jsonrpc_error(message="No Content-Length in request") else: length = environ['CONTENT_LENGTH'] or 0 length = int(environ['CONTENT_LENGTH']) @@ -96,7 +95,7 @@ class JSONRPCController(WSGIController): if length == 0: log.debug("Content-Length is 0") - return jsonrpc_error(0, "Content-Length is 0") + return jsonrpc_error(message="Content-Length is 0") raw_body = environ['wsgi.input'].read(length) @@ -104,12 +103,10 @@ class JSONRPCController(WSGIController): json_body = json.loads(urllib.unquote_plus(raw_body)) except ValueError as e: #catch JSON errors Here - return jsonrpc_error("JSON parse error ERR:%s RAW:%r" \ + return jsonrpc_error(message="JSON parse error ERR:%s RAW:%r" \ % (e, urllib.unquote_plus(raw_body))) - #check AUTH based on API KEY - try: self._req_api_key = json_body['api_key'] self._req_method = json_body['method'] @@ -131,7 +128,7 @@ class JSONRPCController(WSGIController): try: self._func = self._find_method() except AttributeError, e: - return jsonrpc_error(str(e)) + return jsonrpc_error(message=str(e)) # now that we have a method, add self._req_params to # self.kargs and dispatch control to WGIController @@ -143,7 +140,7 @@ class JSONRPCController(WSGIController): self.rhodecode_user = auth_u if 'user' not in arglist: - return jsonrpc_error('This method [%s] does not support ' + return jsonrpc_error(message='This method [%s] does not support ' 'authentication (missing user param)' % self._func.__name__) @@ -155,7 +152,7 @@ class JSONRPCController(WSGIController): continue if not self._req_params or arg not in self._req_params: - return jsonrpc_error('Missing %s arg in JSON DATA' % arg) + return jsonrpc_error(message='Missing %s arg in JSON DATA' % arg) self._rpc_args = dict(user=u) self._rpc_args.update(self._req_params) diff --git a/rhodecode/lib/__init__.py b/rhodecode/lib/__init__.py --- a/rhodecode/lib/__init__.py +++ b/rhodecode/lib/__init__.py @@ -157,44 +157,66 @@ def generate_api_key(username, salt=None return hashlib.sha1(username + salt).hexdigest() -def safe_unicode(_str, from_encoding='utf8'): +def safe_unicode(str_, from_encoding='utf8'): """ - safe unicode function. In case of UnicodeDecode error we try to return - unicode with errors replaceed + safe unicode function. Does few trick to turn str_ into unicode + + In case of UnicodeDecode error we try to return it with encoding detected + by chardet library if it fails fallback to unicode with errors replaced - :param _str: string to decode + :param str_: string to decode :rtype: unicode :returns: unicode object """ - if isinstance(_str, unicode): - return _str + if isinstance(str_, unicode): + return str_ try: - u_str = unicode(_str, from_encoding) + return unicode(str_, from_encoding) except UnicodeDecodeError: - u_str = unicode(_str, from_encoding, 'replace') - - return u_str - + pass + + try: + import chardet + encoding = chardet.detect(str_)['encoding'] + if encoding is None: + raise UnicodeDecodeError() + + return str_.decode(encoding) + except (ImportError, UnicodeDecodeError): + return unicode(str_, from_encoding, 'replace') -def safe_str(_unicode, to_encoding='utf8'): +def safe_str(unicode_, to_encoding='utf8'): """ - safe str function. In case of UnicodeEncode error we try to return - str with errors replaceed + safe str function. Does few trick to turn unicode_ into string + + In case of UnicodeEncodeError we try to return it with encoding detected + by chardet library if it fails fallback to string with errors replaced - :param _unicode: unicode to encode + :param unicode_: unicode to encode :rtype: str :returns: str object """ - if isinstance(_unicode, str): - return _unicode + if isinstance(unicode_, str): + return unicode_ try: - safe_str = str(_unicode) + return str(unicode_) except UnicodeEncodeError: - safe_str = _unicode.encode(to_encoding, 'replace') + pass + + try: + import chardet + encoding = chardet.detect(unicode_)['encoding'] + print encoding + if encoding is None: + raise UnicodeEncodeError() + + return unicode_.encode(encoding) + except (ImportError, UnicodeEncodeError): + return unicode_.encode(to_encoding, 'replace') return safe_str