Porting the C# clippy app to Rust

Last week, I wrote a little hello world app that responds to HTTP requests with a clippy ASCII art. But the docker image for the app was 111MB in size.

So today, I decided to port the app to rust.

If you only want to see the code, here you go. Here's the PR.

It took me 3 hours to port the app, whereas writing the C# app had barely taken me 5 minutes. I ended up spending most of the time trying to decide which web-framework to use, and the rest of the time trying to put together a Dockerfile.

The rust code in itself was straightforward. I chose to use a web-framework called axum, and they already have a huge list of examples in their GitHub repository.

Here's my rust code:

use axum::{response::Result, Router};
use std::net::SocketAddr;
use std::env;

const CLIPPY:&str = r#"

         __
        /  \        _____________
        |  |       /             \
        @  @       | It looks    |
        || ||      | like you    |
        || ||   <--| are very    |
        |\_/|      | bored.      |
        \___/      \_____________/

"#;
const PORT_ENV_VAR:&str = "APP_PORT";

#[tokio::main]
async fn main() {

    // build our application with a fallback route
    let app = Router::new().fallback(handler);

    // run it
    let addr = SocketAddr::from(([0, 0, 0, 0], get_port()));
    println!("listening on {}", addr);
    axum::Server::bind(&addr)
        .serve(app.into_make_service())
        .await
        .unwrap();
}

async fn handler() -> Result<&'static str> {
    Ok(CLIPPY)
}

fn get_port() -> u16 {
    env::var(PORT_ENV_VAR)
        .unwrap_or("NOT_SET".to_string())
        .parse::<u16>()
        .unwrap_or(3000)
}

It's not very different from C# if you think about it.
It's almost as if C++ and C# had a baby.

Since the goal of the rewrite was to reduce the docker image size, here are some size stats:

Final Image Language Size
ubuntu:lunar C# 160MB
ubuntu/dotnet-deps:7.0_edge C# 111MB
alpine:latest Rust 13.1MB
scratch Rust 6MB

Mission accomplished.