fastapi/lib.rs
1//! Ultra-optimized Rust web framework inspired by FastAPI.
2//!
3//! fastapi_rust provides a type-safe, high-performance web framework with:
4//!
5//! - **Type-driven API design** — Route handlers declare types, framework extracts/validates automatically
6//! - **Dependency injection** — Composable, testable request handling
7//! - **Automatic OpenAPI** — Schema generation from type definitions
8//! - **First-class async** — Built on asupersync for structured concurrency
9//! - **Minimal dependencies** — Only asupersync + serde
10//!
11//! # Role In The System
12//!
13//! `fastapi` is the user-facing facade crate. It re-exports the framework's
14//! core types, macros, and utilities from the sub-crates so applications only
15//! need a single dependency. All real behavior lives in the sub-crates listed
16//! below; this crate exists to provide a cohesive, ergonomic API surface.
17//!
18//! # Quick Start
19//!
20//! ```ignore
21//! use fastapi::prelude::*;
22//!
23//! #[derive(Serialize, Deserialize, JsonSchema)]
24//! struct Item {
25//! id: i64,
26//! name: String,
27//! }
28//!
29//! #[get("/items/{id}")]
30//! async fn get_item(cx: &Cx, id: Path<i64>) -> Json<Item> {
31//! Json(Item { id: id.0, name: "Example".into() })
32//! }
33//!
34//! fn main() {
35//! let app = App::new()
36//! .title("My API")
37//! .route(get_item);
38//!
39//! // Run with asupersync
40//! // asupersync::block_on(app.serve("0.0.0.0:8000"));
41//! }
42//! ```
43//!
44//! # Design Philosophy
45//!
46//! This framework is built with the following principles:
47//!
48//! 1. **Zero-cost abstractions** — No runtime reflection, everything at compile time
49//! 2. **Cancel-correct** — Leverages asupersync's structured concurrency
50//! 3. **Minimal allocations** — Zero-copy parsing where possible
51//! 4. **Familiar API** — FastAPI users will recognize the patterns
52//!
53//! # Crate Structure
54//!
55//! | Crate | Purpose |
56//! |-------|---------|
57//! | `fastapi_core` | Core types (Request, Response, Error), extractors, middleware, DI |
58//! | `fastapi_http` | Zero-copy HTTP/1.1 parser, TCP server, chunked encoding |
59//! | `fastapi_router` | Trie-based router with O(log n) lookups |
60//! | `fastapi_macros` | Procedural macros (`#[get]`, `#[derive(Validate)]`, `#[derive(JsonSchema)]`) |
61//! | `fastapi_openapi` | OpenAPI 3.1 schema types and generation |
62//! | `fastapi_output` | Agent-aware rich console output (optional) |
63//!
64//! # Feature Flags
65//!
66//! | Feature | Default | Description |
67//! |---------|---------|-------------|
68//! | `output` | **yes** | Rich console output with agent detection (includes `fastapi-output/rich`) |
69//! | `output-plain` | no | Plain-text-only output (smaller binary, no ANSI codes) |
70//! | `full` | no | All output features including every theme and component |
71//!
72//! ## Sub-crate Feature Flags
73//!
74//! **`fastapi-core`:**
75//!
76//! | Feature | Description |
77//! |---------|-------------|
78//! | `regex` | Regex support in testing assertions |
79//! | `compression` | Response compression middleware (gzip via flate2) |
80//! | `proptest` | Property-based testing support |
81
82//!
83//! # Cookbook
84//!
85//! Common patterns for building APIs with fastapi_rust.
86//!
87//! ## JSON CRUD Handler
88//!
89//! ```ignore
90//! use fastapi::prelude::*;
91//!
92//! #[get("/items/{id}")]
93//! async fn get_item(cx: &Cx, id: Path<i64>, state: State<AppState>) -> Result<Json<Item>, HttpError> {
94//! let item = state.db.find(id.0).await?;
95//! Ok(Json(item))
96//! }
97//! ```
98//!
99//! ## Pagination
100//!
101//! ```ignore
102//! use fastapi::prelude::*;
103//!
104//! #[get("/items")]
105//! async fn list_items(cx: &Cx, page: Pagination) -> Json<Page<Item>> {
106//! // page.page() returns current page (default: 1)
107//! // page.per_page() returns items per page (default: 20, max: 100)
108//! let items = db.list(page.offset(), page.limit()).await;
109//! Json(Page::new(items, total_count, page.page(), page.per_page()))
110//! }
111//! ```
112//!
113//! ## Bearer Token Authentication
114//!
115//! ```ignore
116//! use fastapi::prelude::*;
117//!
118//! #[get("/protected")]
119//! async fn protected(cx: &Cx, token: BearerToken) -> Json<UserInfo> {
120//! let user = verify_jwt(token.token()).await?;
121//! Json(user)
122//! }
123//! ```
124//!
125//! ## Background Tasks
126//!
127//! ```ignore
128//! use fastapi::prelude::*;
129//!
130//! #[post("/send-email")]
131//! async fn send_email(cx: &Cx, body: Json<EmailRequest>, tasks: BackgroundTasks) -> StatusCode {
132//! tasks.add(move || {
133//! // Runs after response is sent
134//! email_service::send(&body.to, &body.subject, &body.body);
135//! });
136//! StatusCode::ACCEPTED
137//! }
138//! ```
139//!
140//! ## CORS + Rate Limiting Middleware
141//!
142//! ```ignore
143//! use fastapi::prelude::*;
144//!
145//! let app = App::new()
146//! .middleware(Cors::new().allow_any_origin(true).allow_credentials(true))
147//! .middleware(RateLimitBuilder::new().max_requests(100).window_secs(60).build());
148//! ```
149//!
150//! ## Error Handling
151//!
152//! ```ignore
153//! use fastapi::prelude::*;
154//!
155//! // Custom errors implement IntoResponse automatically via HttpError
156//! fn not_found(resource: &str, id: u64) -> HttpError {
157//! HttpError::not_found(format!("{} {} not found", resource, id))
158//! }
159//! ```
160//!
161//! # Migrating from Python FastAPI
162//!
163//! ## Key Differences
164//!
165//! | Python FastAPI | fastapi_rust | Notes |
166//! |----------------|--------------|-------|
167//! | `@app.get("/")` | `#[get("/")]` | Proc macro instead of decorator |
168//! | `async def handler(item: Item)` | `async fn handler(cx: &Cx, item: Json<Item>)` | Explicit `Cx` context + typed extractors |
169//! | `Depends(get_db)` | `Depends<DbPool>` | Type-based DI, not function-based |
170//! | `HTTPException(404)` | `HttpError::not_found(msg)` | Typed error constructors |
171//! | `BackgroundTasks` | `BackgroundTasks` | Same concept, different API |
172//! | `Query(q: str)` | `Query<SearchParams>` | Struct-based query extraction |
173//! | `Path(item_id: int)` | `Path<i64>` | Type-safe path parameters |
174//! | `Body(...)` | `Json<T>` | Explicit JSON extraction |
175//! | `Response(status_code=201)` | `StatusCode::CREATED` | Type-safe status codes |
176//!
177//! ## Async Runtime
178//!
179//! Python FastAPI uses `asyncio`. fastapi_rust uses `asupersync`, which provides:
180//! - **Structured concurrency**: Request handlers run in regions
181//! - **Cancel-correctness**: Graceful cancellation via checkpoints
182//! - **Budgeted timeouts**: Request timeouts via budget exhaustion
183//!
184//! Every handler receives `&Cx` as its first parameter for async context.
185//!
186//! ## Dependency Injection
187//!
188//! Python uses function-based DI with `Depends(func)`. Rust uses trait-based DI:
189//!
190//! ```ignore
191//! // Python:
192//! // async def get_db():
193//! // yield db_session
194//! //
195//! // @app.get("/")
196//! // async def handler(db: Session = Depends(get_db)):
197//!
198//! // Rust:
199//! impl FromDependency for DbPool {
200//! async fn from_dependency(cx: &Cx, cache: &DependencyCache) -> Result<Self, HttpError> {
201//! Ok(DbPool::acquire(cx).await?)
202//! }
203//! }
204//!
205//! #[get("/")]
206//! async fn handler(cx: &Cx, db: Depends<DbPool>) -> Json<Data> { ... }
207//! ```
208//!
209//! ## Validation
210//!
211//! Python uses Pydantic models. Rust uses `#[derive(Validate)]`:
212//!
213//! ```ignore
214//! // Python:
215//! // class Item(BaseModel):
216//! // name: str = Field(..., min_length=1, max_length=100)
217//! // price: float = Field(..., gt=0)
218//!
219//! // Rust:
220//! #[derive(Validate)]
221//! struct Item {
222//! #[validate(min_length = 1, max_length = 100)]
223//! name: String,
224//! #[validate(range(min = 0.01))]
225//! price: f64,
226//! }
227//! ```
228
229#![forbid(unsafe_code)]
230// Design doc at PROPOSED_RUST_ARCHITECTURE.md (not embedded - too many conceptual code examples)
231
232// Re-export crates
233pub use fastapi_core as core;
234pub use fastapi_http as http;
235pub use fastapi_macros as macros;
236pub use fastapi_openapi as openapi;
237pub use fastapi_router as router;
238
239// Re-export commonly used types
240pub use fastapi_core::{
241 App, AppBuilder, AppConfig, ConfigError, Cors, CorsConfig, DefaultConfig,
242 DefaultDependencyConfig, DependencyOverrides, DependencyScope, Depends, DependsConfig,
243 FromDependency, FromRequest, HttpError, IntoResponse, Method, NoCache, Request, RequestId,
244 RequestIdConfig, RequestIdMiddleware, Response, ResponseBody, StateContainer, StatusCode,
245 ValidationError, ValidationErrors,
246};
247
248// Re-export extractors
249pub use fastapi_core::{
250 // Common header types
251 Accept,
252 AddResponseHeader,
253 AppState,
254 Authorization,
255 // Background tasks
256 BackgroundTasks,
257 BackgroundTasksInner,
258 // Auth extractors
259 BasicAuth,
260 BasicAuthError,
261 BearerToken,
262 BearerTokenError,
263 ContentType,
264 // Cookies
265 Cookie,
266 CookiePrefix,
267 CookiePrefixError,
268 DEFAULT_PAGE,
269 DEFAULT_PER_PAGE,
270 // Headers
271 Header,
272 HeaderExtractError,
273 HeaderValues,
274 Host,
275 // Body extractors
276 Json,
277 JsonConfig,
278 JsonExtractError,
279 MAX_PER_PAGE,
280 NamedHeader,
281 OAuth2BearerError,
282 OAuth2PasswordBearer,
283 OAuth2PasswordBearerConfig,
284 Page,
285 // Pagination
286 Pagination,
287 PaginationConfig,
288 // Path parameters
289 Path,
290 PathExtractError,
291 PathParams,
292 // Query string
293 Query,
294 QueryExtractError,
295 QueryParams,
296 RequestContext,
297 RequestCookies,
298 // Request utilities
299 RequestRef,
300 // Response mutations
301 ResponseMut,
302 ResponseMutations,
303 SameSite,
304 // State
305 State,
306 UserAgent,
307 XRequestId,
308};
309
310// Re-export testing utilities
311pub use fastapi_core::{CookieJar, RequestBuilder, TestClient, TestResponse};
312pub use fastapi_macros::{JsonSchema, Validate, delete, get, head, options, patch, post, put};
313pub use fastapi_openapi::{OpenApi, OpenApiBuilder, SchemaRegistry};
314pub use fastapi_router::{
315 // Route matching
316 AllowedMethods,
317 ConversionError,
318 // Path parameter types
319 Converter,
320 // Error types
321 InvalidRouteError,
322 ParamInfo,
323 ParamValue,
324 // Core router types
325 Route,
326 RouteAddError,
327 RouteConflictError,
328 RouteLookup,
329 RouteMatch,
330 Router,
331};
332
333// Re-export HTTP server types
334pub use fastapi_http::{
335 GracefulOutcome, ServeError, Server, ServerConfig, ServerError, ShutdownController,
336 ShutdownReceiver, TcpServer, serve, serve_with_config,
337};
338
339/// Prelude module for convenient imports.
340pub mod prelude {
341 pub use crate::{
342 // Core types
343 App,
344 AppBuilder,
345 AppConfig,
346 // Auth
347 BasicAuth,
348 BearerToken,
349 ConfigError,
350 Cookie,
351 Cors,
352 CorsConfig,
353 DefaultConfig,
354 DefaultDependencyConfig,
355 DependencyOverrides,
356 DependencyScope,
357 Depends,
358 DependsConfig,
359 FromDependency,
360 FromRequest,
361 Header,
362 HttpError,
363 IntoResponse,
364 // Extractors
365 Json,
366 // Macros
367 JsonSchema,
368 Method,
369 NoCache,
370 OAuth2PasswordBearer,
371 // OpenAPI
372 OpenApi,
373 OpenApiBuilder,
374 Page,
375 // Pagination
376 Pagination,
377 Path,
378 Query,
379 Request,
380 RequestContext,
381 RequestId,
382 RequestIdMiddleware,
383 Response,
384 Route,
385 Router,
386 // Server
387 Server,
388 ServerConfig,
389 State,
390 StatusCode,
391 Validate,
392 ValidationError,
393 ValidationErrors,
394 delete,
395 get,
396 head,
397 options,
398 patch,
399 post,
400 put,
401 serve,
402 };
403 pub use serde::{Deserialize, Serialize};
404}
405
406/// Testing utilities module.
407pub mod testing {
408 pub use fastapi_core::testing::{CookieJar, RequestBuilder, TestClient, TestResponse};
409}
410
411/// Extractors module for type-safe request data extraction.
412pub mod extractors {
413 pub use fastapi_core::{
414 Accept, AppState, Authorization, BackgroundTasks, BasicAuth, BearerToken, ContentType,
415 Cookie, Header, HeaderValues, Host, Json, JsonConfig, NamedHeader, OAuth2PasswordBearer,
416 Page, Pagination, PaginationConfig, Path, PathParams, Query, QueryParams, RequestRef,
417 ResponseMut, ResponseMutations, State, UserAgent, XRequestId,
418 };
419}
420
421/// HTTP server module with server types and configuration.
422pub mod server {
423 pub use fastapi_http::{
424 // Configuration constants
425 DEFAULT_DRAIN_TIMEOUT_SECS,
426 DEFAULT_KEEP_ALIVE_TIMEOUT_SECS,
427 DEFAULT_MAX_CONNECTIONS,
428 DEFAULT_MAX_REQUESTS_PER_CONNECTION,
429 DEFAULT_READ_BUFFER_SIZE,
430 DEFAULT_REQUEST_TIMEOUT_SECS,
431 // Shutdown coordination
432 GracefulOutcome,
433 // Error types
434 ServeError,
435 // Server types
436 Server,
437 ServerConfig,
438 ServerError,
439 ShutdownController,
440 ShutdownReceiver,
441 TcpServer,
442 // Server functions
443 serve,
444 serve_with_config,
445 };
446}