apiclient
apiclient is a simple, lightweight Python framework for building API clients for REST-like services, leveraging `urllib3` for HTTP requests. It provides decorators for defining API endpoints and handles the boilerplate of request building and response processing. The current version is 1.0.4, with recent minor updates indicating active maintenance.
Common errors
-
urllib3.exceptions.MaxRetryError: HTTPConnectionPool(...)` or `urllib3.exceptions.NewConnectionError: <urllib3.connection.HTTPConnection object at ...>: Failed to establish a new connection: [Errno ...]
cause These exceptions indicate network connectivity issues, an incorrect `base_url` (e.g., wrong host, port, or protocol), or the API server being unreachable.fixVerify network connection, check `base_url` for typos, ensure the target API server is online and accessible. Consider adding retry logic to your client. -
urllib3.exceptions.HTTPError: HTTP 401: Unauthorized` (or `403: Forbidden`, `404: Not Found`, etc.)
cause The API server returned an error status code. This could be due to invalid or missing authentication credentials, incorrect endpoint path, or a resource not being found.fixEnsure your authentication headers are correctly set (e.g., `Authorization` header), verify the API key/token is valid, and double-check the `endpoint` path and method (e.g., `get` vs. `post`). Remember to call `response.raise_for_status()` to explicitly raise these HTTP errors.
Warnings
- gotcha Explicit Response Handling Required: `apiclient`'s `@endpoint` methods return a wrapped `urllib3` response object (type `apiclient._response.ResponseWrapper`). While this wrapper provides convenient `.json()` and `.raise_for_status()` methods, users must explicitly call them to parse the body or check for HTTP errors. The library does not automatically perform these actions.
- gotcha Minimal Feature Set - Implement Advanced Logic Manually: `apiclient` is a lightweight framework for defining API clients. It does not include built-in features like automatic retries with exponential backoff, rate limit handling, advanced caching, or request signing beyond basic headers. These must be implemented by the user if required for robust production clients.
- gotcha Potential for Indirect Impact from `urllib3` Updates: `apiclient` relies on `urllib3` for its HTTP core. While `apiclient` maintains its own stability, breaking changes, deprecations, or security updates in `urllib3` can indirectly affect your client's behavior or require updates to your environment. `apiclient` requires `urllib3>=1.26.0`.
Install
-
pip install apiclient
Imports
- APIClient
from apiclient import APIClient
- endpoint
from apiclient import endpoint
Quickstart
import os
from apiclient import APIClient, endpoint
import urllib3.exceptions # Import for specific error handling
class GitHubClient(APIClient):
@endpoint
def get_user_repos(self, username: str):
# The 'get' method returns a apiclient._response.ResponseWrapper object
return self.get(f'/users/{username}/repos')
# Initialize the client. For authentication, pass headers.
# Use os.environ.get for an example of token usage.
token = os.environ.get('GITHUB_TOKEN', '')
headers = {'Authorization': f'token {token}'} if token else {}
client = GitHubClient(base_url='https://api.github.com', headers=headers)
try:
# Call the endpoint. The wrapped urllib3 response is returned.
response = client.get_user_repos(username='shazow')
# apiclient returns wrapped urllib3 responses directly.
# Always check status and explicitly parse JSON.
response.raise_for_status() # Raises an exception for HTTP error codes (e.g., 404, 500)
repos = response.json() # Parses the JSON body
print(f"Successfully fetched {len(repos)} repositories for shazow.")
if repos:
print(f"First repository: {repos[0]['name']}")
except urllib3.exceptions.HTTPError as e:
print(f"HTTP Error: {e.status} - {e.reason}")
except urllib3.exceptions.MaxRetryError as e:
print(f"Network Error: Could not connect to host. {e}")
except Exception as e:
print(f"An unexpected error occurred: {e}")