Simple API Access Objects¶
Most of the APIs out there leverage basic REST with JSON or XML as the data
encoding method. Since these APIs behave similarly, we can define the API
URLs and HTTP methods inside a dict
, without writing any actual python
methods.
HTTPBin RestConsumer¶
HTTPBIN = {
'path': '/',
'http_methods': {'get': {}},
'attrs': {
'get': {
'path': '/get',
'http_methods': {'get': {}},
},
'post': {
'path': '/post',
'http_methods': {'post': {}},
},
'put': {
'path': '/put',
'http_methods': {'put': {}},
},
'delete': {
'path': '/delete',
'http_methods': {'delete': {}},
},
}
}
class HTTPBinRestClient(api.RestConsumer):
CONFIG = HTTPBIN
ENDPOINT = 'http://httpbin.org'
class HTTPBinGetThenPost(object):
def __init__(self, \*args, \**kwargs):
super(HTTPBinGetThenPost, self).__init__(\*args, \**kwargs)
self._api = HTTPBinRestClient(timeout=60)
@gen.coroutine
def execute(self):
yield self._api.get().http_get()
yield self._api.post().http_post(foo='bar')
Exception Handling in HTTP Requests¶
The fetch()
method has been wrapped
in a retry()
decorator that allows you to
define different behaviors based on the exceptions returned from the fetch
method. For example, you may want to handle an
HTTPError
exception with a 401
error code differently than a 503
error code.
You can customize the exception handling by subclassing the
RestClient
:
class MyRestClient(api.RestClient):
EXCEPTIONS = {
httpclient.HTTPError: {
# These do not retry, they immediately raise an exception
'401': my.CustomException(),
'403': exceptions.InvalidCredentials,
'500': my.UnretryableError(),
'502': exceptions.InvalidOptions,
# This indicates a retry should happen
'503': None,
# This acts as a catch-all
'': MyException,
}
}