Changeset - fee9895fa46e
[Not reviewed]
beta
0 2 0
Marcin Kuzminski - 14 years ago 2011-11-21 02:08:09
marcin@python-works.com
changed API to match fully JSON-RPC specs
2 files changed with 13 insertions and 7 deletions:
0 comments (0 inline, 0 general)
docs/api/api.rst
Show inline comments
 
@@ -2,48 +2,51 @@
 

	
 

	
 
API
 
===
 

	
 

	
 
Starting from RhodeCode version 1.2 a simple API was implemented.
 
There's a single schema for calling all api methods. API is implemented
 
with JSON protocol both ways. An url to send API request in RhodeCode is
 
<your_server>/_admin/api
 

	
 

	
 
All clients need to send JSON data in such format::
 
All clients are required to send JSON-RPC spec JSON data::
 

	
 
    {
 
    {   
 
        "id:<id>,
 
        "api_key":"<api_key>",
 
        "method":"<method_name>",
 
        "args":{"<arg_key>":"<arg_val>"}
 
    }
 

	
 
Example call for autopulling remotes repos using curl::
 
    curl https://server.com/_admin/api -X POST -H 'content-type:text/plain' --data-binary '{"api_key":"xe7cdb2v278e4evbdf5vs04v832v0efvcbcve4a3","method":"pull","args":{"repo":"CPython"}}'
 
    curl https://server.com/_admin/api -X POST -H 'content-type:text/plain' --data-binary '{"id":1,"api_key":"xe7cdb2v278e4evbdf5vs04v832v0efvcbcve4a3","method":"pull","args":{"repo":"CPython"}}'
 

	
 
Simply provide
 
 - *id* A value of any type, which is used to match the response with the request that it is replying to.
 
 - *api_key* for access and permission validation.
 
 - *method* is name of method to call
 
 - *args* is an key:value list of arguments to pass to method
 

	
 
.. note::
 

	
 
    api_key can be found in your user account page
 

	
 

	
 
RhodeCode API will return always a JSON formatted answer::
 
RhodeCode API will return always a JSON-RPC response::
 

	
 
    {
 
    {   
 
        "id":<id>,
 
        "result": "<result>",
 
        "error": null
 
    }
 

	
 
All responses from API will be `HTTP/1.0 200 OK`, if there's an error while
 
calling api *error* key from response will contain failure description
 
and result will be null.
 

	
 
API METHODS
 
+++++++++++
 

	
 

	
rhodecode/controllers/api/__init__.py
Show inline comments
 
@@ -41,35 +41,36 @@ from pylons.controllers import WSGIContr
 
from webob.exc import HTTPNotFound, HTTPForbidden, HTTPInternalServerError, \
 
HTTPBadRequest, HTTPError
 

	
 
from rhodecode.model.db import User
 
from rhodecode.lib.auth import AuthUser
 

	
 
log = logging.getLogger('JSONRPC')
 

	
 
class JSONRPCError(BaseException):
 

	
 
    def __init__(self, message):
 
        self.message = message
 
        super(JSONRPCError, self).__init__()
 

	
 
    def __str__(self):
 
        return str(self.message)
 

	
 

	
 
def jsonrpc_error(message, code=None):
 
    """
 
    Generate a Response object with a JSON-RPC error body
 
    """
 
    from pylons.controllers.util import Response
 
    resp = Response(body=json.dumps(dict(result=None, error=message)),
 
    resp = Response(body=json.dumps(dict(id=None, result=None, error=message)),
 
                    status=code,
 
                    content_type='application/json')
 
    return resp
 

	
 

	
 

	
 
class JSONRPCController(WSGIController):
 
    """
 
     A WSGI-speaking JSON-RPC controller class
 
    
 
     See the specification:
 
     <http://json-rpc.org/wiki/specification>`.
 
@@ -108,24 +109,25 @@ class JSONRPCController(WSGIController):
 
        raw_body = environ['wsgi.input'].read(length)
 

	
 
        try:
 
            json_body = json.loads(urllib.unquote_plus(raw_body))
 
        except ValueError, e:
 
            #catch JSON errors Here
 
            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_id = json_body['id']
 
            self._req_method = json_body['method']
 
            self._req_params = json_body['args']
 
            log.debug('method: %s, params: %s',
 
                      self._req_method,
 
                      self._req_params)
 
        except KeyError, e:
 
            return jsonrpc_error(message='Incorrect JSON query missing %s' % e)
 

	
 
        # check if we can find this session using api_key
 
        try:
 
            u = User.get_by_api_key(self._req_api_key)
 
            if u is None:
 
@@ -211,25 +213,26 @@ class JSONRPCController(WSGIController):
 
                self._error = str(raw_response)
 
        except JSONRPCError, e:
 
            self._error = str(e)
 
        except Exception, e:
 
            log.error('Encountered unhandled exception: %s' \
 
                      % traceback.format_exc())
 
            json_exc = JSONRPCError('Internal server error')
 
            self._error = str(json_exc)
 

	
 
        if self._error is not None:
 
            raw_response = None
 

	
 
        response = dict(result=raw_response, error=self._error)
 
        response = dict(id=self._req_id, result=raw_response,
 
                        error=self._error)
 

	
 
        try:
 
            return json.dumps(response)
 
        except TypeError, e:
 
            log.debug('Error encoding response: %s', e)
 
            return json.dumps(dict(result=None,
 
                                   error="Error encoding response"))
 

	
 
    def _find_method(self):
 
        """
 
        Return method named by `self._req_method` in controller if able
 
        """
0 comments (0 inline, 0 general)