//! Run with //! //! ```not_rust //! cargo run -p example-tls-graceful-shutdown //! ``` fn main() { // This example has not yet been updated to Hyper 1.0 } //use axum::{ // extract::Host, // handler::HandlerWithoutStateExt, // http::{StatusCode, Uri}, // response::Redirect, // routing::get, // BoxError, Router, //}; //use axum_server::tls_rustls::RustlsConfig; //use std::{future::Future, net::SocketAddr, path::PathBuf, time::Duration}; //use tokio::signal; //use tracing_subscriber::{layer::SubscriberExt, util::SubscriberInitExt}; //#[derive(Clone, Copy)] //struct Ports { // http: u16, // https: u16, //} //#[tokio::main] //async fn main() { // tracing_subscriber::registry() // .with( // tracing_subscriber::EnvFilter::try_from_default_env() // .unwrap_or_else(|_| "example_tls_graceful_shutdown=debug".into()), // ) // .with(tracing_subscriber::fmt::layer()) // .init(); // let ports = Ports { // http: 7878, // https: 3000, // }; // //Create a handle for our TLS server so the shutdown signal can all shutdown // let handle = axum_server::Handle::new(); // //save the future for easy shutting down of redirect server // let shutdown_future = shutdown_signal(handle.clone()); // // optional: spawn a second server to redirect http requests to this server // tokio::spawn(redirect_http_to_https(ports, shutdown_future)); // // configure certificate and private key used by https // let config = RustlsConfig::from_pem_file( // PathBuf::from(env!("CARGO_MANIFEST_DIR")) // .join("self_signed_certs") // .join("cert.pem"), // PathBuf::from(env!("CARGO_MANIFEST_DIR")) // .join("self_signed_certs") // .join("key.pem"), // ) // .await // .unwrap(); // let app = Router::new().route("/", get(handler)); // // run https server // let addr = SocketAddr::from(([127, 0, 0, 1], ports.https)); // tracing::debug!("listening on {addr}"); // axum_server::bind_rustls(addr, config) // .handle(handle) // .serve(app.into_make_service()) // .await // .unwrap(); //} //async fn shutdown_signal(handle: axum_server::Handle) { // let ctrl_c = async { // signal::ctrl_c() // .await // .expect("failed to install Ctrl+C handler"); // }; // #[cfg(unix)] // let terminate = async { // signal::unix::signal(signal::unix::SignalKind::terminate()) // .expect("failed to install signal handler") // .recv() // .await; // }; // #[cfg(not(unix))] // let terminate = std::future::pending::<()>(); // tokio::select! { // _ = ctrl_c => {}, // _ = terminate => {}, // } // tracing::info!("Received termination signal shutting down"); // handle.graceful_shutdown(Some(Duration::from_secs(10))); // 10 secs is how long docker will wait // // to force shutdown //} //async fn handler() -> &'static str { // "Hello, World!" //} //async fn redirect_http_to_https(ports: Ports, signal: impl Future) { // fn make_https(host: String, uri: Uri, ports: Ports) -> Result { // let mut parts = uri.into_parts(); // parts.scheme = Some(axum::http::uri::Scheme::HTTPS); // if parts.path_and_query.is_none() { // parts.path_and_query = Some("/".parse().unwrap()); // } // let https_host = host.replace(&ports.http.to_string(), &ports.https.to_string()); // parts.authority = Some(https_host.parse()?); // Ok(Uri::from_parts(parts)?) // } // let redirect = move |Host(host): Host, uri: Uri| async move { // match make_https(host, uri, ports) { // Ok(uri) => Ok(Redirect::permanent(&uri.to_string())), // Err(error) => { // tracing::warn!(%error, "failed to convert URI to HTTPS"); // Err(StatusCode::BAD_REQUEST) // } // } // }; // let addr = SocketAddr::from(([127, 0, 0, 1], ports.http)); // //let listener = tokio::net::TcpListener::bind(addr).await.unwrap(); // tracing::debug!("listening on {addr}"); // hyper::Server::bind(&addr) // .serve(redirect.into_make_service()) // .with_graceful_shutdown(signal) // .await // .unwrap(); //}