Redirect HTTP to HTTPS in tls-rustls example (#1166)

This commit is contained in:
Sugih Jamin 2022-07-23 04:23:40 -04:00 committed by GitHub
parent bb309319ff
commit 4558671a0b
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23

View file

@ -4,11 +4,24 @@
//! cd examples && cargo run -p example-tls-rustls //! cd examples && cargo run -p example-tls-rustls
//! ``` //! ```
use axum::{routing::get, Router}; use axum::{
extract::Host,
handler::Handler,
http::{StatusCode, Uri},
response::Redirect,
routing::get,
BoxError, Router,
};
use axum_server::tls_rustls::RustlsConfig; use axum_server::tls_rustls::RustlsConfig;
use std::{net::SocketAddr, path::PathBuf}; use std::{net::SocketAddr, path::PathBuf};
use tracing_subscriber::{layer::SubscriberExt, util::SubscriberInitExt}; use tracing_subscriber::{layer::SubscriberExt, util::SubscriberInitExt};
#[derive(Clone, Copy)]
struct Ports {
http: u16,
https: u16,
}
#[tokio::main] #[tokio::main]
async fn main() { async fn main() {
tracing_subscriber::registry() tracing_subscriber::registry()
@ -18,6 +31,14 @@ async fn main() {
.with(tracing_subscriber::fmt::layer()) .with(tracing_subscriber::fmt::layer())
.init(); .init();
let ports = Ports {
http: 7878,
https: 3000,
};
// optional: spawn a second server to redirect http requests to this server
tokio::spawn(redirect_http_to_https(ports));
// configure certificate and private key used by https
let config = RustlsConfig::from_pem_file( let config = RustlsConfig::from_pem_file(
PathBuf::from(env!("CARGO_MANIFEST_DIR")) PathBuf::from(env!("CARGO_MANIFEST_DIR"))
.join("self_signed_certs") .join("self_signed_certs")
@ -31,8 +52,9 @@ async fn main() {
let app = Router::new().route("/", get(handler)); let app = Router::new().route("/", get(handler));
let addr = SocketAddr::from(([127, 0, 0, 1], 3000)); // run https server
println!("listening on {}", addr); let addr = SocketAddr::from(([127, 0, 0, 1], ports.https));
tracing::debug!("listening on {}", addr);
axum_server::bind_rustls(addr, config) axum_server::bind_rustls(addr, config)
.serve(app.into_make_service()) .serve(app.into_make_service())
.await .await
@ -42,3 +64,38 @@ async fn main() {
async fn handler() -> &'static str { async fn handler() -> &'static str {
"Hello, World!" "Hello, World!"
} }
async fn redirect_http_to_https(ports: Ports) {
fn make_https(host: String, uri: Uri, ports: Ports) -> Result<Uri, BoxError> {
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));
tracing::debug!("http redirect listening on {}", addr);
axum::Server::bind(&addr)
.serve(redirect.into_make_service())
.await
.unwrap();
}