Skip to main content

FastAPI JSON-RPC 2.0 + OpenRPC 1.0 service discovery plugin

Project description

fastapi-openrpc

PyPI version Python versions License

Declarative JSON-RPC 2.0 interface and OpenRPC 1.0 service discovery for FastAPI applications.

Features

  • Declarative Registration@method() decorator with automatic JSON Schema inference
  • OpenRPC Service DiscoveryGET /openrpc.json returns complete OpenRPC document
  • Pydantic Support — Automatic schema generation with $ref references
  • RpcContext Propagation — Secure caller context injection via FastAPI Depends()
  • HMAC Authentication — Built-in signature verification with Nonce replay protection
  • Role-Based Authorization — Method-level role declarations with composition semantics

Installation

pip install fastapi-openrpc

Optional dependencies:

# Redis support (Nonce replay protection)
pip install fastapi-openrpc[redis]

# Development dependencies
pip install fastapi-openrpc[dev]

Quick Start

from fastapi import FastAPI
from fastapi_openrpc import OpenRpcRouter, RpcContext, method

app = FastAPI()

openrpc_router = OpenRpcRouter(
    title="My API",
    version="1.0.0",
    description="My JSON-RPC service",
)

@method(name="getUser")
async def get_user(ctx: RpcContext, user_id: str) -> dict:
    """Get user information by user_id."""
    return {"id": user_id, "name": "Alice", "roles": ctx.roles}

@method(name="listUsers")
async def list_users(ctx: RpcContext, limit: int = 10) -> list[dict]:
    """Return a list of users."""
    return [{"id": i, "name": f"User {i}"} for i in range(limit)]

app.include_router(openrpc_router)

After starting the server, access GET /openrpc.json to view the OpenRPC service document.

Authentication

HMAC Authentication

from fastapi_openrpc.authentication import HMACAuthentication

auth = HMACAuthentication(secret_key="your-secret-key")
openrpc_router = OpenRpcRouter(
    authentication=auth,
)

Nonce Replay Protection

auth = HMACAuthentication(
    secret_key="your-secret-key",
    enable_nonce=True,
    redis_url="redis://localhost:6379",
    nonce_ttl=3600,
    redis_required=True,       # Reject requests when Redis is unavailable
    connect_timeout=2.0,      # Redis connection timeout (seconds)
    operation_timeout=5.0,     # Redis operation timeout (seconds)
    cleanup_timeout=2.0,      # Redis cleanup timeout (seconds)
)

Header format:

{
  "roles": ["admin"],
  "nonce": "550e8400-e29b-41d4-a716-446655440000"
}

Authorization

from fastapi_openrpc import Require

@method(name="adminAction", required_roles=["admin"])
async def admin_action(ctx: RpcContext) -> dict:
    """Admin only."""
    return {"status": "done"}

@method(name="editContent", required_roles=["editor", "admin"], require=Require.ALL)
async def edit_content(ctx: RpcContext) -> dict:
    """Requires both editor and admin roles."""
    return {"status": "edited"}

Error Handling

from fastapi_openrpc import InvalidParams, MethodNotFound

@method(name="divide")
async def divide(ctx: RpcContext, a: float, b: float) -> float:
    if b == 0:
        raise InvalidParams("Division by zero")
    return a / b

Built-in error codes:

Error Code
Parse error -32700
Invalid Request -32600
Method Not Found -32601
Invalid Params -32602
Internal Error -32603
Forbidden -32000
Replay Detected -32002

Library reserves -32000 ~ -32099, application custom errors start from -32100.

API Reference

OpenRpcRouter

from concurrent.futures import ThreadPoolExecutor

executor = ThreadPoolExecutor(max_workers=4)
openrpc_router = OpenRpcRouter(
    title="My API",
    version="1.0.0",
    description="...",
    servers=[{"url": "https://api.example.com"}],
    authentication=HMACAuthentication(secret_key="..."),  # Optional
    executor=executor,  # Optional, for sync handler thread pool
)
app.include_router(openrpc_router)

@method() Decorator

@method(
    name="myMethod",           # RPC method name
    tags=["admin"],           # OpenRPC tags
    summary="Short description",
    deprecated=False,
    required_roles=["admin"],  # Required roles
    require=Require.ALL,      # Role composition semantics
)
async def my_handler(ctx: RpcContext, arg1: str, arg2: int = 10) -> dict:
    return {"result": arg1}

Note: ctx: RpcContext is a reserved parameter name for injecting caller context.

Usage Examples

# Call RPC method
curl -X POST http://localhost:8000/ \
  -H "Content-Type: application/json" \
  -d '{"jsonrpc": "2.0", "id": 1, "method": "getUser", "params": {"user_id": "42"}}'

# Service discovery
curl http://localhost:8000/openrpc.json

Documentation

For detailed user documentation, see docs/index.md.

Additional guides:

Contributing

Issues and Pull Requests are welcome.

License

MIT

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

fastapi_openrpc-0.1.4.tar.gz (125.9 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

fastapi_openrpc-0.1.4-py3-none-any.whl (30.6 kB view details)

Uploaded Python 3

File details

Details for the file fastapi_openrpc-0.1.4.tar.gz.

File metadata

  • Download URL: fastapi_openrpc-0.1.4.tar.gz
  • Upload date:
  • Size: 125.9 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.11.6 {"installer":{"name":"uv","version":"0.11.6","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"26.04","id":"resolute","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

File hashes

Hashes for fastapi_openrpc-0.1.4.tar.gz
Algorithm Hash digest
SHA256 4160f554705b0f2450872636dd7453b81730cba87be5543659c332aa7b51da7d
MD5 30d343b1ff5ed9315bc63f3381524326
BLAKE2b-256 72ac92caa95bf6ca425ee8d6371bb2e8c566a0a410cb07ba63ca342e458d2c69

See more details on using hashes here.

File details

Details for the file fastapi_openrpc-0.1.4-py3-none-any.whl.

File metadata

  • Download URL: fastapi_openrpc-0.1.4-py3-none-any.whl
  • Upload date:
  • Size: 30.6 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.11.6 {"installer":{"name":"uv","version":"0.11.6","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"26.04","id":"resolute","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

File hashes

Hashes for fastapi_openrpc-0.1.4-py3-none-any.whl
Algorithm Hash digest
SHA256 70e89340c2a4847d4e5d75dff9b4f2893f0615ca92f8b38de675597821e274ce
MD5 9b95a358b19d0903c71f48fb20ec0197
BLAKE2b-256 cdee4575a94b83ddc4e68ac31d3168f59094f4730d9c9a8d6694d7e08ffa3839

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page