OxAPY is a Python HTTP server library built in Rust using PyO3/maturin. It provides a fast, feature-rich web framework with routing, middleware, sessions, JWT authentication, and static file serving.
# Development build (installs in editable mode)
maturin dev --release
# Or use the build script
./build.sh
# Build wheel for distribution
maturin build --release# Run all tests
pytest -vv tests
# Run a single test file
pytest -vv tests/test_http_server.py
# Run a single test
pytest -vv tests/test_http_server.py::test_ping_endpoint
# Run with specific test markers
pytest -vv tests -k "test_name_pattern"# Format Rust code
cargo fmt
# Run clippy lints
cargo clippy --all-targets --all-features
# Check Rust code
cargo check --all-targetsThe project uses pre-commit hooks defined in .pre-commit-config.yaml:
- Rust:
cargo fmtandcargo clippy - Python:
maturin develop --releaseandpytest -vv tests
# Install pre-commit hooks
pre-commit install
# Run all hooks manually
pre-commit run --all-files- Rust source:
src/directory with modular.rsfiles - Python tests:
tests/directory
-
Imports: Use absolute imports from crate root
use crate::routing::*; use crate::middleware::Middleware;
-
PyO3 Patterns:
- Use
#[pyclass]for Python-exposed structs - Use
#[pymethods]for methods callable from Python - Use
#[gen_stub_pyclass]and#[gen_stub_pymethods]for stub generation - Use
#[new]for constructors - Use
#[pyo3(signature=(...))]for keyword arguments
- Use
-
Naming:
- Structs/Enums:
PascalCase - Functions/Methods:
snake_case - Constants:
SCREAMING_SNAKE_CASE
- Structs/Enums:
-
Error Handling:
- Return
PyResult<T>for functions that can raise Python exceptions - Use the
IntoPyExceptiontrait for custom error types - Use
pyo3::exceptions::*for standard Python exceptions
- Return
-
Documentation:
- Use doc comments
///for public APIs - Include Args, Returns, and Example sections in docstrings
- Use doc comments
-
Concurrency:
- Use
Arc<T>for shared ownership - Use
tokiofor async runtime withpyo3-async-runtimes
- Use
-
Imports: Follow standard Python import conventions
from oxapy import HttpServer, Router, get, post, Status, Response
-
Type Hints: Use type hints for function signatures
@get("/hello/{name}") def hello(_request, name: str) -> dict: return {"message": f"Hello, {name}!"}
-
Handler Functions:
- First argument is always
request - Path parameters are passed as keyword arguments
- Return type can be
str,dict,Response, orStatus
- First argument is always
- pyo3: Python bindings (>=0.27.0)
- pyo3-async-runtimes: Async support with tokio-runtime
- tokio: Async runtime
- hyper: HTTP server
- matchit: URL routing
- serde/serde_json: Serialization
- minijinja/tera: Template engines
- jsonwebtoken: JWT authentication
Tests use a session-scoped fixture that starts a real HTTP server:
@pytest.fixture(scope="session")
def oxapy_server(static_files_dir):
thread = threading.Thread(target=lambda: main(static_files_dir), daemon=True)
thread.start()
time.sleep(2) # Wait for server to start
yield "http://127.0.0.1:9999"Use requests library for HTTP assertions in tests.
-
Creating a Router:
# Create router and register decorated handlers with .routes() router = Router("/api/v1") router.routes([handler1, handler2]) # Or use .route() for single handler router.route(handler)
-
Middleware:
def auth_middleware(request, next, **kw): if "authorization" not in request.headers: return Status.UNAUTHORIZED return next(request, **kw)
-
Response Types:
- Return
strfor plain text - Return
dictfor JSON (auto-serialized) - Return
Responseobject for custom responses - Return
Statusfor error codes
- Return
- The project uses
ahashinstead of standardHashMapfor performance - Path parameters in routes use
{param_name}syntax - Middleware applies to all routes registered after it within the same router; use separate
Routerinstances to isolate middleware groups - Multiple routers can be attached to the server and are checked in order until a matching route is found
- Application state is shared via
request.app_data