api_error

Attribute Macro api_error 

Source
#[api_error]
Expand description

Attribute macro for automatically generating HTTP error responses.

This macro automatically implements axum::response::IntoResponse for error enums, mapping each variant to an appropriate HTTP status code. Use doc comments with /// {code}: {description} format to specify status codes for variants.

§Basic Usage

use stonehm_macros::api_error;
 
#[api_error]
enum ApiError {
    /// 404: User not found
    UserNotFound { id: u32 },
     
    /// 400: Invalid input provided
    InvalidInput { message: String },
     
    /// 401: Authentication required
    Unauthorized,
     
    /// 403: Access forbidden
    Forbidden,
     
    // Variants without doc comments default to 500 Internal Server Error
    DatabaseError,
    NetworkTimeout,
}

§Generated Implementation

The macro automatically generates:

  • IntoResponse implementation for HTTP responses
  • Serialize implementation for JSON serialization
  • StonehmSchema implementation for OpenAPI documentation
  • Maps each variant to its specified status code
  • Uses 500 Internal Server Error for variants without doc comments
  • Serializes the error as JSON in the response body

§Supported Status Codes

Common HTTP status codes you can use:

  • 200 OK
  • 201 Created
  • 204 No Content
  • 400 Bad Request
  • 401 Unauthorized
  • 403 Forbidden
  • 404 Not Found
  • 409 Conflict
  • 422 Unprocessable Entity
  • 500 Internal Server Error
  • 502 Bad Gateway
  • 503 Service Unavailable

§Examples

§Basic Error Enum

#[api_error]
#[derive(Serialize)]
enum UserError {
    /// 404: User not found
    NotFound { id: u32 },
     
    /// 400: Invalid user data
    InvalidData { field: String, reason: String },
}

§With Custom Serialization

#[api_error]
#[derive(Serialize)]
#[serde(tag = "error", content = "details")]
enum ApiError {
    /// 401: Missing or invalid authentication token
    #[serde(rename = "auth_required")]
    AuthRequired,
     
    /// 403: User lacks required permissions
    #[serde(rename = "access_denied")]
    AccessDenied { required_role: String },
}

§Usage in Handlers

 
/// Update user information
#[api_handler]
async fn update_user(
    axum::extract::Path(id): axum::extract::Path<u32>,
    Json(data): Json<UpdateUserRequest>
) -> Result<Json<User>, UserError> {
    if id == 0 {
        return Err(UserError::NotFound { id });
    }
     
    if data.name.is_empty() {
        return Err(UserError::InvalidData { 
            message: "Name cannot be empty".to_string() 
        });
    }
     
    Ok(Json(User { id, name: data.name }))
}

§Requirements

  • The error enum must also have #[derive(Serialize)] or implement Serialize manually
  • Each variant’s doc comment should start with a 3-digit HTTP status code followed by a colon
  • The macro will automatically implement axum::response::IntoResponse
  • The macro will register the error schema for OpenAPI documentation