A (flash) message framework for actix-web. A port to Rust of Django's message framework.

Overview

actix-web-flash-messages

Flash messages for actix-web


Web applications sometimes need to show a one-time notification to the user - e.g. an error message after having failed to login.
These notifications are commonly called flash messages.

actix-web-flash-messages provides a framework to work with flash messages in actix-web, closely modeled after Django's message framework.

impl Responder { FlashMessage::info("Hey there!").send(); FlashMessage::debug("How is it going?").send(); // Redirect to /show HttpResponse::TemporaryRedirect() .insert_header((http::header::LOCATION, "/show")) .finish() } /// Pick up the flash messages attached to the request, showing /// them to the user via the request body. #[get("/show")] async fn show(messages: IncomingFlashMessages) -> impl Responder { let mut body = String::new(); for message in messages.iter() { writeln!(body, "{} - {}", message.content(), message.level()).unwrap(); } HttpResponse::Ok().body(body) } ">
use actix_web::{Responder, HttpResponse, get,http};
use actix_web_flash_messages::{
    FlashMessage, IncomingFlashMessages,
};
use std::fmt::Write;

/// Attach two flash messages to the outgoing response,
/// a redirect.
#[get("/set")]
async fn set() -> impl Responder {
    FlashMessage::info("Hey there!").send();
    FlashMessage::debug("How is it going?").send();
    // Redirect to /show
    HttpResponse::TemporaryRedirect()
        .insert_header((http::header::LOCATION, "/show"))
        .finish()
}

/// Pick up the flash messages attached to the request, showing
/// them to the user via the request body.
#[get("/show")]
async fn show(messages: IncomingFlashMessages) -> impl Responder {
    let mut body = String::new();
    for message in messages.iter() {
        writeln!(body, "{} - {}", message.content(), message.level()).unwrap();
    }
    HttpResponse::Ok().body(body)
}

How to install

Add actix-web-flash-messages to your dependencies:

[dependencies]
# ...
actix-web = "4.0.0-beta.9"
actix-web-flash-messages = "0.2"

By default, actix-web-flash-messages does not provide any storage backend to receive and send flash messages.
You can enable:

  • a cookie-based one, storage::CookieMessageStore, using the cookies feature flag. The cookie store uses a signed cookie to store and retrieve messages;
[dependencies]
# ...
actix-web-flash-messages = { version = "0.2", features = ["cookies"] }
  • a session-based one, [storage::SessionMessageStore], using the sessions feature flag. The session store attaches flash messages to the current session.
[dependencies]
# ...
actix-web-flash-messages = { version = "0.2", features = ["sessions"] }

You can provide a different message store by implementing the storage::FlashMessageStore trait.

Examples

You can find examples of application using actix-web-flash-messages on GitHub:

The Structure of a Flash Message

FlashMessages are made of a Level and a string of content.

The message level can be used for filtering and rendering - for example:

  • Only show flash messages at info level or above in a production environment, while retaining debug level messages for local development;
  • Use different colours, in the UI, to display messages (e.g. red for errors, orange for warnings, etc.);

You can build a FlashMessage via FlashMessage::new by specifying its content and Level.
You can also use the shorter level-based constructors - e.g. FlashMessage::info.

Enabling Flash Messages

To start sending and receiving flash messages you need to register FlashMessagesFramework as a middleware on your actix_web's App:

use actix_web_flash_messages::{FlashMessagesFramework, storage::CookieMessageStore};
use actix_web::{HttpServer, App, web};
use actix_web::cookie::Key;

#[actix_web::main]
async fn main() {
    let signing_key = Key::generate(); // This will usually come from configuration!
    let message_store = CookieMessageStore::builder(signing_key).build();
    let message_framework = FlashMessagesFramework::builder(message_store).build();
    
    HttpServer::new(move || {
        App::new()
            .wrap(message_framework.clone())
            // [...] your endpoints
    })
}

You will then be able to:

impl Responder { FlashMessage::info("Hey there!").send(); // [...] } /// Extract the flash message from the incoming request. #[get("/show")] async fn show(_messages: IncomingFlashMessages) -> impl Responder { // [...] } ">
use actix_web::{Responder, HttpResponse, get};
use actix_web_flash_messages::{
    FlashMessage, IncomingFlashMessages,
};

/// Send a flash messages alongside the outgoing response, a redirect.
#[get("/set")]
async fn set() -> impl Responder {
    FlashMessage::info("Hey there!").send();
    // [...]
}

/// Extract the flash message from the incoming request.
#[get("/show")]
async fn show(_messages: IncomingFlashMessages) -> impl Responder {
    // [...]
}

Framework Configuration

There are a few knobs that you can tweak when it comes to FlashMessagesFramework.
Use FlashMessagesFramework::builder to get access to its fluent configuration API, built around FlashMessagesFrameworkBuilder.

Minimum Level

By default, FlashMessagesFramework will only dispatch messages at info-level or above, discarding debug-level messages.
You can change this setting using FlashMessagesFrameworkBuilder::minimum_level.

Level::Debug, _ => Level::Info, }; let message_framework = FlashMessagesFramework::builder(get_message_store()) .minimum_level(minimum_level) .build(); HttpServer::new(move || { App::new() .wrap(message_framework.clone()) // [...] Your endpoints }) } ">
use actix_web_flash_messages::{FlashMessagesFramework, Level, storage::CookieMessageStore};
use actix_web::{HttpServer, App, web};

fn get_message_store() -> CookieMessageStore {
    // [...]
    # CookieMessageStore::builder(actix_web::cookie::Key::generate()).build()
}

#[actix_web::main]
async fn main() {
    // Show debug-level messages when developing locally
    let minimum_level = match std::env::var("APP_ENV") {
        Ok(s) if &s == "local" => Level::Debug,
        _ => Level::Info,
    };
    let message_framework = FlashMessagesFramework::builder(get_message_store())
        .minimum_level(minimum_level)
        .build();

    HttpServer::new(move || {
        App::new()
            .wrap(message_framework.clone())
            // [...] Your endpoints
    })
}

Message Storage

actix-web-flash-messages provides a cookie-based implementation of flash messages, storage::CookieMessageStore, using a signed cookie to store and retrieve messages.
You can provide a different message store by implementing the storage::FlashMessageStore trait.

License

Licensed under either of Apache License, Version 2.0 or MIT license at your option. Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in this crate by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions.

You might also like...
A highly customizable, full scale web backend for web-rwkv, built on axum with websocket protocol.

web-rwkv-axum A axum web backend for web-rwkv, built on websocket. Supports BNF-constrained grammar, CFG sampling, etc., all streamed over network. St

A Rust web framework

cargonauts - a Rust web framework Documentation cargonauts is a Rust web framework intended for building maintainable, well-factored web apps. This pr

A rust web framework with safety and speed in mind.

darpi A web api framework with speed and safety in mind. One of the big goals is to catch all errors at compile time, if possible. The framework uses

A web framework for Rust.

Rocket Rocket is an async web framework for Rust with a focus on usability, security, extensibility, and speed. #[macro_use] extern crate rocket; #[g

Rust / Wasm framework for building client web apps
Rust / Wasm framework for building client web apps

Yew Rust / Wasm client web app framework Documentation (stable) | Documentation (latest) | Examples | Changelog | Roadmap | 简体中文文档 | 繁體中文文檔 | ドキュメント A

Thruster - An fast and intuitive rust web framework

A fast, middleware based, web framework written in Rust

A full-featured and easy-to-use web framework with the Rust programming language.

Poem Framework A program is like a poem, you cannot write a poem without writing it. --- Dijkstra A full-featured and easy-to-use web framework with t

Perseus is a blazingly fast frontend web development framework built in Rust with support for major rendering strategies

Perseus is a blazingly fast frontend web development framework built in Rust with support for major rendering strategies, reactivity without a virtual DOM, and extreme customizability

Seed is a Rust front-end framework for creating fast and reliable web apps with an Elm-like architecture.
Seed is a Rust front-end framework for creating fast and reliable web apps with an Elm-like architecture.

Seed is a Rust front-end framework for creating fast and reliable web apps with an Elm-like architecture.

Comments
  • Add additional builder for cookie settings

    Add additional builder for cookie settings

    Hi, I'm proposing to add builder options for the rest of the cookie settings in CookieMessageStore. It's useful to be able to set these, for example when testing without https, etc. Please let me know, if there is anything I can do to improve this. All best, Jeremy

    opened by jeremymarch 4
  • Set path on expiry cookie

    Set path on expiry cookie

    I've been running into some issues with my flash messages not expiring correctly when running unit tests (the same issue doesn't seem to happen when testing manually in the browser for some reason).

    I've been able to test that the issue disappears if I set the path of the expiry cookie to be the same as the path on the original cookie. I'm not 100% sure what is going on here, but my theory is that the cookie is not being deleted correctly when identified by only name and not path, and this answer from stack-overflow seems to suggest that is the case: https://stackoverflow.com/a/23995984

    opened by SebRollen 2
  • Add #[must_use] attribute to FlashMessage

    Add #[must_use] attribute to FlashMessage

    This commit adds the #[must_use] attribute to FlashMessage so that a warning is displayed when a user constructs a message without calling send().

    FlashMessage is a good candidate for a #[must_use] attribute, as constructing it by itself with FlashMessage::new(...) or one of its level-specific constructors has no effect; you must call .send() in order to ensure it is sent.

    An example of the warning produced after this commit:

    warning: unused `FlashMessage` that must be used
      --> src/main.rs:19:5
       |
    19 |     FlashMessage::info("Should have warning!");
       |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
       |
       = note: `#[warn(unused_must_use)]` on by default
       = note: You must call `.send()` on a `FlashMessage` for it to have an effect
    
    opened by avandesa 0
Owner
Luca Palmieri
Playing around with Rust, at $dayjob and for fun.
Luca Palmieri
Implementation of the RealWorld backend API spec in Actix, Rust's powerful actor system and most fun web framework.

Actix codebase containing real world examples (CRUD, auth, advanced patterns, etc) that adheres to the RealWorld spec and API. ❗ (2021/05/13) This cod

Allen 475 Jan 2, 2023
Web Application with using Rust(Actix, Diesel and etc)

Santa Service App Used technology stack Web Server with using Rust (Actix, Actix-web, Diesel) Data base (Postgres) Console Application (Tokio) Tasks o

null 3 Jan 8, 2023
A simple authentication flow using Rust and Actix-web, with a PostgreSQL database and a sveltekit frontend.

Rust-auth-example This repository aims to represent a simple authentication flow using Rust and Actix-web, with a PostgreSQL database and a sveltekit

Kival Mahadew 4 Feb 19, 2023
An API project using Rust, Actix Web and JWT. *WIP*

Actix-web REST API with JWT (WIP) A simple CRUD backend app using Actix-web, Diesel and JWT Require Rust Stable Postgres Or using Docker How to run Ma

Akhil Sharma 4 Sep 21, 2023
A newsletter with actix-web and sqlx-postgres

Newsletter backend Health check: production Pre-requisites You'll need to install: Rust Docker There are also some OS-specific requirements. Windows c

Nadeem Bhati 4 Dec 10, 2022
RESTful Todo API with Actix-web and SeaORM. Documented by swagger-ui

RESTful Todo RESTful Todo API with Actix and SeaORM. Documented by swagger-ui Prerequisites Rust Usage Clone the repository and run the following comm

Awiteb 4 Dec 27, 2022
Sauron is an html web framework for building web-apps. It is heavily inspired by elm.

sauron Guide Sauron is an web framework for creating fast and interactive client side web application, as well as server-side rendering for back-end w

Jovansonlee Cesar 1.7k Dec 26, 2022
a port of yaxpeax-dis that runs as a web application

this a rough translation of yaxpeax-dis, the CLI tool, to instead accept architectures and data to disassemble as an HTTP request. the package is then deployed to dis.yaxpeax.net as a compute@edge application.

iximeow 5 Aug 8, 2021
Hot reload static web server for deploying mutiple static web site with version control.

SPA-SERVER It is to provide a static web http server with cache and hot reload. 中文 README Feature Built with Hyper and Warp, fast and small! SSL with

null 7 Dec 18, 2022
Code template for a production Web Application using Axum: The AwesomeApp Blueprint for Professional Web Development.

AwesomeApp rust-web-app More info at: https://awesomeapp.dev/rust-web-app/ rust-web-app YouTube episodes: Episode 01 - Rust Web App - Course to Produc

null 45 Sep 6, 2023