Skip to content

Hands-On Guide: How to Use MessagePack to Optimize Data Transmission in HTTP Interfaces with Rust

kingzcheung
Published date:
Edit this post

MessagePack is an efficient binary serialization format. It supports multi-language data exchange. Compared to JSON, it is more compact and faster in processing.

MessagePack has a smaller data size. This means it occupies less bandwidth during transmission and is faster. Compared to JSON, MessagePack supports more primitive data types, including 8-bit to 64-bit integers, floating-point numbers, timestamps, and custom extension types.

Despite these advantages, MessagePack has existed for more than a decade. Many experienced developers have never heard of it. This indicates that its popularity is relatively low.

Main Advantages

In my opinion, the greatest advantage of MessagePack is its support for raw binary data.

Imagine a scenario: you need to upload file or image data through an HTTP interface.

There are typically two solutions:

If you also need to pass other parameters, you can only choose the second method according to the specifications. However, if you need structured parameters, multipart/form-data is not convenient. Although some web frameworks can make it behave similarly to JSON, the processing flow is different.

In this case, MessagePack is a good choice. It allows you to include JSON-like data in the request body while supporting binary data.

Usage Method

In Rust, you can use it through the following dependency:

[dependencies]
rmp-serde = "1.3.0"

Assume there is an interface that needs to send text and binary image data:

#[derive(Debug, PartialEq, Deserialize, Serialize)]
struct Message {
    id: i32,
    text: String,
    image: Vec<u8>,
}

Serialization code is as follows:

fn main() {
    let img = include_bytes!("../img.png");

    let msg = Message {
        id: 1,
        text: "Hello, world!".to_string(),
        image: img.to_vec(),
    };
    let mut buf = Vec::new();
    msg.serialize(&mut Serializer::new(&mut buf)).unwrap();

    println!("{:?}", buf);
}

When transmitting MessagePack data, the request header Content-Type can be:

Application in Web Frameworks

If you are developing a Rust project with Axum, you can add this crate:

cargo add axum-msgpack

Usage is very simple:

async fn post_handler(MsgPack(msg): MsgPack<Message>) -> Html<String> {
    let img = msg.image;
    // More operations
    "OK"
}

Returning MessagePack data is also easy:

async fn get_handler() -> MsgPack<Message> {
    let img = include_bytes!("../img.png");

    let msg = Message {
        id: 1,
        text: "Hello, world!".to_string(),
        image: img.to_vec(),
    };
    MsgPack(msg)
}

Support Level

Since MessagePack is simple to implement, almost all mainstream programming languages support it. For more details, see here.

For example, calling it in JavaScript/TypeScript:

import { deepStrictEqual } from "assert";
import { encode, decode } from "@msgpack/msgpack";

const object = {
  id: 1,
  text: "Hello, world!",
  image: Uint8Array.from([1, 2, 3]),
};

const encoded: Uint8Array = encode(object);

// encoded can be put into the http body to transmit to the backend.

deepStrictEqual(decode(encoded), object);
Previous
实战指南:在 Rust 中使用 Qwen 和知识库通过 RAG 构建高效 LLM 应用
Next
实战指南:如何在Rust中使用MessagePack优化HTTP接口的数据传输