You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Side-effect dependencies (auth guards, audit writers) that run before the handler — return values are discarded; `HTTPException` short-circuits the request:
207
+
208
+
```python
209
+
from hawkapi import Depends
210
+
211
+
asyncdefaudit(request): ...
212
+
213
+
@app.get("/admin", dependencies=[Depends(audit)])
214
+
asyncdefadmin(): ...
215
+
```
216
+
217
+
Router-level is also supported: `Router(dependencies=[Depends(audit)])`.
218
+
201
219
#### DI Introspection
202
220
203
221
Inspect the container at runtime or export a Mermaid dependency graph:
@@ -304,6 +341,8 @@ class AuthMiddleware(Middleware):
304
341
305
342
Middleware is registered globally via `app.add_middleware()`. Each entry is stored as a `MiddlewareEntry` dataclass holding the middleware class and its kwargs, then compiled into an onion-model pipeline at startup.
306
343
344
+
See also: [Bulkhead](#bulkhead) — named async concurrency isolator living in `hawkapi.middleware.bulkhead`.
345
+
307
346
### Security
308
347
309
348
```python
@@ -333,6 +372,26 @@ async def admin_panel():
333
372
return {"secret": "data"}
334
373
```
335
374
375
+
#### OAuth2 Scopes
376
+
377
+
Fine-grained scope enforcement with OpenAPI `operation.security` reflection:
378
+
379
+
```python
380
+
from hawkapi import OAuth2PasswordBearer, Security, SecurityScopes
Both HTTP (`status.HTTP_200_OK`, `status.HTTP_422_UNPROCESSABLE_ENTITY`, …) and WebSocket (`status.WS_1008_POLICY_VIOLATION`, …) constants are available.
Providers: `StaticFlagProvider`, `EnvFlagProvider`, `FileFlagProvider` (JSON/TOML/YAML with mtime hot-reload). Use when you need to gate features per environment or roll out incrementally without a deployment. See [docs/guide/feature-flags.md](docs/guide/feature-flags.md).
620
+
621
+
### GraphQL
622
+
623
+
Thin GraphQL-over-HTTP adapter with GraphiQL UI served to browsers. Zero runtime deps on the default path — `graphql-core` and `strawberry` are imported lazily only when the adapter is used:
624
+
625
+
```python
626
+
from hawkapi.graphql.adapters import from_graphql_core
Adapters: `from_graphql_core`, `from_strawberry`. Use when you need a GraphQL API alongside REST without adding a separate framework. See [docs/guide/graphql.md](docs/guide/graphql.md).
634
+
635
+
### gRPC
636
+
637
+
Thin gRPC integration with ASGI lifespan-tied lifecycle — the gRPC server starts and stops with the app:
Built-in `HawkAPIObservabilityInterceptor` adds structured logs and Prometheus metrics to every RPC. TLS via `ssl_credentials=`. Install: `pip install hawkapi[grpc]`. Use when you need gRPC and HTTP APIs from a single process. See [docs/guide/grpc.md](docs/guide/grpc.md).
657
+
658
+
### Bulkhead
659
+
660
+
Named async concurrency isolator — caps simultaneous in-flight requests per named pool to prevent one slow resource from exhausting the entire process:
661
+
662
+
```python
663
+
from hawkapi.middleware.bulkhead import bulkhead
664
+
665
+
@app.get("/export")
666
+
@bulkhead("exports", max_concurrent=4)
667
+
asyncdefexport(): ...
668
+
```
669
+
670
+
Context-manager form also supported. Backends: `LocalBulkheadBackend` (default, `asyncio.Semaphore` per name) and `RedisBulkheadBackend` (distributed, hash + lease-TTL). Optional Prometheus metrics. Use when you need hard concurrency caps per operation type. See [docs/guide/bulkhead.md](docs/guide/bulkhead.md).
671
+
672
+
### Free-threaded Python 3.13
673
+
674
+
HawkAPI ships experimental `cp313t-cp313t` wheels built via cibuildwheel for the no-GIL CPython 3.13 free-threaded build (PEP 703):
675
+
676
+
```python
677
+
from hawkapi._threading importFREE_THREADED, maybe_thread_lock, maybe_async_lock
678
+
679
+
# FREE_THREADED is True only on a no-GIL 3.13t interpreter
680
+
lock = maybe_thread_lock() # real threading.Lock on 3.13t, no-op elsewhere
681
+
alock = maybe_async_lock() # real asyncio.Lock on 3.13t, no-op elsewhere
682
+
```
683
+
684
+
`maybe_thread_lock()` and `maybe_async_lock()` let library code be PEP 703-aware without branching on every call site. Use when running HawkAPI under `python3.13t` for CPU-bound workloads that benefit from true parallelism. See [docs/guide/free-threaded.md](docs/guide/free-threaded.md).
685
+
686
+
---
687
+
525
688
## Production Features
526
689
527
690
### Health Probes
@@ -817,24 +980,38 @@ hawkapi dev app:app
817
980
hawkapi dev app:app --host 0.0.0.0 --port 3000
818
981
819
982
# Detect API breaking changes
820
-
hawkapi diff app:app --base openapi-v1.json
983
+
hawkapi diff old_app:app new_app:app
821
984
822
985
# Lint OpenAPI spec
823
986
hawkapi check app:app
824
987
825
988
# Generate API changelog
826
-
hawkapi changelog app:app --base openapi-v1.json
989
+
hawkapi changelog old_app:app new_app:app
827
990
828
991
# Scaffold a new project
829
992
hawkapi new myproject
830
993
hawkapi new myproject --docker
831
994
832
995
# Initialize config files in current directory
833
996
hawkapi init
997
+
998
+
# Generate a TypeScript or Python client SDK from OpenAPI
hawkapi migrate path/to/fastapi_project --output ./migrated # write to separate directory
834
1007
```
835
1008
836
1009
`hawkapi init` creates `.env` and `.env.example` files with commented-out HawkAPI configuration templates. Existing files are skipped.
837
1010
1011
+
`hawkapi gen-client` generates a zero-dependency client: native `fetch` for TypeScript, msgspec-backed for Python. Source can be a live app (`--app module:attr`) or a saved spec file (`--spec openapi.json`).
1012
+
1013
+
`hawkapi migrate` uses AST rewriting (libcst) to replace FastAPI imports, decorators, and patterns with their HawkAPI equivalents. See [docs/guide/migration-from-fastapi.md](docs/guide/migration-from-fastapi.md).
1014
+
838
1015
---
839
1016
840
1017
## Configuration
@@ -905,6 +1082,8 @@ Response headers use `CaseInsensitiveDict` — lookups like `response.headers["c
905
1082
906
1083
## Benchmarks
907
1084
1085
+
> **Note:** The numbers below are local dev measurements on Apple M3 Pro. The canonical competitive comparison (Linux CI, head-to-head against FastAPI/Litestar/BlackSheep/Starlette/Sanic) is the table at the top of this README.
1086
+
908
1087
Tested on Apple M3 Pro, Python 3.13, msgspec 0.20. ASGI-level benchmarks (no HTTP server overhead — pure framework performance).
0 commit comments