Skip to content

A multi-codec extractor and response writer for Axum.

License

Apache-2.0, MIT licenses found

Licenses found

Apache-2.0
LICENSE-APACHE
MIT
LICENSE-MIT
Notifications You must be signed in to change notification settings

matteopolak/axum-codec

Folders and files

NameName
Last commit message
Last commit date

Latest commit

096ef7e Â· Feb 22, 2025

History

80 Commits
Dec 21, 2024
Feb 22, 2025
Dec 21, 2024
Feb 22, 2025
Jul 13, 2024
Jul 10, 2024
Feb 22, 2025
Feb 22, 2025
Jul 9, 2024
Jul 9, 2024
Dec 21, 2024
Jul 15, 2024

Repository files navigation

Axum Codec

https://img.shields.io/crates/v/axum-codec https://img.shields.io/docsrs/axum-codec ci status

A body extractor for the Axum web framework.

Features

  • Supports encoding and decoding of various formats with a single extractor.
  • Provides a wrapper for axum::routing::method_routing to automatically encode responses in the correct format according to the specified Accept header (with a fallback to Content-Type, then one of the enabled formats).
  • Provides an attribute macro (under the macros feature) to add derives for all enabled formats to a struct/enum.
  • Zero-copy decoding with BorrowCodec.

Here's a quick example that can do the following:

  • Decode a User from the request body in any of the supported formats.
  • Encode a Greeting to the response body in any of the supported formats.
use axum::{Router, response::IntoResponse};
use axum_codec::{
  response::IntoCodecResponse,
  routing::{get, post},
  Codec, Accept,
};

// Shorthand for the following (assuming all features are enabled):
//
// #[derive(
//   serde::Serialize, serde::Deserialize,
//   bincode::Encode, bincode::Decode,
//   bitcode::Encode, bitcode::Decode,
//   validator::Validate,
// )]
// #[serde(crate = "...")]
// #[bincode(crate = "...")]
// #[bitcode(crate = "...")]
// #[validator(crate = "...")]
#[axum_codec::apply(encode, decode)]
struct User {
  name: String,
  age: u8,
}

async fn me() -> Codec<User> {
  Codec(User {
    name: "Alice".into(),
    age: 42,
  })
}

/// A manual implementation of the handler above.
async fn manual_me(accept: Accept) -> impl IntoResponse {
  Codec(User {
    name: "Alice".into(),
    age: 42,
  })
  .into_codec_response(accept.into())
}

#[axum_codec::apply(encode)]
struct Greeting {
  message: String,
}

/// Specify `impl IntoCodecResponse`, similar to `axum`
async fn greet(Codec(user): Codec<User>) -> impl IntoCodecResponse {
  Codec(Greeting {
    message: format!("Hello, {}! You are {} years old.", user.name, user.age),
  })
}

#[tokio::main]
async fn main() {
  let app: Router = Router::new()
    .route("/me", get(me).into())
    .route("/manual", axum::routing::get(manual_me))
    .route("/greet", post(greet).into());

  let listener = tokio::net::TcpListener::bind(("127.0.0.1", 3000))
    .await
    .unwrap();

  // axum::serve(listener, app).await.unwrap();
}

Feature flags

  • macros: Enables the axum_codec::apply attribute macro.
  • json*: Enables JSON support.
  • form: Enables x-www-form-urlencoded support.
  • msgpack: Enables MessagePack support.
  • bincode: Enables Bincode support.
  • bitcode: Enables Bitcode support.
  • yaml: Enables YAML support.
  • toml: Enables TOML support.
  • aide: Enables support for the Aide documentation library.
  • validator: Enables support for the Validator validation library, validating all input when extracted with Codec<T>.

* Enabled by default.

A note about #[axum::debug_handler]

Since axum-codec uses its own IntoCodecResponse trait for encoding responses, it is not compatible with #[axum::debug_handler]. However, a new #[axum_codec::debug_handler] (and #[axum_codec::debug_middleware]) macro is provided as a drop-in replacement.

Roadmap

  • Add codec! macro for defining custom codecs that use a different subset of enabled formats.

License

Dual-licensed under MIT or Apache License v2.0.