RESTfly
RESTfly (pronounced restfully) is a framework for building libraries to easily interact with RESTful APIs. It aims to simplify the creation of API interaction libraries by providing a basic scaffolding with an emphasis on simplicity and readability of the resulting code. The library is currently at version 1.5.1 and receives regular updates, ensuring active development and maintenance.
Common errors
-
ImportError: cannot import name 'APISession' from 'restfly'
cause Attempting to import `APISession` directly from the top-level `restfly` package instead of its specific submodule.fixUse `from restfly.session import APISession`. -
AttributeError: 'Response' object has no attribute 'json'
cause This typically occurs when a `requests.Response` object (which `restfly` uses internally) is returned, but the content is not JSON, or the `.json()` method is called on an empty response. It can also happen if `_conv_json` is set to `False` in the `APISession` and the result is not manually parsed.fixEnsure the API endpoint actually returns JSON content. For non-JSON responses, access `response.text` or `response.content`. If `_conv_json` is explicitly set to `False`, handle the raw `requests.Response` object accordingly. Consider checking `response.ok` or `response.status_code` before attempting to parse. -
restfly.errors.UnauthorizedError: 401 Unauthorized
cause The API request failed due to missing or invalid authentication credentials (e.g., incorrect API key, expired token).fixVerify that your API key, token, or other authentication methods are correctly configured and passed in the `APISession` initialization or request headers. Use context handling for session-based authentication to ensure proper login/logout.
Warnings
- gotcha When handling session-based authentication, developers commonly forget to explicitly log out or close sessions, potentially leading to lingering sessions. RESTfly offers context management hooks to facilitate proper authentication and de-authentication.
- gotcha RESTfly wraps common HTTP status codes (e.g., 400, 401, 403, 404, 500) into specific exception classes (e.g., `BadRequestError`, `UnauthorizedError`, `NotFoundError`). Failing to catch these specific exceptions can lead to less granular error handling, potentially masking the true nature of API failures.
- breaking The project repository was moved in version 1.5.0. While `pip install` typically handles this, direct clones or older documentation links referencing the previous repository location may be broken.
Install
-
pip install restfly
Imports
- APISession
from restfly import APISession
from restfly.session import APISession
- APIEndpoint
from restfly import APIEndpoint
from restfly.endpoint import APIEndpoint
- APIError
from restfly.errors import APIError, BadRequestError, UnauthorizedError
Quickstart
import os
from restfly.session import APISession
from restfly.endpoint import APIEndpoint
# Define your base API session
class MyAPI(APISession):
_url = 'https://httpbin.org'
# Example of adding an API key, if needed
def __init__(self, api_key: str = os.environ.get('MY_API_KEY', ''), **kwargs):
self._api_key = api_key
super().__init__(**kwargs)
def _build_session(self, **kwargs):
super()._build_session(**kwargs)
if self._api_key:
self._session.headers.update({
'X-API-Key': self._api_key
})
# Define an endpoint for a specific resource
class StatusAPI(APIEndpoint):
_path = 'status'
def get_status_code(self, code: int) -> dict:
# _req is a protected method for making requests, leveraging _path
return self._req('GET', path=str(code)).json()
# Instantiate and use the API
my_api_client = MyAPI(api_key='your_optional_api_key_here')
# Link the endpoint to the API session
my_api_client.status = StatusAPI(my_api_client)
try:
# Call a simple GET request directly from the session
response_get = my_api_client.get('get').json()
print(f"GET /get Response: {response_get.get('url')}")
# Use the defined endpoint
status_200 = my_api_client.status.get_status_code(200)
print(f"GET /status/200 Response: {status_200}")
status_404 = my_api_client.status.get_status_code(404)
print(f"GET /status/404 Response: {status_404}") # This will raise an APIError
except Exception as e:
print(f"An error occurred: {e}")
# Example of handling specific errors
from restfly.errors import NotFoundError, APIError
try:
my_api_client.status.get_status_code(404)
except NotFoundError as e:
print(f"Caught specific NotFoundError: {e}")
except APIError as e:
print(f"Caught generic APIError: {e}")