Core Conceptsο
This document explains the fundamental concepts and components of the APIFromAnything library.
API Classο
The API class is the main entry point for creating an API. It serves as a container for your API endpoints and provides methods for configuring and running your API.
from apifrom import API
app = API(
title="My API",
description="A powerful API built with APIFromAnything",
version="1.0.0",
docs_url="/docs",
openapi_url="/openapi.json",
redoc_url="/redoc",
debug=True
)
Key Propertiesο
title: The name of your API, displayed in the documentation
description: A detailed description of your API
version: The version of your API
docs_url: The URL path for the Swagger UI documentation
openapi_url: The URL path for the OpenAPI schema
redoc_url: The URL path for the ReDoc documentation
debug: Enable debug mode for detailed error messages
Key Methodsο
run(): Start the API server
add_middleware(): Add a middleware component to the API
mount(): Mount a sub-application at a specific path
include_router(): Include a router in the API
API Decoratorο
The @api decorator is used to transform a Python function into an API endpoint. It handles routing, request parsing, validation, and response serialization.
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:
# Function implementation
return {"id": user_id, "name": "John Doe"}
Key Parametersο
route: The URL path for the endpoint, can include path parameters
method: The HTTP method (GET, POST, PUT, DELETE, etc.)
tags: Tags for organizing endpoints in the documentation
summary: A brief summary of the endpoint
description: A detailed description of the endpoint
response_model: The expected response model
status_code: The HTTP status code for successful responses
deprecated: Mark the endpoint as deprecated
include_in_schema: Include the endpoint in the OpenAPI schema
Request and Responseο
APIFromAnything provides Request and Response classes for handling HTTP requests and responses.
Requestο
The Request class represents an HTTP request and provides methods for accessing request data.
from apifrom.core.request import Request
@api(route="/echo", method="POST")
def echo(request: Request) -> dict:
# Access request data
body = request.json()
headers = request.headers
query_params = request.query_params
path_params = request.path_params
cookies = request.cookies
client_ip = request.client.host
return {
"body": body,
"headers": dict(headers),
"query_params": dict(query_params),
"path_params": dict(path_params),
"cookies": dict(cookies),
"client_ip": client_ip
}
Responseο
The Response class represents an HTTP response and allows you to customize the response.
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"},
media_type="application/json"
)
Routerο
The Router class allows you to organize your API endpoints into groups.
from apifrom import API, Router, api
app = API()
# Create a router for user-related endpoints
user_router = Router(
prefix="/users",
tags=["users"],
responses={404: {"description": "User not found"}}
)
# Add endpoints to the router
@user_router.api(route="/{user_id}", method="GET")
def get_user(user_id: int) -> dict:
return {"id": user_id, "name": "John Doe"}
@user_router.api(route="/", method="POST")
def create_user(name: str, email: str) -> dict:
return {"id": 123, "name": name, "email": email}
# Include the router in the API
app.include_router(user_router)
Middlewareο
Middleware components process requests and responses before and after they reach your API endpoints. They can be used for authentication, logging, error handling, and more.
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
# Create a custom middleware
class LoggingMiddleware(Middleware):
async def dispatch(
self,
request: Request,
call_next: Callable[[Request], Awaitable[Response]]
) -> Response:
print(f"Request: {request.method} {request.url.path}")
# Process the request through the next middleware or endpoint
response = await call_next(request)
print(f"Response: {response.status_code}")
return response
# Add the middleware to the API
app = API()
app.add_middleware(LoggingMiddleware())
Type Validationο
APIFromAnything uses Python type hints and Pydantic models for request validation.
Basic Type Validationο
@api(route="/users", method="POST")
def create_user(
name: str,
email: str,
age: int,
is_active: bool = True
) -> dict:
return {
"name": name,
"email": email,
"age": age,
"is_active": is_active
}
Advanced Type Validation with Pydanticο
from enum import Enum
from typing import List, Optional
from pydantic import BaseModel, Field, EmailStr
class UserRole(str, Enum):
ADMIN = "admin"
USER = "user"
GUEST = "guest"
class Address(BaseModel):
street: str
city: str
country: str
postal_code: str
class User(BaseModel):
name: str = Field(..., min_length=2, max_length=50)
email: EmailStr
age: int = Field(..., ge=18, le=120)
role: UserRole = UserRole.USER
tags: List[str] = []
address: Optional[Address] = None
@api(route="/users", method="POST")
def create_user(user: User) -> dict:
return user.dict()
Asynchronous Supportο
APIFromAnything supports both synchronous and asynchronous functions.
import asyncio
from apifrom import API, api
app = API()
@api(route="/sync", method="GET")
def sync_endpoint() -> dict:
# Synchronous function
return {"message": "Sync endpoint"}
@api(route="/async", method="GET")
async def async_endpoint() -> dict:
# Asynchronous function
await asyncio.sleep(0.1)
return {"message": "Async endpoint"}
Plugin Systemο
The plugin system allows you to extend and customize the functionality of your API.
from apifrom import API, Plugin
from apifrom.plugins.base import PluginMetadata
# Create a custom plugin
class TimingPlugin(Plugin):
def get_metadata(self) -> PluginMetadata:
return PluginMetadata(
name="timing",
version="1.0.0",
description="Measures request execution time"
)
async def pre_request(self, request):
request.state.start_time = time.time()
return request
async def post_response(self, response, request):
duration = time.time() - request.state.start_time
response.headers["X-Execution-Time"] = f"{duration:.4f}s"
return response
# Register the plugin
app = API()
app.plugin_manager.register(TimingPlugin())
Serverless Adaptersο
APIFromAnything includes adapters for popular serverless platforms.
from apifrom import API, api
from apifrom.adapters import LambdaAdapter
# Create an API
app = API(title="Serverless API")
@api(route="/hello/{name}", method="GET")
def hello(name: str):
return {"message": f"Hello, {name}!"}
# Create a Lambda handler
lambda_adapter = LambdaAdapter(app)
def handler(event, context):
return lambda_adapter.handle(event, context)
OpenAPI Documentationο
APIFromAnything automatically generates OpenAPI documentation for your API.
from apifrom import API, api
app = API(
title="My API",
description="API description",
version="1.0.0",
docs_url="/docs", # Swagger UI
openapi_url="/openapi.json", # OpenAPI schema
redoc_url="/redoc" # ReDoc
)
@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
)
def get_user(user_id: int) -> dict:
"""
Get a user by ID.
Args:
user_id: The ID of the user to retrieve
Returns:
User information
"""
return {"id": user_id, "name": "John Doe"}
Visit http://localhost:8000/docs to see the Swagger UI documentation, http://localhost:8000/redoc for ReDoc, or http://localhost:8000/openapi.json for the raw OpenAPI schema.