I have this Macgyver-esque desire to know how to take a device and make it do something else, something it wasn't intended to do; I want to be able to take scrap electronics, take pieces from them and create something practical and useful
In that desire to understand electronics, came a desire to learn low-level programming like you would for small devices. Like common devices in your home, stuff like the software that makes a home projector run, or your smart thermostat. Even older TV's have some sort of basic software running them. Even seemingly basic stuff like your keyboard, bluetooth headphones, TV Remote.
Almost any device you have has some sort of chip set in it. If it has chips in it, one of those is responsible for telling everything else what to do and when.
These devices can be pretty tiny which means the software on it has to be extremly small and sometimes you don't have room for a language like python. In those cases people turn to a "low-level" language, like the language simply called 'C'. Back in the day C was considered a high-level languages. Assembly was a low level language
Anyway, long story short, Rust is the new and improved low-level language because I've been hearing recently that C has some vulnerabilities that are hard to patch due to human inclination for mistakes. SO since this was on the path to learning a low level language I decided to do it. And another recent obsession I've had is how to code and pick a tech stack that is super fast. It almost sounds like the rule is, any language is faster without libraries because of the added bloat that comes with other languages.
Additionally CMS systems like Wordpress are super slow because they have a lot of power and capabilities and can be extremely user friendly but that comes at the cost of speed.
So i picked Rust because I wanted to learn Rust, learn more about servers and have something real fast.
I used chatgpt from beginning to end. No help from google or other sources. I couldn't even help me because I don't know Rust! We did HTTPS and SSL support which involved redirecting and referencing SSL certificates. Chatgpt even helped me write a systemd file so that I can manage it as a background service and doesn't need me to manually start it. It's working great so far. It took me about 3 or 4 hours to complete it and get it deployed on my production server.
The speeds are comparable to Nginx and it's faster than Apache Web Server for sure (Which i'm so sad about because I love that web server) on my site I'm getting 0.8s on mobile and 0.2 seconds on desktop which I think is pretty impressive considering I know nothing about Rust or low-level programming and I know relatively little about web servers
This project was not as straightforward as I'd hoped. There was A LOT of back and forth with ChatGPT trying to figure out the errors.
It's fun and I want to do more low-level coding for hardware and also do some hardware hacking and I think understanding these concepts will be helpful so I will continue to use Rust as projects come up. I might even go out of my way to seek out Rust projects, we'll see.
use std::{fs::File, io::BufReader, sync::Arc};
use tokio::net::TcpListener;
use tokio_rustls::{TlsAcceptor, rustls::{Certificate, PrivateKey, ServerConfig}};
use warp::hyper::server::conn::Http;
use warp::Filter;
#[tokio::main]
async fn main() {
// HTTPS Server Configuration
let cert_file = &mut BufReader::new(File::open("/etc/letsencrypt/live/your-site.com/fullchain.pem")
.expect("Certificate not found"));
let key_file = &mut BufReader::new(File::open("/etc/letsencrypt/live/your-site.com/privkey.pem")
.expect("Key not found"));
let certs = rustls_pemfile::certs(cert_file)
.expect("Error reading certificates")
.into_iter()
.map(Certificate)
.collect();
let keys = rustls_pemfile::pkcs8_private_keys(key_file)
.expect("Error reading private keys")
.into_iter()
.map(PrivateKey)
.collect::>();
let config = ServerConfig::builder()
.with_safe_defaults()
.with_no_client_auth()
.with_single_cert(certs, keys[0].clone())
.expect("Error building TLS config");
let acceptor = TlsAcceptor::from(Arc::new(config));
// Warp filter to serve static files from "./public"
let static_files = warp::fs::dir("./public");
// Start HTTP-to-HTTPS redirect server
tokio::spawn(async {
let http_listener = TcpListener::bind("0.0.0.0:80")
.await
.expect("Failed to bind HTTP listener");
println!("HTTP server running on http://jordancrandell.com");
loop {
let (mut socket, _) = http_listener.accept().await.expect("Failed to accept HTTP connection");
// Redirect HTTP to HTTPS
let redirect = "HTTP/1.1 301 Moved Permanently\r\n\
Location: https://jordancrandell.com\r\n\
Connection: close\r\n\r\n";
if let Err(e) = tokio::io::AsyncWriteExt::write_all(&mut socket, redirect.as_bytes()).await {
eprintln!("Failed to send HTTP redirect: {}", e);
}
}
});
// Start HTTPS server
let https_listener = TcpListener::bind("0.0.0.0:443")
.await
.expect("Failed to bind HTTPS listener");
println!("HTTPS server running on https://jordancrandell.com");
// Handle incoming HTTPS connections
loop {
let (stream, addr) = https_listener.accept().await.expect("Failed to accept HTTPS connection");
let acceptor = acceptor.clone();
let static_files_filter = static_files.clone();
tokio::spawn(async move {
match acceptor.accept(stream).await {
Ok(tls_stream) => {
println!("TLS connection established with {}", addr);
// Use Warp's hyper-based server to handle the stream
if let Err(err) = Http::new()
.serve_connection(tls_stream, warp::service(static_files_filter))
.await
{
eprintln!("Failed to serve connection: {}", err);
}
}
Err(err) => {
eprintln!("Failed to establish TLS connection: {}", err);
}
}
});
}
}
Home