Advanced usage

httpbin.org is a great testing tool for various situations you may run into when interacting with RESTful services. Let’s define a Service that points at httpbin.org and hook up a few interesting endpoints.

Service and endpoints

# test_service.py
from apiron import Endpoint, JsonEndpoint, Service, StreamingEndpoint

class HttpBin(Service):
    domain = 'https://httpbin.org'

    getter = JsonEndpoint(path='/get')
    poster = JsonEndpoint(path='/post', default_method='POST')
    status = Endpoint(path='/status/{status_code}/')
    anything = JsonEndpoint(path='/anything/{anything}')
    slow = JsonEndpoint(path='/delay/5')
    streamer = StreamingEndpoint(path='/stream/{num_lines}')

Using all the features

import requests

from apiron import Timeout

from test_service import HttpBin

# A normal old GET call
HttpBin.getter(params={'foo': 'bar'})

# A normal old POST call
HttpBin.poster(data={'foo': 'bar'})

# A GET call with parameters formatted into the path
HttpBin.anything(anything=42)

# A GET call with a 500 response, raises RetryError since we successfully tried but got a bad response
try:
    HttpBin.status(status_code=500)
except requests.exceptions.RetryError:
    pass

# A GET call to a slow endpoint, raises ConnectionError since our connection failed
try:
    HttpBin.slow()
except requests.exceptions.ConnectionError:
    pass

# A GET call to a slow endpoint with a longer timeout
HttpBin.slow(
    timeout_spec=Timeout(connection_timeout=1, read_timeout=6)
)

# A streaming response
response = HttpBin.streamer(num_lines=20)
for chunk in response:
    print(chunk)

Service discovery

You may want to interact with a service whose name is known but whose hosts are resolved via another application. Here is an example where the resolver application always resolves to https://www.google.com for the host.

from apiron import DiscoverableService

class Eureka:
    @staticmethod
    def resolve(service_name):
        hosts = ...  # get host list from Eureka

class AuthenticationService(DiscoverableService):
    service_name = 'authentication-service'
    host_resolver_class = Eureka

    auth = Endpoint(path='/auth')


response = AuthenticationService.auth(data={'user': 'Gandalf', 'password': 'Mellon'})

An application may wish to use a load balancer application or a more complex service discovery mechanism (like Netflix’s Eureka) to resolve the hostnames of a given service.

Workflow consistency

It’s common to have an existing requests.Session object you’d like to use to make additional requests. This is enabled in apiron with the session argument to an endpoint call. The passed in session object will be used to send the request. This is useful for workflows where cookies or other information need to persist across multiple calls.

It’s often more useful in logs to know which module initiated the code doing the logging. apiron allows for an existing logger object to be passed to an endpoint call using the logger argument so that logs will indicate the caller module rather than apiron.client.