# 📚 API Reference for APIFromAnything
Comprehensive reference documentation for all modules, classes, and functions
This document provides a comprehensive reference for the APIFromAnything library's classes, methods, and functions. Use this as your go-to resource when building applications with APIFromAnything.
## 🧩 Core Module
The core module contains the fundamental components for creating and running APIs.
### API Class
The `API` class is the main entry point for creating an API. It handles routing, middleware, and serves as the central configuration point for your application.
```python
from apifrom import API
app = API(
title="My API",
description="API description",
version="1.0.0",
docs_url="/docs",
openapi_url="/openapi.json",
redoc_url="/redoc",
debug=True
)
```
#### Constructor Parameters
| Parameter | Type | Default | Description |
|-----------|------|---------|-------------|
| `title` | `str` | `"APIFromAnything"` | The title of the API, displayed in documentation |
| `description` | `str` | `None` | A detailed description of the API's purpose and functionality |
| `version` | `str` | `"1.0.0"` | The semantic version of the API (e.g., "1.2.3") |
| `docs_url` | `str` | `"/docs"` | The URL path for the Swagger UI documentation |
| `openapi_url` | `str` | `"/openapi.json"` | The URL path for the OpenAPI schema JSON |
| `redoc_url` | `str` | `"/redoc"` | The URL path for the ReDoc documentation |
| `debug` | `bool` | `False` | Enable debug mode for detailed error messages and logging |
#### Methods
##### `add_middleware`
Add a middleware component to the API. Middleware components are executed in the order they are added.
```python
from apifrom.middleware import CORSMiddleware
app.add_middleware(CORSMiddleware(
allow_origins=["https://example.com"],
allow_methods=["GET", "POST", "PUT", "DELETE"],
allow_headers=["Content-Type", "Authorization"]
))
```
| Parameter | Type | Description |
|-----------|------|-------------|
| `middleware` | `Middleware` | The middleware instance to add to the request/response processing pipeline |
##### `run`
Start the API server.
```python
app.run(host="0.0.0.0", port=8000, workers=4)
```
| Parameter | Type | Default | Description |
|-----------|------|---------|-------------|
| `host` | `str` | `"127.0.0.1"` | The host address to bind the server to |
| `port` | `int` | `8000` | The port number to listen on |
| `workers` | `int` | `1` | Number of worker processes (for production use) |
| `ssl_certfile` | `str` | `None` | Path to SSL certificate file for HTTPS |
| `ssl_keyfile` | `str` | `None` | Path to SSL key file for HTTPS |
##### `register_plugin`
Register a plugin with the API.
```python
from apifrom.plugins import LoggingPlugin
logger_plugin = LoggingPlugin()
app.register_plugin(logger_plugin)
```
| Parameter | Type | Description |
|-----------|------|-------------|
| `plugin` | `Plugin` | The plugin instance to register |
##### `mount`
Mount another API or WSGI/ASGI application at a specific path.
```python
app.mount(path="/subapi", app=subapp)
```
| Parameter | Type | Description |
|-----------|------|-------------|
| `path` | `str` | The path to mount the application at |
| `app` | `Union[API, Any]` | The application to mount |
##### `include_router`
Include a router in the API.
```python
app.include_router(router)
```
| Parameter | Type | Description |
|-----------|------|-------------|
| `router` | `Router` | The router to include |
| `prefix` | `str` | The prefix to add to all routes in the router |
| `tags` | `List[str]` | The tags to add to all routes in the router |
### api Decorator
The `api` decorator is used to define API endpoints.
```python
from apifrom import api
@api(
route="/users/{user_id}",
method="GET",
tags=["users"],
summary="Get a user",
description="Get a user by ID",
response_model=dict,
status_code=200,
deprecated=False,
include_in_schema=True
)
def get_user(user_id: int) -> dict:
return {"id": user_id, "name": "John Doe"}
```
#### Parameters
| Parameter | Type | Default | Description |
|-----------|------|---------|-------------|
| `route` | `str` | `None` | The URL path for the endpoint |
| `method` | `str` | `"GET"` | The HTTP method for the endpoint |
| `tags` | `List[str]` | `[]` | Tags for documentation |
| `summary` | `str` | `None` | Summary for documentation |
| `description` | `str` | `None` | Description for documentation |
| `response_model` | `Type` | `None` | Expected response model |
| `status_code` | `int` | `200` | HTTP status code |
| `deprecated` | `bool` | `False` | Mark as deprecated |
| `include_in_schema` | `bool` | `True` | Include in OpenAPI schema |
| `responses` | `Dict[int, Dict]` | `{}` | Additional responses |
| `response_description` | `str` | `"Successful Response"` | Description of the response |
### Request Class
The `Request` class represents an HTTP request.
```python
from apifrom.core.request import Request
@api(route="/echo", method="POST")
def echo(request: Request) -> dict:
body = request.json()
headers = request.headers
query_params = request.query_params
path_params = request.path_params
return {"body": body}
```
#### Properties
| Property | Type | Description |
|----------|------|-------------|
| `method` | `str` | The HTTP method |
| `url` | `URL` | The URL object |
| `headers` | `Headers` | The request headers |
| `query_params` | `QueryParams` | The query parameters |
| `path_params` | `PathParams` | The path parameters |
| `cookies` | `Cookies` | The cookies |
| `client` | `Address` | The client address |
| `state` | `State` | The request state |
#### Methods
##### `json`
Parse the request body as JSON.
```python
body = request.json()
```
##### `form`
Parse the request body as form data.
```python
form_data = request.form()
```
##### `body`
Get the raw request body.
```python
raw_body = request.body()
```
### Response Class
The `Response` class represents an HTTP response.
```python
from apifrom.core.response import Response
@api(route="/custom-response", method="GET")
def custom_response() -> Response:
return Response(
content={"message": "Hello, world!"},
status_code=200,
headers={"X-Custom-Header": "Value"}
)
```
#### Constructor Parameters
| Parameter | Type | Default | Description |
|-----------|------|---------|-------------|
| `content` | `Any` | `None` | The response content |
| `status_code` | `int` | `200` | The HTTP status code |
| `headers` | `Dict[str, str]` | `None` | The response headers |
| `media_type` | `str` | `None` | The media type |
| `background` | `BackgroundTask` | `None` | A background task to run after sending the response |
## Middleware Module
### Middleware Base Class
The `Middleware` class is the base class for all middleware components.
```python
from apifrom.middleware import Middleware
from apifrom.core.request import Request
from apifrom.core.response import Response
from typing import Callable, Awaitable
class CustomMiddleware(Middleware):
async def dispatch(
self,
request: Request,
call_next: Callable[[Request], Awaitable[Response]]
) -> Response:
# Process the request
print(f"Request: {request.method} {request.url.path}")
# Call the next middleware or endpoint
response = await call_next(request)
# Process the response
print(f"Response: {response.status_code}")
return response
```
#### Methods
##### `dispatch`
Process the request and response.
```python
async def dispatch(
self,
request: Request,
call_next: Callable[[Request], Awaitable[Response]]
) -> Response:
# Implementation
```
| Parameter | Type | Description |
|-----------|------|-------------|
| `request` | `Request` | The request object |
| `call_next` | `Callable[[Request], Awaitable[Response]]` | The next middleware in the stack |
### Built-in Middleware Components
#### CacheMiddleware
```python
from apifrom.middleware import CacheMiddleware
app.add_middleware(
CacheMiddleware(
ttl=60,
max_size=1000,
key_builder=None,
storage="memory",
redis_url=None,
include_query_params=True,
include_headers=False,
cache_control=True
)
)
```
| Parameter | Type | Default | Description |
|-----------|------|---------|-------------|
| `ttl` | `int` | `60` | Cache TTL in seconds |
| `max_size` | `int` | `1000` | Maximum number of cached responses |
| `key_builder` | `Callable` | `None` | Custom function to build cache keys |
| `storage` | `str` | `"memory"` | Storage backend (memory, redis) |
| `redis_url` | `str` | `None` | Redis URL (if using redis storage) |
| `include_query_params` | `bool` | `True` | Include query parameters in cache key |
| `include_headers` | `bool` | `False` | Include headers in cache key |
| `cache_control` | `bool` | `True` | Add Cache-Control headers to responses |
#### RateLimitMiddleware
```python
from apifrom.middleware import RateLimitMiddleware
app.add_middleware(
RateLimitMiddleware(
limit=100,
window=60,
key_func=lambda request: request.client.host,
storage="memory",
redis_url=None,
headers=True
)
)
```
| Parameter | Type | Default | Description |
|-----------|------|---------|-------------|
| `limit` | `int` | `100` | Maximum requests |
| `window` | `int` | `60` | Time window in seconds |
| `key_func` | `Callable` | `lambda request: request.client.host` | Function to extract the client key |
| `storage` | `str` | `"memory"` | Storage backend (memory, redis) |
| `redis_url` | `str` | `None` | Redis URL (if using redis storage) |
| `headers` | `bool` | `True` | Add rate limit headers to responses |
#### CORSMiddleware
```python
from apifrom.middleware import CORSMiddleware
app.add_middleware(
CORSMiddleware(
allow_origins=["https://example.com"],
allow_methods=["GET", "POST", "PUT", "DELETE", "OPTIONS"],
allow_headers=["Content-Type", "Authorization"],
allow_credentials=True,
expose_headers=[],
max_age=600
)
)
```
| Parameter | Type | Default | Description |
|-----------|------|---------|-------------|
| `allow_origins` | `List[str]` | `["*"]` | Allowed origins |
| `allow_methods` | `List[str]` | `["GET", "POST", "PUT", "DELETE", "OPTIONS"]` | Allowed methods |
| `allow_headers` | `List[str]` | `["*"]` | Allowed headers |
| `allow_credentials` | `bool` | `False` | Allow credentials |
| `expose_headers` | `List[str]` | `[]` | Headers to expose |
| `max_age` | `int` | `600` | Maximum age of preflight requests |
## Security Module
### JWT Authentication
```python
from apifrom.security import jwt_required
@api(route="/protected", method="GET")
@jwt_required(
secret="your-secret-key",
algorithm="HS256",
token_location="header",
header_name="Authorization",
header_type="Bearer",
verify_exp=True
)
def protected_endpoint(request):
jwt_payload = request.state.jwt_payload
return {"user": jwt_payload.get("sub")}
```
| Parameter | Type | Default | Description |
|-----------|------|---------|-------------|
| `secret` | `str` | Required | The secret key |
| `algorithm` | `str` | `"HS256"` | The algorithm to use |
| `token_location` | `str` | `"header"` | Where to look for the token (header, query, cookie) |
| `header_name` | `str` | `"Authorization"` | Header name |
| `header_type` | `str` | `"Bearer"` | Header type |
| `verify_exp` | `bool` | `True` | Verify token expiration |
| `verify_aud` | `bool` | `False` | Verify audience |
| `verify_iss` | `bool` | `False` | Verify issuer |
| `verify_sub` | `bool` | `False` | Verify subject |
| `verify_jti` | `bool` | `False` | Verify JWT ID |
| `verify_at_hash` | `bool` | `False` | Verify access token hash |
### API Key Authentication
```python
from apifrom.security import api_key_required
@api(route="/api-key-protected", method="GET")
@api_key_required(
api_keys={"api-key-1": ["read"]},
scopes=["read"],
header_name="X-API-Key",
query_param_name=None,
cookie_name=None
)
def api_key_protected_endpoint(request):
api_key = request.state.api_key
return {"api_key": api_key}
```
| Parameter | Type | Default | Description |
|-----------|------|---------|-------------|
| `api_keys` | `Dict[str, List[str]]` | Required | API keys and their scopes |
| `scopes` | `List[str]` | `[]` | Required scopes |
| `header_name` | `str` | `"X-API-Key"` | Header name |
| `query_param_name` | `str` | `None` | Query parameter name |
| `cookie_name` | `str` | `None` | Cookie name |
### Basic Authentication
```python
from apifrom.security import basic_auth_required
@api(route="/basic-auth-protected", method="GET")
@basic_auth_required(
credentials={"user1": "password1"},
realm="My API"
)
def basic_auth_protected_endpoint(request):
username = request.state.username
return {"username": username}
```
| Parameter | Type | Default | Description |
|-----------|------|---------|-------------|
| `credentials` | `Dict[str, str]` | Required | Username and password pairs |
| `realm` | `str` | `"APIFromAnything"` | Realm for WWW-Authenticate header |
## Performance Module
### Caching
```python
from apifrom.performance import cache
@api(route="/expensive-operation", method="GET")
@cache(ttl=60)
def expensive_operation():
# Expensive operation
return {"result": "expensive computation"}
```
| Parameter | Type | Default | Description |
|-----------|------|---------|-------------|
| `ttl` | `int` | `60` | Cache TTL in seconds |
| `key_builder` | `Callable` | `None` | Custom function to build cache keys |
| `key_prefix` | `str` | `None` | Prefix for cache keys |
| `storage` | `str` | `"memory"` | Storage backend (memory, redis) |
| `redis_url` | `str` | `None` | Redis URL (if using redis storage) |
| `invalidate_on_update` | `bool` | `False` | Invalidate cache on update |
| `stale_while_revalidate` | `bool` | `False` | Serve stale data while revalidating |
| `stale_ttl` | `int` | `3600` | Stale data TTL in seconds |
| `vary_by_headers` | `List[str]` | `[]` | Vary cache by headers |
| `vary_by_query_params` | `List[str] | `[]` | Vary cache by query parameters |
### Request Coalescing
```python
from apifrom.performance import coalesce_requests
@api(route="/popular-data", method="GET")
@coalesce_requests(ttl=30, max_wait_time=0.05)
async def get_popular_data():
# Expensive operation
return {"data": "expensive computation result"}
```
| Parameter | Type | Default | Description |
|-----------|------|---------|-------------|
| `ttl` | `int` | `30` | Cache TTL in seconds |
| `max_wait_time` | `float` | `0.05` | Maximum wait time in seconds |
| `key_builder` | `Callable` | `lambda request: request.url.path` | Custom key builder |
### Batch Processing
```python
from apifrom.performance import batch_process
@api(route="/users", method="POST")
@batch_process(max_batch_size=100, max_wait_time=0.1)
async def create_users(user_data_batch):
# Bulk insert all users in the batch
return db.bulk_insert_users(user_data_batch)
```
| Parameter | Type | Default | Description |
|-----------|------|---------|-------------|
| `max_batch_size` | `int` | `100` | Maximum batch size |
| `max_wait_time` | `float` | `0.1` | Maximum wait time in seconds |
| `key_builder` | `Callable` | `lambda request: request.url.path` | Custom key builder |
### Web Decorator
```python
from apifrom.performance import Web
@api(route="/products", method="GET")
@Web.optimize(
cache_ttl=30,
profile=True,
connection_pool=True,
request_coalescing=True,
batch_processing=True,
batch_size=100
)
def get_products():
# Your code here (automatically optimized)
return {"products": [...]}
```
| Parameter | Type | Default | Description |
|-----------|------|---------|-------------|
| `cache_ttl` | `int` | `60` | Cache TTL in seconds |
| `profile` | `bool` | `False` | Enable profiling |
| `connection_pool` | `bool` | `False` | Enable connection pooling |
| `request_coalescing` | `bool` | `False` | Enable request coalescing |
| `batch_processing` | `bool` | `False` | Enable batch processing |
| `batch_size` | `int` | `100` | Batch size |
## Exceptions Module
### Base Exception Classes
#### APIError
Base class for all API errors.
```python
from apifrom.exceptions import APIError
raise APIError(message="An error occurred", status_code=500, details={"error": "details"})
```
| Parameter | Type | Default | Description |
|-----------|------|---------|-------------|
| `message` | `str` | `"An error occurred"` | Error message |
| `status_code` | `int` | `500` | HTTP status code |
| `details` | `Dict` | `None` | Additional error details |
### Common Error Classes
#### BadRequestError
```python
from apifrom.exceptions import BadRequestError
raise BadRequestError(message="Invalid input", details={"field": "name", "error": "Required"})
```
| Parameter | Type | Default | Description |
|-----------|------|---------|-------------|
| `message` | `str` | `"Bad request"` | Error message |
| `details` | `Dict` | `None` | Additional error details |
#### NotFoundError
```python
from apifrom.exceptions import NotFoundError
raise NotFoundError(message="User not found", details={"user_id": 123})
```
| Parameter | Type | Default | Description |
|-----------|------|---------|-------------|
| `message` | `str` | `"Not found"` | Error message |
| `details` | `Dict` | `None` | Additional error details |
#### UnauthorizedError
```python
from apifrom.exceptions import UnauthorizedError
raise UnauthorizedError(message="Authentication required")
```
| Parameter | Type | Default | Description |
|-----------|------|---------|-------------|
| `message` | `str` | `"Unauthorized"` | Error message |
| `details` | `Dict` | `None` | Additional error details |
#### ForbiddenError
```python
from apifrom.exceptions import ForbiddenError
raise ForbiddenError(message="Insufficient permissions")
```
| Parameter | Type | Default | Description |
|-----------|------|---------|-------------|
| `message` | `str` | `"Forbidden"` | Error message |
| `details` | `Dict` | `None` | Additional error details |
## Monitoring Module
### MetricsCollector
```python
from apifrom.monitoring import MetricsCollector
metrics = MetricsCollector()
# Create a counter
counter = metrics.create_counter(
name="requests_total",
description="Total number of requests",
labels=["method", "path"]
)
# Increment the counter
counter.inc(labels={"method": "GET", "path": "/users"})
# Create a gauge
gauge = metrics.create_gauge(
name="active_requests",
description="Number of active requests",
labels=["method"]
)
# Set the gauge value
gauge.set(1, labels={"method": "GET"})
# Create a histogram
histogram = metrics.create_histogram(
name="request_duration_seconds",
description="Request duration in seconds",
labels=["method", "path"],
buckets=[0.1, 0.5, 1.0, 5.0]
)
# Observe a value
histogram.observe(0.2, labels={"method": "GET", "path": "/users"})
```
### MetricsMiddleware
```python
from apifrom.monitoring import MetricsMiddleware
app.add_middleware(
MetricsMiddleware(
collector=metrics,
prefix="api",
include_paths=True,
include_methods=True,
include_status_codes=True
)
)
```
| Parameter | Type | Default | Description |
|-----------|------|---------|-------------|
| `collector` | `MetricsCollector` | Required | The metrics collector |
| `prefix` | `str` | `"api"` | Prefix for metric names |
| `include_paths` | `bool` | `True` | Include paths in labels |
| `include_methods` | `bool` | `True` | Include methods in labels |
| `include_status_codes` | `bool` | `True` | Include status codes in labels |
### PrometheusExporter
```python
from apifrom.monitoring import PrometheusExporter
exporter = PrometheusExporter(collector=metrics)
@api(route="/metrics", method="GET")
def metrics():
return exporter.export()
```
| Parameter | Type | Default | Description |
|-----------|------|---------|-------------|
| `collector` | `MetricsCollector` | Required | The metrics collector |
## Adapters Module
### LambdaAdapter
```python
from apifrom import API
from apifrom.adapters import LambdaAdapter
app = API()
@app.api(route="/hello/{name}", method="GET")
def hello(name: str):
return {"message": f"Hello, {name}!"}
lambda_adapter = LambdaAdapter(app)
def handler(event, context):
return lambda_adapter.handle(event, context)
```
| Parameter | Type | Default | Description |
|-----------|------|---------|-------------|
| `app` | `API` | Required | The API instance |
### VercelAdapter
```python
from apifrom import API
from apifrom.adapters import VercelAdapter
app = API()
@app.api(route="/api/hello", method="GET")
def hello(name: str = "World"):
return {"message": f"Hello, {name}!"}
vercel_adapter = VercelAdapter(app)
def handler(req):
return vercel_adapter.handle(req)
```
| Parameter | Type | Default | Description |
|-----------|------|---------|-------------|
| `app` | `API` | Required | The API instance |
## Utility Functions
### create_jwt_token
```python
from apifrom.security import create_jwt_token
token = create_jwt_token(
payload={"sub": "user123", "role": "admin"},
secret="your-secret-key",
algorithm="HS256",
expires_delta=3600
)
```
| Parameter | Type | Default | Description |
|-----------|------|---------|-------------|
| `payload` | `Dict` | Required | The JWT payload |
| `secret` | `str` | Required | The secret key |
| `algorithm` | `str` | `"HS256"` | The algorithm to use |
| `expires_delta` | `int` | `None` | Token expiration in seconds |
### invalidate_cache
```python
from apifrom.performance import invalidate_cache
invalidate_cache("user:123")
```
| Parameter | Type | Default | Description |
|-----------|------|---------|-------------|
| `key` | `str` | Required | The cache key to invalidate |
| `storage` | `str` | `"memory"` | Storage backend (memory, redis) |
| `redis_url` | `str` | `None` | Redis URL (if using redis storage) |
### get_performance_metrics
```python
from apifrom.performance import get_performance_metrics
metrics = get_performance_metrics()
```
## Constants
### HTTP Methods
```python
from apifrom.constants import HTTPMethod
HTTPMethod.GET # "GET"
HTTPMethod.POST # "POST"
HTTPMethod.PUT # "PUT"
HTTPMethod.DELETE # "DELETE"
HTTPMethod.PATCH # "PATCH"
HTTPMethod.HEAD # "HEAD"
HTTPMethod.OPTIONS # "OPTIONS"
```
### Status Codes
```python
from apifrom.constants import StatusCode
StatusCode.OK # 200
StatusCode.CREATED # 201
StatusCode.ACCEPTED # 202
StatusCode.NO_CONTENT # 204
StatusCode.BAD_REQUEST # 400
StatusCode.UNAUTHORIZED # 401
StatusCode.FORBIDDEN # 403
StatusCode.NOT_FOUND # 404
StatusCode.METHOD_NOT_ALLOWED # 405
StatusCode.CONFLICT # 409
StatusCode.GONE # 410
StatusCode.UNPROCESSABLE_ENTITY # 422
StatusCode.TOO_MANY_REQUESTS # 429
StatusCode.INTERNAL_SERVER_ERROR # 500
StatusCode.NOT_IMPLEMENTED # 501
StatusCode.BAD_GATEWAY # 502
StatusCode.SERVICE_UNAVAILABLE # 503
StatusCode.GATEWAY_TIMEOUT # 504
```
## Plugin System
The plugin system allows you to extend and customize the functionality of your API.
### Plugin Class
The `Plugin` abstract base class defines the interface that all plugins must implement.
```python
from apifrom.plugins import Plugin
```
#### Methods
##### `get_metadata`
Get the metadata for this plugin.
```python
def get_metadata(self) -> PluginMetadata:
"""
Get the metadata for this plugin.
Returns:
The plugin metadata
"""
pass
```
##### `get_config`
Get the configuration for this plugin.
```python
def get_config(self) -> PluginConfig:
"""
Get the configuration for this plugin.
Returns:
The plugin configuration
"""
return PluginConfig()
```
##### `initialize`
Initialize the plugin.
```python
def initialize(self, api: API) -> None:
"""
Initialize the plugin.
Args:
api: The API instance
"""
self._api = api
self._state = PluginState.INITIALIZED
```
##### `activate`
Activate the plugin.
```python
def activate(self) -> None:
"""
Activate the plugin.
"""
self._state = PluginState.ACTIVE
```
##### `deactivate`
Deactivate the plugin.
```python
def deactivate(self) -> None:
"""
Deactivate the plugin.
"""
self._state = PluginState.DISABLED
```
##### `shutdown`
Shutdown the plugin.
```python
def shutdown(self) -> None:
"""
Shutdown the plugin.
"""
pass
```
##### `pre_request`
Process a request before it is handled by the API.
```python
async def pre_request(self, request: Request) -> Request:
"""
Process a request before it is handled by the API.
Args:
request: The request object
Returns:
The processed request object
"""
return request
```
##### `post_response`
Process a response after it is generated by the API.
```python
async def post_response(self, response: Response, request: Request) -> Response:
"""
Process a response after it is generated by the API.
Args:
response: The response object
request: The request object
Returns:
The processed response object
"""
return response
```
##### `on_error`
Handle an error that occurred during request processing.
```python
async def on_error(self, error: Exception, request: Request) -> Optional[Response]:
"""
Handle an error that occurred during request processing.
Args:
error: The error that occurred
request: The request object
Returns:
A response object, or None to let the API handle the error
"""
return None
```
##### `on_event`
Handle an event emitted by the plugin system.
```python
async def on_event(self, event: PluginEvent, **kwargs) -> None:
"""
Handle an event emitted by the plugin system.
Args:
event: The event that occurred
**kwargs: Additional event data
"""
pass
```
##### `register_hook`
Register a callback for a hook.
```python
def register_hook(self, hook: PluginHook, callback: Callable, priority: int = PluginPriority.NORMAL.value) -> None:
"""
Register a callback for a hook.
Args:
hook: The hook to register for
callback: The callback function
priority: The priority of the callback
"""
hook.register(callback, priority)
```
##### `unregister_hook`
Unregister a callback from a hook.
```python
def unregister_hook(self, hook: PluginHook, callback: Callable) -> None:
"""
Unregister a callback from a hook.
Args:
hook: The hook to unregister from
callback: The callback function
"""
hook.unregister(callback)
```
### PluginManager Class
The `PluginManager` class manages the registration and execution of plugins.
```python
from apifrom.plugins.base import PluginManager
```
#### Methods
##### `register_plugin`
Register a plugin with the manager.
```python
def register_plugin(self, plugin: Plugin) -> None:
"""
Register a plugin with the manager.
Args:
plugin: The plugin to register
Raises:
PluginDependencyError: If a plugin dependency cannot be satisfied
PluginConfigurationError: If the plugin configuration is invalid
"""
pass
```
##### `register`
Register a plugin with the manager (alias for register_plugin).
```python
def register(self, plugin: Plugin) -> None:
"""
Register a plugin with the manager (alias for register_plugin).
Args:
plugin: The plugin to register
"""
self.register_plugin(plugin)
```
##### `unregister_plugin`
Unregister a plugin from the manager.
```python
def unregister_plugin(self, plugin_name: str) -> None:
"""
Unregister a plugin from the manager.
Args:
plugin_name: The name of the plugin to unregister
Raises:
ValueError: If the plugin is not registered
PluginDependencyError: If other plugins depend on this plugin
"""
pass
```
##### `unregister`
Unregister a plugin from the manager (alias for unregister_plugin).
```python
def unregister(self, plugin_name: str) -> None:
"""
Unregister a plugin from the manager (alias for unregister_plugin).
Args:
plugin_name: The name of the plugin to unregister
"""
self.unregister_plugin(plugin_name)
```
##### `get_plugin`
Get a plugin by name.
```python
def get_plugin(self, plugin_name: str) -> Plugin:
"""
Get a plugin by name.
Args:
plugin_name: The name of the plugin
Returns:
The plugin instance
Raises:
ValueError: If the plugin is not registered
"""
pass
```
##### `get_plugins_by_tag`
Get plugins by tag.
```python
def get_plugins_by_tag(self, tag: str) -> List[Plugin]:
"""
Get plugins by tag.
Args:
tag: The tag to filter by
Returns:
A list of plugins with the specified tag
"""
pass
```
##### `get_plugins_by_state`
Get plugins by state.
```python
def get_plugins_by_state(self, state: PluginState) -> List[Plugin]:
"""
Get plugins by state.
Args:
state: The state to filter by
Returns:
A list of plugins in the specified state
"""
pass
```
##### `register_hook`
Register a new hook.
```python
def register_hook(self, name: str, description: str = "") -> PluginHook:
"""
Register a new hook.
Args:
name: The name of the hook
description: A description of the hook
Returns:
The hook instance
"""
pass
```
##### `get_hook`
Get a hook by name.
```python
def get_hook(self, name: str) -> Optional[PluginHook]:
"""
Get a hook by name.
Args:
name: The name of the hook
Returns:
The hook instance, or None if not found
"""
pass
```
### PluginMetadata Class
The `PluginMetadata` class stores metadata about a plugin.
```python
from apifrom.plugins.base import PluginMetadata
```
#### Constructor Parameters
| Parameter | Type | Default | Description |
|-----------|------|---------|-------------|
| `name` | `str` | Required | The name of the plugin |
| `version` | `str` | Required | The version of the plugin |
| `description` | `str` | `""` | A description of the plugin |
| `author` | `str` | `""` | The author of the plugin |
| `website` | `str` | `""` | The website of the plugin |
| `license` | `str` | `""` | The license of the plugin |
| `dependencies` | `List[str]` | `None` | A list of plugin names that this plugin depends on |
| `tags` | `List[str]` | `None` | A list of tags for the plugin |
### PluginConfig Class
The `PluginConfig` class stores configuration options for a plugin.
```python
from apifrom.plugins.base import PluginConfig
```
#### Constructor Parameters
| Parameter | Type | Default | Description |
|-----------|------|---------|-------------|
| `defaults` | `Dict[str, Any]` | `None` | Default values for configuration options |
| `schema` | `Dict[str, Any]` | `None` | JSON Schema for validating configuration options |
#### Methods
##### `get`
Get a configuration value.
```python
def get(self, key: str, default: Any = None) -> Any:
"""
Get a configuration value.
Args:
key: The configuration key
default: The default value to return if the key is not found
Returns:
The configuration value
"""
pass
```
##### `set`
Set a configuration value.
```python
def set(self, key: str, value: Any) -> None:
"""
Set a configuration value.
Args:
key: The configuration key
value: The configuration value
"""
pass
```
##### `update`
Update multiple configuration values.
```python
def update(self, values: Dict[str, Any]) -> None:
"""
Update multiple configuration values.
Args:
values: A dictionary of configuration values to update
"""
pass
```
##### `validate`
Validate the configuration against the schema.
```python
def validate(self) -> bool:
"""
Validate the configuration against the schema.
Returns:
True if the configuration is valid, False otherwise
"""
pass
```
### PluginHook Class
The `PluginHook` class provides a way for plugins to register callbacks for specific hooks.
```python
from apifrom.plugins.base import PluginHook
```
#### Constructor Parameters
| Parameter | Type | Default | Description |
|-----------|------|---------|-------------|
| `name` | `str` | Required | The name of the hook |
| `description` | `str` | `""` | A description of the hook |
#### Methods
##### `register`
Register a callback for this hook.
```python
def register(self, callback: Callable[..., T], priority: int = PluginPriority.NORMAL.value) -> None:
"""
Register a callback for this hook.
Args:
callback: The callback function
priority: The priority of the callback (higher priority callbacks are executed first)
"""
pass
```
##### `unregister`
Unregister a callback from this hook.
```python
def unregister(self, callback: Callable[..., T]) -> None:
"""
Unregister a callback from this hook.
Args:
callback: The callback function to unregister
"""
pass
```
### PluginEvent Enum
The `PluginEvent` enum defines events that can be emitted by the plugin system.
```python
from apifrom.plugins.base import PluginEvent
```
#### Values
| Value | Description |
|-------|-------------|
| `PLUGIN_REGISTERED` | A plugin has been registered |
| `PLUGIN_INITIALIZED` | A plugin has been initialized |
| `PLUGIN_ACTIVATED` | A plugin has been activated |
| `PLUGIN_DISABLED` | A plugin has been disabled |
| `PLUGIN_ERROR` | An error occurred in a plugin |
| `SERVER_STARTING` | The server is starting |
| `SERVER_STARTED` | The server has started |
| `SERVER_STOPPING` | The server is stopping |
| `SERVER_STOPPED` | The server has stopped |
| `REQUEST_RECEIVED` | A request has been received |
| `RESPONSE_SENT` | A response has been sent |
| `ERROR_OCCURRED` | An error occurred during request processing |
### PluginState Enum
The `PluginState` enum defines the possible states for plugins.
```python
from apifrom.plugins.base import PluginState
```
#### Values
| Value | Description |
|-------|-------------|
| `REGISTERED` | The plugin is registered but not initialized |
| `INITIALIZED` | The plugin is initialized but not active |
| `ACTIVE` | The plugin is active and processing requests |
| `DISABLED` | The plugin is disabled and not processing requests |
| `ERROR` | The plugin encountered an error |
### PluginPriority Enum
The `PluginPriority` enum defines priority levels for plugins.
```python
from apifrom.plugins.base import PluginPriority
```
#### Values
| Value | Description |
|-------|-------------|
| `HIGHEST` | Highest priority (100) |
| `HIGH` | High priority (75) |
| `NORMAL` | Normal priority (50) |
| `LOW` | Low priority (25) |
| `LOWEST` | Lowest priority (0) |
### Built-in Plugins
#### LoggingPlugin
The `LoggingPlugin` logs requests and responses.
```python
from apifrom.plugins import LoggingPlugin
```
##### Constructor Parameters
| Parameter | Type | Default | Description |
|-----------|------|---------|-------------|
| `logger` | `Optional[logging.Logger]` | `None` | The logger to use (defaults to a new logger) |
| `level` | `int` | `logging.INFO` | The logging level |
| `log_request_body` | `bool` | `False` | Whether to log request bodies |
| `log_response_body` | `bool` | `False` | Whether to log response bodies |
| `log_headers` | `bool` | `False` | Whether to log headers |
| `exclude_paths` | `list` | `None` | Paths to exclude from logging |
| `exclude_methods` | `list` | `None` | HTTP methods to exclude from logging |
## 🔄 Async Support
APIFromAnything provides comprehensive support for asynchronous programming using Python's `async`/`await` syntax. This allows you to build high-performance APIs that can handle many concurrent requests efficiently.
### Async API Endpoints
You can define asynchronous API endpoints using the `async def` syntax:
```python
from apifrom import API, api
import asyncio
app = API(title="Async API")
@api(route="/async-hello/{name}", method="GET")
async def async_hello(name: str, delay: float = 1.0) -> dict:
"""Say hello asynchronously after a delay."""
await asyncio.sleep(delay) # Non-blocking sleep
return {"message": f"Hello, {name}!", "delay": delay}
@api(route="/parallel", method="GET")
async def parallel_operations():
"""Execute multiple operations in parallel."""
# Create tasks for concurrent execution
task1 = asyncio.create_task(async_operation_1())
task2 = asyncio.create_task(async_operation_2())
task3 = asyncio.create_task(async_operation_3())
# Wait for all tasks to complete
results = await asyncio.gather(task1, task2, task3)
return {
"operation1": results[0],
"operation2": results[1],
"operation3": results[2]
}
async def async_operation_1():
await asyncio.sleep(1)
return "Result 1"
async def async_operation_2():
await asyncio.sleep(1)
return "Result 2"
async def async_operation_3():
await asyncio.sleep(1)
return "Result 3"
```
### Async Middleware
Middleware components can also be asynchronous:
```python
from apifrom import API
from apifrom.middleware import Middleware
from apifrom.core.request import Request
from apifrom.core.response import Response
from typing import Callable, Awaitable
import time
class AsyncTimingMiddleware(Middleware):
async def dispatch(
self,
request: Request,
call_next: Callable[[Request], Awaitable[Response]]
) -> Response:
start_time = time.time()
# Process the request through the next middleware or endpoint
response = await call_next(request)
# Calculate processing time
processing_time = time.time() - start_time
# Add timing header to response
response.headers["X-Processing-Time"] = f"{processing_time:.6f} seconds"
return response
# Create an API instance
app = API()
# Add async middleware to the API
app.add_middleware(AsyncTimingMiddleware())
```
### Async Database Operations
When working with databases, you can use async database libraries for non-blocking database operations:
```python
from apifrom import API, api
import asyncpg
app = API(title="Async Database API")
# Database connection pool
db_pool = None
@app.on_startup
async def setup_database():
global db_pool
db_pool = await asyncpg.create_pool(
"postgresql://user:password@localhost/database"
)
@app.on_shutdown
async def close_database():
await db_pool.close()
@api(route="/users", method="GET")
async def get_users():
"""Get all users from the database."""
async with db_pool.acquire() as connection:
rows = await connection.fetch("SELECT id, name, email FROM users")
return [dict(row) for row in rows]
@api(route="/users/{user_id}", method="GET")
async def get_user(user_id: int):
"""Get a user by ID."""
async with db_pool.acquire() as connection:
row = await connection.fetchrow(
"SELECT id, name, email FROM users WHERE id = $1",
user_id
)
if not row:
return {"error": "User not found"}, 404
return dict(row)
@api(route="/users", method="POST")
async def create_user(name: str, email: str):
"""Create a new user."""
async with db_pool.acquire() as connection:
user_id = await connection.fetchval(
"INSERT INTO users (name, email) VALUES ($1, $2) RETURNING id",
name, email
)
return {"id": user_id, "name": name, "email": email}
```