Rust library to generate static websites
at fix/misc-errors 101 lines 3.3 kB view raw
1use axum::{body::Body, http::Uri, response::Response}; 2use colored::Colorize; 3use local_ip_address::local_ip; 4use quanta::Instant; 5use std::{ 6 net::{IpAddr, SocketAddr}, 7 time::Duration, 8}; 9use tokio::net::TcpSocket; 10use tower_http::trace::OnResponse; 11use tracing::{Span, debug, info}; 12 13use crate::logging::{FormatElapsedTimeOptions, format_elapsed_time}; 14 15pub fn log_server_start(start_time: Instant, host: bool, addr: SocketAddr, server_type: &str) { 16 info!(name: "SKIP_FORMAT", ""); 17 let elapsed_time = format_elapsed_time( 18 start_time.elapsed(), 19 &FormatElapsedTimeOptions::default_dev(), 20 ); 21 info!(name: "SKIP_FORMAT", "{} {}", "Maudit 👑".bold().bright_red(), format!("{} server started in {}", server_type, elapsed_time)); 22 info!(name: "SKIP_FORMAT", ""); 23 24 let port = addr.port(); 25 let url = format!("\x1b]8;;http://localhost:{port}\x1b\\http://localhost:{port}\x1b]8;;\x1b\\") 26 .bold() 27 .underline() 28 .bright_blue(); 29 let network_url = if host { 30 let local_ip = local_ip().unwrap(); 31 format!("\x1b]8;;http://{local_ip}:{port}\x1b\\http://{local_ip}:{port}\x1b]8;;\x1b\\") 32 .bold() 33 .underline() 34 .bright_magenta() 35 } else { 36 "Use --host to expose the server to your network".dimmed() 37 }; 38 info!(name: "SKIP_FORMAT", "🮔 {} {}", "Local".bold(), url); 39 info!(name: "SKIP_FORMAT", "🮔 {} {}", "Network".bold(), network_url); 40 info!(name: "SKIP_FORMAT", ""); 41 42 info!(name: "server", "{}", "waiting for requests...".dimmed()); 43} 44 45#[derive(Clone, Debug)] 46pub struct CustomOnResponse; 47 48impl OnResponse<Body> for CustomOnResponse { 49 fn on_response(self, response: &Response<Body>, latency: Duration, _span: &Span) { 50 let status = response.status(); 51 52 // Skip informational responses 53 if status.is_informational() { 54 return; 55 } 56 57 let status = if status.is_server_error() { 58 status.to_string().red() 59 } else if status.is_client_error() { 60 status.to_string().yellow() 61 } else { 62 status.to_string().green() 63 }; 64 65 // There's allegedly a way to get the request URI from the span, but I can't figure it out 66 let uri = response 67 .extensions() 68 .get::<Uri>() 69 .unwrap_or(&Uri::default()) 70 .to_string() 71 .bold(); 72 73 let latency = format_elapsed_time(latency, &FormatElapsedTimeOptions::default()); 74 75 let message = format!("{} {} {}", status, uri, latency); 76 77 info!(name: "", "{}", message); 78 } 79} 80 81pub async fn find_open_port(address: &IpAddr, starting_port: u16) -> u16 { 82 let mut port = starting_port; 83 84 loop { 85 let socket = TcpSocket::new_v4().unwrap(); 86 let socket_addr = SocketAddr::new(*address, port); 87 match socket.bind(socket_addr) { 88 Ok(_) => { 89 debug!("Found open port: {}", port); 90 return port; 91 } 92 Err(_) => { 93 debug!( 94 "Port {} is already in use or failed to bind, trying next one", 95 port 96 ); 97 port += 1; 98 } 99 } 100 } 101}