Response & Error Handling
Response types
Handlers can return various types, the framework automatically converts them to HTTP responses.
Direct data return
rust
#[get("/")]
async fn index(&self) -> String {
"Hello".to_string()
}
#[get("/health")]
async fn health(&self) -> StatusCode {
StatusCode::OK
}Json
Return JSON responses:
rust
#[get("/users")]
async fn list(&self) -> Json<Vec<User>> {
Json(vec![/* ... */])
}Result / WebrResult
Supports ? error propagation:
rust
use webr::WebrResult;
#[get("/users/{id}")]
async fn get_user(&self, Path(id): Path<i64>) -> WebrResult<Json<User>> {
let user = self.service.find(id).await
.ok_or_else(|| Error::Http {
status: StatusCode::NOT_FOUND,
message: format!("User {id} not found"),
})?;
Ok(Json(user))
}Use WebrResult<T> as an alias for Result<T, Error>.
Error handling
Returning Error directly
Use Error::Http to construct errors with status code and message:
rust
use webr::Error;
#[get("/items/{id}")]
async fn get_item(&self, Path(id): Path<i64>) -> Result<Json<Item>, Error> {
if id > 0 {
Ok(Json(Item { id, name: "Item".into() }))
} else {
Err(Error::Http {
status: StatusCode::NOT_FOUND,
message: format!("Item {id} not found"),
})
}
}Error types
rust
pub enum Error {
Http { status: StatusCode, message: String }, // HTTP business error
Database(Box<dyn Error + Send + Sync>), // Database error
Cache(Box<dyn Error + Send + Sync>), // Cache error
Internal(String), // Internal error
}Errors automatically convert to JSON responses: {"code": 404, "message": "Item 42 not found"}.
#[derive(HttpError)]
Declarative error definition, automatically maps to HTTP responses:
rust
#[derive(Debug, webr::HttpError)]
pub enum UserError {
#[error(status = 404, message = "User not found")]
NotFound(i64),
#[error(status = 409, message = "Email already exists")]
DuplicateEmail(String),
}
// Usage in handler
async fn get_user(&self, Path(id): Path<i64>) -> Result<Json<User>, UserError> {
let user = self.service.find(id).await
.ok_or(UserError::NotFound(id))?;
Ok(Json(user))
}Features generated by HttpError derive:
- Automatically implements
IntoResponse, can be used directly as return value - Automatically implements
From<Self> for Error, supports?upward conversion toError
Unified response wrapping
Enable unified_response to automatically wrap 2xx JSON responses into a standard format:
rust
app.unified_response();Original response:
json
{"id": 1, "name": "Alice"}Wrapped response:
json
{"code": 200, "message": "success", "data": {"id": 1, "name": "Alice"}}Rules:
- 2xx + JSON response → wrapped
- Non-2xx responses → passed through as-is
- Non-JSON responses (String, StatusCode, etc.) → passed through as-is
