Clients ======= At the heart of RestORM you have a ``Client``. The client simply allows you to communicate with an API and the one RestORM uses is built on top of the excellent `httplib2 library `_. However, you are free to use any HTTP client library as long as you add the RestORM mixins. Create a client --------------- Most RESTful API support the JSON format for their responses. A client that can handle JSON is therefore included in RestORM. .. autoclass:: restorm.clients.jsonclient.JSONClient .. sourcecode:: python from restorm.clients.jsonclient import JSONClient client = JSONClient(root_uri='http://www.example.com/api/') The ``JSONClient`` is actually a combination of the classes ``BaseClient`` and ``JSONClientMixin``. The ``BaseClient`` is responsible for communicating with the API while the ``JSONClientMixin`` adds serialization and deserialization for JSON. ``JSONClient`` itself is a subclass of ``ClientMixin`` which exposes various convenience methods. .. autoclass:: restorm.clients.base.BaseClient :members: request .. autoclass:: restorm.clients.base.ClientMixin :members: serialize, deserialize, create_request, create_response, get, post, put, delete Writing your own client ----------------------- You can tweak almost everything about the client architecture but the minimum requirements to work with RestORM resources are: #. You use the ``ClientMixin`` in your client. #. Have a ``request`` function that returns a ``Response`` object. A minimal implementation would be: .. sourcecode:: python from restorm.clients.base import ClientMixin class MyClient(ClientMixin): def request(self, uri, method, body=None, headers=None): # Create request. request = self.create_request(uri, method, body, headers) # My very own client doesn't need an internet connection! response_headers, response_content = {'Status': 200}, 'Hello world!' # Create response. return self.create_response(response_headers, response_content, request) The above client doesn't do much but it shows how to create your own client: .. sourcecode:: python >>> client = MyClient() >>> response = client.get('/hello/') >>> response.content 'Hello world!' >>> response.headers {'Status': 200} >>> response.request.uri '/hello/' You can override any of the ``ClientMixin`` functions to add custom behaviour: .. sourcecode:: python class MyClient(ClientMixin): # ... def create_request(uri, method, body=None, headers=None): """ Make sure the URI is absolute. """ if not uri.startswith('/'): uri = '/%s' % uri return super(MyClient, self).create_request(uri, method, body, headers) def create_response(response_headers, response_content, request): """ Let everone know that it was MyClient that processed the response. """ response_headers.update({ 'X-Response-Updated-By': 'MyClient' }) return super(MyClient, self).create_response(response_headers, response_content, request) .. sourcecode:: python >>> client = MyClient() >>> response = client.get('hello/') >>> response.content 'Hello world!' >>> response.headers {'Status': 200, 'X-Response-Updated-By': 'MyClient'} >>> response.request.uri '/hello/' RestORM can handle JSON as response format from RESTful API's. Implementing your own format requires you to override the ``serialize`` and ``deserialize`` function in your own client class. Using different HTTP client libraries ------------------------------------- There are lots of different client libraries. RestORM chose for ``httplib2`` as default HTTP client library because it's an active project with built-in caching and overall has the best performance. Do not let the above stop you from using your own preferred HTTP client library like `requests `_, `oauth2 `_, or even the standard library `httplib `_ Example: OAuth ~~~~~~~~~~~~~~ Many API's use OAuth, an open standard for authorization. It's quite simple to incorporate the `oauth2 library `_ in combination with one of the client mixins, for example the ``JSONClientMixin`` and override the ``request`` method to make a request using OAuth: .. sourcecode:: python import oauth2 as oauth from restorm.clients.jsonclient import JSONClientMixin class OauthClient(oauth.Client, JSONClientMixin): def request(self, uri, method='GET', body=None, headers=None, *args, **kwargs): # Create request. request = self.create_request(uri, method, body, headers) # Perform request. response_headers, response_content = super(OauthClient, self).request(request.uri, request.method, request.body, request, *args, **kwargs) # Create response. return self.create_response(response_headers, response_content, request) Once we have this, we can do: .. sourcecode:: python >>> consumer = oauth.Consumer(key='YOUR_KEY', secret='YOUR_SECRET') >>> token = oauth.Token(key='YOUR_TOKEN', secret='YOUR_TOKEN_SECRET') >>> client = OauthClient(consumer, token)