Skip to content

Make page tokens shorter #923

Open
Open
@david-crespo

Description

@david-crespo

This is helpful but not essential for oxidecomputer/console#1102, putting page tokens in console URLs. The real blocker is #436.


Page tokens are base64ed JSON and they come out pretty long. Here's an example:

> atob('eyJ2IjoidjEiLCJwYWdlX3N0YXJ0Ijp7InNvcnRfYnkiOiJuYW1lX2FzY2VuZGluZyIsInByb2plY3QiOiJhbGFuIiwibGFzdF9zZWVuIjoienp6LWluc3QtMTE0In19')
'{"v":"v1","page_start":{"sort_by":"name_ascending","project":"alan","last_seen":"zzz-inst-114"}}' 

oxiderack.com/projects/mock-project/instances?page=eyJ2IjoidjEiLCJwYWdlX3N0YXJ0Ijp7InNvcnRfYnkiOiJuYW1lX2FzY2VuZGluZyIsInByb2plY3QiOiJhbGFuIiwibGFzdF9zZWVuIjoienp6LWluc3QtMTE0In19 would work fine I guess, but to me it looks a bit silly. Here's where we do the serialization:

let token_bytes = {
let serialized_token =
SerializedToken { v: PaginationVersion::V1, page_start };
let json_bytes =
serde_json::to_vec(&serialized_token).map_err(|e| {
HttpError::for_internal_error(format!(
"failed to serialize token: {}",
e
))
})?;
URL_SAFE.encode(json_bytes)
};

It should be pretty easy to encode the token in a more efficient format like MessagePack and maybe reduce the size of the data itself by, e.g., making some keys shorter.

Method Length of token
Current: base64 JSON string 128
MessagePack JSON as-is 104
MessagePack JSON with page_start -> p 92
MessagePack struct directly with serde_rmp (code below) 52
Rust program to compare base64 JSON and MessagePack
# Cargo.toml
[package]
name = "serialization-test"
version = "0.1.0"
edition = "2021"

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]
serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0"
rmp-serde = "0.15.4"
base64 = "0.13.0"
// src/main.rs

extern crate base64;
extern crate rmp_serde as rmps;
extern crate serde;
extern crate serde_json;

use serde::{Deserialize, Serialize};
use std::error::Error;

#[derive(Debug, PartialEq, Deserialize, Serialize)]
struct MyStruct {
    v: String,
    page_start: PageStart,
}

#[derive(Debug, PartialEq, Deserialize, Serialize)]
struct PageStart {
    sort_by: String,
    project: String,
    last_seen: String,
}

fn main() -> Result<(), Box<dyn Error>> {
    let data = MyStruct {
        v: "v1".to_owned(),
        page_start: PageStart {
            sort_by: "name_ascending".to_owned(),
            project: "alan".to_owned(),
            last_seen: "zzz-inst-114".to_owned(),
        },
    };

    // Serialize with JSON
    let json_data = serde_json::to_vec(&data)?;
    let encoded_json = base64::encode(&json_data);

    // Serialize with MessagePack
    let msgpack_data = rmps::to_vec(&data)?;
    let encoded_msgpack = base64::encode(&msgpack_data);

    // Compare the lengths of the encoded strings
    println!("Base64 JSON Length: {}", encoded_json.len());
    println!("Base64 MessagePack Length: {}", encoded_msgpack.len());

    Ok(())
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions