lilydocs
HTTP APIWebSocketConsumer
HTTP2 min read

Validation and custom extractors

Separate parsing errors from business rules and return safe HTTP errors.

Typed extraction converts data to a Rust type. Business rules, such as a field being nonempty, a user existing, or two fields being consistent, are validated separately.

Validate the DTO's shape#

DTO
#[derive(serde::Deserialize)]
#[serde(deny_unknown_fields)]
struct CreateUser {
    name: String,
}

deny_unknown_fields is an explicit application choice. Ordinary Json<T> does not automatically enable this rule for every DTO. Content-type mismatches, malformed JSON, and typed conversion errors are handled by the extractor.

Validate business rules#

The action in the controller example checks that the name is not empty:

Inside an action or domain service
if input.name.trim().is_empty() {
    return Err(HttpApiError::ValidationError("name is required".into()));
}

ValidationError produces HTTP 422. Do not assume its payload string is returned to the client verbatim; built-in errors use a safe public-message contract. If you need a public field-level error schema, define a custom error converter.

Reusable extractors#

Need Trait
Validate a request part without consuming the body FromRequestParts
Treat the absence of that part as optional OptionalFromRequestParts
Produce a new data type by consuming the body FromRequest

A custom extractor's Rejection type must implement Into<HttpApiError>. A custom body extractor must be the last typed parameter. Do not move request/body references outside the operation.

Choose the right error type#

Situation Typical HTTP result
Malformed data or typed conversion 400
Unsupported content type 415
Body limit exceeded 413
Business validation in this example 422

Lily's extension points are extractors, guards, middleware, and response converters. Although the explanation order may feel familiar from NestJS, ValidationPipe is not part of Lily's API.

Sources for this page v0.1.0

This guide is based on the reviewed framework commit.

QUICK START
Documentation
Source code