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.