Crate actix_failwrap

Crate actix_failwrap 

Source
Expand description

actix_failwrap banner

Crates.io License Docs.rs Downloads Codecov tests Discord

actix_failwrap /หˆรฆk.tษชks หˆfeษชl.rรฆp/ (โ€œaktiks fail-rapโ€) A micro-package that enables ergonomic error propagation (via thiserror) inside Actix Web route handlers.

This crate allows you to:

  • โœ… Assign HTTP status codes to your thiserror enums.
  • ๐Ÿงฉ Customize the HTTP response with a builder function.
  • โšก Use the ? operator naturally inside route handlers.

ยงTable of Contents ๐Ÿ“–


ยงFeatures ๐Ÿš€

  • โœ… Automatic error-to-response conversion using thiserror enums Define route errors with #[derive(ErrorResponse)] to auto-generate HttpResponse.

  • ๐Ÿงฉ Custom response transformation per error enum Use #[transform_response(fn)] to modify headers, body, or status codes.

  • ๐Ÿง  Per-variant status code overrides Set status codes using #[status_code(...)] โ€” supports both constants and numbers.

  • ๐Ÿ” Fallback behavior for unannotated variants Variants without #[status_code] fall back to #[default_status_code] or HTTP 500.

  • โœ๏ธ Extractor error mapping with #[error_override(...)] Map deserialization or extractor failures to your own enum variant.

  • โšก Minimal boilerplate route macros with #[proof_route(...)] Use ? with error enums directly and skip actix_web macro imports.


ยงInstallation ๐Ÿ“ฆ

[!IMPORTANT] The actix_failwrap macros rely on thiserror for the Display implementation, and are tightly coupled with actix-web for building HTTP responses.

This crate is published on crates.io and is intended for use alongside actix-web and thiserror.

Add all three to your Cargo.toml:

[dependencies]
actix-web = "4"
thiserror = "1"
actix_failwrap = "1.0.0"

ยงUsage Example ๐Ÿค”

This example shows a login route in Actix Web using actix_failwrap.

In your project you may have a module that declares models, in this case a User model. In that file you may declare your thiserror error that you may re-use for your handler.

โ“˜
use serde::{Serialize, Deserialize};
use actix_failwrap::ErrorResponse;
use thiserror::Error;

// Custom error transformation function used by #[transform_response]
// Converts an error into a response with an "Error" header.
fn error_to_header(mut response: HttpResponseBuilder, error: String) -> HttpResponse {
  response.insert_header(("Error", error)).finish()
}

// Define a custom error enum for user-related errors.
#[derive(ErrorResponse, Error, Debug)]
// Default fallback for variants without #[status_code],
// if the attribute is not present, the default status code will be 500.
#[default_status_code(InternalServerError)]
// Function used to transform the final HttpResponse,
// if the attribute not present, the Display is mapped to the body.
#[transform_response(error_to_header)]
pub enum UserError {
  #[error("Either the email or the password is invalid. Please check the input credentials")]
  // This can also be a numeric HTTP status code.
  #[status_code(Unauthorized)]
  InvalidCredentials,

  #[error("Missing credentials, please, introduce your email and password.")]
  #[status_code(BadRequest)]
  MissingCredentials,
}

#[derive(Serialize, Deserialize)]
pub struct UserCredentials {
  pub email: String,
  pub password: String,
}

// Simulates a function that attempts to authenticate a user and returns a Result
pub fn obtain_user(credentials: UserCredentials) -> Result<User, UserError> {
  /* ... */
}

And another module that declares handlers, this example handler obtains a user with some credentials and returns its JWT token if successful.

โ“˜
use actix_failwrap::proof_route;
use actix_web::{web::Form, HttpResponse, HttpResponseBuilder};

use crate::models::user::{UserError, UserCredentials, obtain_user};

// Route macro expands to #[actix_web::post("/login")] and allows
// to use `Result<HttpResponse, _>`.
#[proof_route("POST /login")]
async fn post_login(
  // If the extractor (Form) fails, override it with MissingCredentials variant
  #[error_override(MissingCredentials)] credentials: Form<UserCredentials>
) -> Result<HttpResponse, UserError> {
  // Attempt to obtain the user; if it fails, propagate the error
  let user = obtain_user(credentials.into_inner())?;

  // On success, return a response with a "Login" header containing the JWT
  Ok(
    HttpResponse::Ok().
      .insert_header(("Login", user.jwt()))
      .finish()
  )
}

ยงExported macros ๐Ÿ”ง

This crate exports two macros: ErrorResponse and proof_route.

ยง#[derive(ErrorResponse)]

Implements Into<actix_web::HttpResponse> and Into<actix_web::Error> for your thiserror enums, allowing direct propagation with the ? operator in handlers.

[!WARNING] Requires #[derive(thiserror::Error)] because it uses the Display implementation.

ยงSupported Attributes
  • #[default_status_code(...)] Fallback status code used if a variant does not have its own #[status_code(...)] Defaults to InternalServerError (500).

  • #[status_code(...)] Sets the HTTP status code for a specific variant. Accepts a named status (e.g. BadRequest) or number (400).

  • #[transform_response(fn)] Customizes how the response is built. Takes a function of signature: fn(HttpResponseBuilder, String) -> HttpResponse.

ยง#[proof_route(...)]

Simplifies route definition and error propagation.

โ“˜
#[proof_route("POST /path")]

Expands to:

โ“˜
#[actix_web::post("/path")]

An example function signature looks like

โ“˜
#[proof_route("GET /users")]
async fn get_users() -> Result<HttpResponse, Error> {}

[!TIP] You can use a Result<T: actix_web::Responder, Error> instead of HttpResponse.

Allows you to:

  • Use Result<HttpResponse, Error> directly in route bodies.
  • Avoid importing #[post], #[get], etc. individually.
  • Support extractor error override via #[error_override(...)].

ยงSecurity ๐Ÿ”

Security is a top priority for us. If you believe youโ€™ve found a security vulnerability, do not open a public issue. Instead, please read our SECURITY.md policy and report it responsibly by contacting us at security@flaky.es.


ยงLicense ๐Ÿ“œ

This repository is dual licensed, If your repository is open source, the library is free of use, otherwise contact licensing@flaky.es for a custom license for your use case.

For more information read the license file.

Attribute Macrosยง

proof_route
proof_route Attribute Macro

Derive Macrosยง

ErrorResponse
ErrorResponse Derive Macro