Extractors and Validation
Relevant source files
The following files were used as context for generating this wiki page:
Extractors and Validation in the Loco framework provide a robust mechanism for parsing, retrieving, and verifying incoming request data within controllers. Built upon the Axum ecosystem, extractors allow developers to declaratively define how data—such as JSON payloads or shared application state—should be pulled from an HTTP request and transformed into strongly-typed Rust structures.
The system integrates deeply with validation logic to ensure that extracted data meets business requirements before reaching the core controller logic. This ensures that the application models remain clean and that errors are caught early in the request lifecycle, providing consistent feedback to the client.
Request Data Extraction
Loco utilizes extractors to handle various parts of an HTTP request. This includes standard payloads and specialized containers for application context and shared storage.
JSON and Validation Extraction
The Validate extractor is a primary component that combines JSON parsing with immediate schema validation. It wraps a data structure and automatically triggers a validation check upon extraction.
The flow demonstrates how the Validate extractor acts as a gatekeeper between the raw request and the controller action.
Sources: src/controller/extractor/validate.rs
Shared Store Extraction
The SharedStore extractor provides a mechanism for accessing globally shared data within the application. It is designed to be highly concurrent, utilizing an Arc<RwLock<T>> to allow multiple readers or exclusive writers to access the underlying data.
| Component | Description |
|---|---|
SharedStore<T> | A wrapper around Arc<RwLock<T>> used to inject shared state into controllers. |
from_request_parts | The implementation allowing the store to be extracted from Axum request parts. |
Sources: src/controller/extractor/shared_store.rs
Validation Logic and Models
Validation in Loco is not limited to controllers; it is a core feature of the data models. The framework supports rich entities with built-in validation logic to maintain data integrity.
Validation Structure
The validation system is designed to be informative and non-cryptic. It utilizes the thiserror crate to provide clear context when validation fails, often indicating precisely which field or file caused the issue.
The diagram represents the relationship where models encapsulate their own validation logic, producing results that can be handled by the framework's error systems.
Sources: docs-site/config.toml, DEVELOPMENT.md
Key Validation Features
- Entity Validation: Logic is built directly into entities to avoid writing manual SQL checks and to ensure maintainability.
- Informative Errors: Errors are designed to indicate how to fix issues precisely, avoiding cryptic messages.
- Auto Conversions: The framework uses
Fromtrait implementations to centralize error conversions, reducing boilerplate in controller code.
Sources: docs-site/config.toml, DEVELOPMENT.md
Implementation Details
Validated JSON Extraction
The Validate struct is defined as a tuple struct pub struct Validate<T>(pub T). Its implementation of FromRequest (specifically through from_request) handles the deserialization of JSON and subsequent validation.
// Implementation example (derived from logic)
// 1. Extract JSON using Axum's Json extractor
// 2. Perform validation on the inner type T
// 3. Return T wrapped in Validate or a Rejection
Sources: src/controller/extractor/validate.rs
Shared State Management
The SharedStore implementation ensures that shared application state is available across different request threads.
Summary
The Extractors and Validation system in Loco provides a productivity-first approach to handling web requests. By combining Axum's high-performance extraction with a centralized validation philosophy, Loco ensures that controllers remain focused on business logic while the framework handles the complexities of data parsing, shared state management, and error reporting. This structure allows solo developers and teams to build and scale Rust applications with the same confidence and speed typically associated with frameworks like Ruby on Rails.