ripress/
lib.rs

1#![warn(missing_docs)]
2
3//! # Ripress
4//!
5//! Ripress is a lightweight, modular web framework for building HTTP APIs and web applications in Rust.
6//! It provides a simple and flexible API for defining routes, handling requests and responses, and composing middleware.
7//! Inspired by Express.js, Ripress brings the familiar developer experience to Rust while maintaining high performance.
8//!
9//! ## Quick Start
10//!
11//! ```no_run
12//! use ripress::{app::App, types::RouterFns};
13//!
14//! #[tokio::main]
15//! async fn main() {
16//!     let mut app = App::new();
17//!
18//!     // Define routes
19//!     app.get("/", |_req, res| async move {
20//!         res.ok().text("Hello, World!")
21//!     });
22//!
23//!     app.get("/api/users", |_req, res| async move {
24//!         res.ok().json(serde_json::json!({
25//!             "users": ["Alice", "Bob", "Charlie"]
26//!         }))
27//!     });
28//!
29//!     // Add middleware
30//!     app.use_cors(None);
31//!
32//!     // Start server
33//!     app.listen(3000, || {
34//!         println!("Server running on http://localhost:3000");
35//!     }).await;
36//! }
37//! ```
38//!
39//! ## Key Features
40//!
41//! - **Express.js-like API**: Familiar routing and middleware patterns
42//! - **Async/Await Support**: Built on Tokio for high-performance async operations
43//! - **Type Safety**: Full Rust type safety with compile-time error checking
44//! - **Built-in Middleware**: CORS, logging, compression, rate limiting, and more
45//! - **Request/Response Objects**: Rich APIs for handling HTTP data
46//! - **WebSocket Support**: Real-time communication via the `wynd` crate (optional `with-wynd` feature)
47//! - **Static File Serving**: Built-in support for serving static assets
48//!
49//! ## Optional Features
50//!
51//! Several features are optional and can be enabled to reduce compile time and binary size:
52//!
53//! - **`compression`**: Response compression middleware (gzip/deflate)
54//! - **`file-upload`**: File upload middleware for multipart form data
55//! - **`logger`**: Request/response logging middleware
56//! - **`with-wynd`**: WebSocket support via the `wynd` crate
57//!
58//! ## Advanced Examples
59//!
60//! ### RESTful API with JSON
61//! ```no_run
62//! use ripress::{app::App, types::RouterFns};
63//! use serde::{Deserialize, Serialize};
64//!
65//! #[derive(Serialize, Deserialize)]
66//! struct User {
67//!     id: u32,
68//!     name: String,
69//!     email: String,
70//! }
71//!
72//! #[tokio::main]
73//! async fn main() {
74//!     let mut app = App::new();
75//!
76//!     // GET /users - List all users
77//!     app.get("/users", |_req, res| async move {
78//!         let users = vec![
79//!             User { id: 1, name: "Alice".to_string(), email: "alice@example.com".to_string() },
80//!             User { id: 2, name: "Bob".to_string(), email: "bob@example.com".to_string() },
81//!         ];
82//!         res.ok().json(users)
83//!     });
84//!
85//!     // POST /users - Create a new user
86//!     app.post("/users", |req, res| async move {
87//!         match req.json::<User>() {
88//!             Ok(user) => res.created().json(user),
89//!             Err(_) => res.bad_request().text("Invalid JSON"),
90//!         }
91//!     });
92//!
93//!     // GET /users/:id - Get user by ID
94//!     app.get("/users/:id", |req, res| async move {
95//!         let user_id = req.params.get("id").unwrap_or("0");
96//!         res.ok().json(serde_json::json!({
97//!             "id": user_id,
98//!             "message": "User found"
99//!         }))
100//!     });
101//!
102//!     app.listen(3000, || {
103//!         println!("API server running on http://localhost:3000");
104//!     }).await;
105//! }
106//! ```
107//!
108//! ### File Upload with Middleware
109//! ```ignore
110//! use ripress::{app::App, middlewares::file_upload::file_upload, types::RouterFns};
111//!
112//! #[tokio::main]
113//! async fn main() {
114//!     let mut app = App::new();
115//!
116//!     // Add file upload middleware
117//!     app.use_pre_middleware("/upload", file_upload(None));
118//!
119//!     app.post("/upload", |req, res| async move {
120//!         // Access uploaded files through request data
121//!         if let Some(file_data) = req.get_data("uploaded_file") {
122//!             res.ok().text(format!("File uploaded: {}", file_data))
123//!         } else {
124//!             res.bad_request().text("No file uploaded")
125//!         }
126//!     });
127//!
128//!     app.listen(3000, || {
129//!         println!("File upload server running on http://localhost:3000");
130//!     }).await;
131//! }
132//! ```
133//!
134
135/// The main application struct and its methods for configuring and running your server.
136///
137/// The `App` struct is the core of Ripress, providing methods to define routes, add middleware,
138/// and start the HTTP server. It follows an Express.js-like pattern for route handling.
139///
140/// # Examples
141///
142/// Basic server setup:
143/// ```rust
144/// use ripress::{app::App, types::RouterFns};
145///
146/// #[tokio::main]
147/// async fn main() {
148///     let mut app = App::new();
149///     app.get("/", |_req, res| async move { res.ok().text("Hello, World!") } );
150/// }
151/// ```
152///
153/// With middleware:
154/// ```rust
155/// use ripress::{app::App, types::RouterFns};
156///
157/// #[tokio::main]
158/// async fn main() {
159///     let mut app = App::new();
160///
161///     app.use_cors(None)
162///         .get("/api/data", |_req, res| async move {
163///             res.ok().json(serde_json::json!({"status": "ok"}))
164///         });
165/// }
166/// ```
167pub mod app;
168
169/// The HTTP request struct and its methods for extracting data from requests.
170///
171/// `HttpRequest` provides comprehensive access to incoming HTTP request data including
172/// headers, cookies, query parameters, route parameters, and request body content.
173///
174/// # Examples
175///
176/// Accessing request data:
177/// ```rust
178/// use ripress::context::HttpRequest;
179///
180/// async fn handler(req: HttpRequest, res: ripress::context::HttpResponse) -> ripress::context::HttpResponse {
181///     // Get query parameters
182///     let name = req.query.get("name").unwrap_or("World");
183///     
184///     // Get route parameters
185///     let user_id = req.params.get("id");
186///     
187///     // Parse JSON body
188///     if let Ok(data) = req.json::<serde_json::Value>() {
189///         println!("Received JSON: {:?}", data);
190///     }
191///     
192///     res.ok().text(format!("Hello, {}!", name))
193/// }
194/// ```
195///
196/// See [`req::HttpRequest`] for details.
197pub mod req;
198
199/// The HTTP response struct and its methods for building responses.
200///
201/// `HttpResponse` provides methods to construct HTTP responses with different status codes,
202/// headers, cookies, and various body types (JSON, text, HTML, binary).
203///
204/// # Examples
205///
206/// Creating responses:
207/// ```rust
208/// use ripress::context::{HttpResponse, HttpRequest};
209///
210/// // JSON response
211/// async fn json_res(req: HttpRequest, res: HttpResponse) -> HttpResponse {
212///     return res.ok().json(serde_json::json!({"message": "Success"}));
213/// }
214///
215/// // Text response with custom status
216/// async fn text_res(req: HttpRequest, res: HttpResponse) -> HttpResponse {
217///     return res.status(201).text("Resource created");
218/// }
219///
220/// // Response with cookies
221/// async fn cookie_res(req: HttpRequest, res: HttpResponse) -> HttpResponse {
222///     return res.ok().set_cookie("session", "abc123", None).text("Logged in");
223/// }
224/// ```
225///
226/// See [`res::HttpResponse`] for details.
227pub mod res;
228
229/// Common context types for handler functions.
230///
231/// Re-exports [`HttpRequest`] and [`HttpResponse`] for convenience in route handlers.
232/// This module provides the most commonly used types when writing route handlers.
233///
234/// # Examples
235///
236/// ```rust
237/// use ripress::context::{HttpRequest, HttpResponse};
238///
239/// async fn my_handler(req: HttpRequest, res: HttpResponse) -> HttpResponse {
240///     res.ok().text("Hello from handler!")
241/// }
242/// ```
243pub mod context {
244    pub use super::req::HttpRequest;
245    pub use super::res::HttpResponse;
246}
247
248/// Utility functions and helpers for common web tasks.
249///
250/// This module contains helper functions for common web development tasks such as
251/// parsing multipart forms, handling query parameters, and other utilities.
252pub mod helpers;
253
254/// Built-in middleware modules for CORS, logging, file uploads, and rate limiting.
255///
256/// Ripress includes several built-in middleware modules to handle common web application
257/// concerns. These can be easily added to your application using the `App` methods.
258///
259/// # Available Middleware
260///
261/// - **CORS**: Cross-Origin Resource Sharing configuration
262/// - **Logger**: Request/response logging with customizable output (requires `logger` feature)
263/// - **Compression**: Response compression (gzip, deflate) (requires `compression` feature)
264/// - **Rate Limiter**: Request rate limiting and throttling
265/// - **Body Limit**: Request body size limiting
266/// - **Shield**: Security headers and protection
267/// - **File Upload**: Multipart form data and file upload handling (requires `file-upload` feature)
268///
269/// # Examples
270///
271/// ```ignore
272/// use ripress::{app::App, types::RouterFns};
273///
274/// #[tokio::main]
275/// async fn main() {
276///     let mut app = App::new();
277///     
278///     // Add multiple middleware
279///     app.use_cors(None)                    // Enable CORS    
280///         .use_logger(None)                 // Enable request logging
281///         .use_compression(None)            // Enable response compression
282///         .use_rate_limiter(None)           // Enable rate limiting
283///         .use_shield(None);                // Add security headers
284/// }
285/// ```
286pub mod middlewares;
287
288/// The router struct and routing logic for organizing endpoints.
289///
290/// The router module provides functionality for organizing and managing routes
291/// in your application. While most applications will use the `App` struct directly,
292/// the router can be used for more complex routing scenarios.
293pub mod router;
294
295/// Core types, traits, and enums used throughout the framework.
296///
297/// This module contains the fundamental types, traits, and enums that power
298/// the Ripress framework, including HTTP methods, content types, and routing traits.
299///
300/// # Key Types
301///
302/// - `HttpMethods`: Enum representing HTTP methods (GET, POST, PUT, etc.)
303/// - `RouterFns`: Trait for route definition methods
304/// - `ResponseContentType`: Enum for response content types
305/// - `RequestBodyType`: Enum for request body types
306pub mod types;
307
308/// Internal test module for framework testing.
309mod tests;
310
311/// Error types and utilities for the Ripress framework.
312///
313/// This module provides structured error types, error categories, and conversion utilities
314/// for handling errors throughout the framework. It includes the [`RipressError`] struct,
315/// the [`RipressErrorKind`] enum for classifying errors, and conversions from lower-level
316/// errors such as query parameter and route parameter parsing failures.
317///
318/// # Error Handling
319///
320/// Ripress provides comprehensive error handling with structured error types that make it
321/// easy to handle different kinds of errors that can occur in web applications.
322///
323/// # Examples
324///
325/// Basic error handling:
326/// ```ignore
327/// use ripress::error::{RipressError, RipressErrorKind};
328///
329/// // Create a custom error
330/// let error = RipressError::new(
331///     RipressErrorKind::InvalidInput,
332///     "Invalid input data".to_string()
333/// );
334///
335/// // Handle different error types
336/// match error.kind() {
337///     RipressErrorKind::InvalidInput => {
338///         println!("Invalid data: {}", error.message());
339///     }
340///     RipressErrorKind::NotFound => {
341///         println!("Resource not found: {}", error.message());
342///     }
343///     _ => {
344///         println!("Other error: {}", error.message());
345///     }
346/// }
347/// ```
348///
349/// See [`error::RipressError`] and [`error::RipressErrorKind`] for details.
350pub mod error;