|
1 | 1 | use anyhow::Context; |
2 | 2 | use axum::{ |
3 | 3 | body::Body, |
4 | | - extract::Request, |
| 4 | + extract::{ConnectInfo, Request}, |
5 | 5 | http::{HeaderMap, HeaderValue, Method, Response, StatusCode}, |
6 | 6 | middleware::Next, |
7 | 7 | response::IntoResponse, |
@@ -590,74 +590,111 @@ async fn main() { |
590 | 590 | } |
591 | 591 | }); |
592 | 592 |
|
593 | | - let address = SocketAddr::from((state.config.api.host, state.config.api.port)); |
| 593 | + if let Ok(host) = state.config.api.host.parse::<std::net::IpAddr>() { |
| 594 | + let address = SocketAddr::from((host, state.config.api.port)); |
594 | 595 |
|
595 | | - if config.api.ssl.enabled { |
596 | | - tracing::info!("loading ssl certs"); |
| 596 | + if config.api.ssl.enabled { |
| 597 | + tracing::info!("loading ssl certs"); |
597 | 598 |
|
598 | | - let config = axum_server::tls_rustls::RustlsConfig::from_pem_file( |
599 | | - config.api.ssl.cert.as_str(), |
600 | | - config.api.ssl.key.as_str(), |
601 | | - ) |
602 | | - .await |
603 | | - .context("failed to load SSL certificate and key") |
604 | | - .unwrap(); |
| 599 | + let config = axum_server::tls_rustls::RustlsConfig::from_pem_file( |
| 600 | + config.api.ssl.cert.as_str(), |
| 601 | + config.api.ssl.key.as_str(), |
| 602 | + ) |
| 603 | + .await |
| 604 | + .context("failed to load SSL certificate and key") |
| 605 | + .unwrap(); |
605 | 606 |
|
606 | | - tracing::info!( |
607 | | - "{} listening on {}", |
608 | | - "https server".bright_red(), |
609 | | - address.to_string().cyan(), |
610 | | - ); |
| 607 | + tracing::info!( |
| 608 | + "{} listening on {}", |
| 609 | + "https server".bright_red(), |
| 610 | + address.to_string().cyan(), |
| 611 | + ); |
611 | 612 |
|
612 | | - match axum_server::bind_rustls(address, config) |
613 | | - .serve(router.into_make_service_with_connect_info::<SocketAddr>()) |
614 | | - .await |
615 | | - { |
616 | | - Ok(_) => {} |
617 | | - Err(err) => { |
618 | | - if err.kind() == std::io::ErrorKind::AddrInUse { |
619 | | - tracing::error!("failed to start https server (address already in use)"); |
620 | | - } else { |
621 | | - tracing::error!("failed to start https server: {:?}", err,); |
622 | | - } |
| 613 | + match axum_server::bind_rustls(address, config) |
| 614 | + .serve(router.into_make_service_with_connect_info::<SocketAddr>()) |
| 615 | + .await |
| 616 | + { |
| 617 | + Ok(_) => {} |
| 618 | + Err(err) => { |
| 619 | + if err.kind() == std::io::ErrorKind::AddrInUse { |
| 620 | + tracing::error!("failed to start https server (address already in use)"); |
| 621 | + } else { |
| 622 | + tracing::error!("failed to start https server: {:?}", err,); |
| 623 | + } |
623 | 624 |
|
624 | | - std::process::exit(1); |
| 625 | + std::process::exit(1); |
| 626 | + } |
625 | 627 | } |
626 | | - } |
627 | | - } else { |
628 | | - tracing::info!( |
629 | | - "{} listening on {}", |
630 | | - "http server".bright_red(), |
631 | | - address.to_string().cyan(), |
632 | | - ); |
| 628 | + } else { |
| 629 | + tracing::info!( |
| 630 | + "{} listening on {}", |
| 631 | + "http server".bright_red(), |
| 632 | + address.to_string().cyan(), |
| 633 | + ); |
633 | 634 |
|
634 | | - match axum::serve( |
635 | | - match tokio::net::TcpListener::bind(address).await { |
636 | | - Ok(listener) => listener, |
| 635 | + match axum::serve( |
| 636 | + match tokio::net::TcpListener::bind(address).await { |
| 637 | + Ok(listener) => listener, |
| 638 | + Err(err) => { |
| 639 | + if err.kind() == std::io::ErrorKind::AddrInUse { |
| 640 | + tracing::error!("failed to start http server (address already in use)"); |
| 641 | + std::process::exit(1); |
| 642 | + } else { |
| 643 | + tracing::error!("failed to start http server: {:?}", err); |
| 644 | + std::process::exit(1); |
| 645 | + } |
| 646 | + } |
| 647 | + }, |
| 648 | + router.into_make_service_with_connect_info::<SocketAddr>(), |
| 649 | + ) |
| 650 | + .await |
| 651 | + { |
| 652 | + Ok(_) => {} |
637 | 653 | Err(err) => { |
638 | 654 | if err.kind() == std::io::ErrorKind::AddrInUse { |
639 | 655 | tracing::error!("failed to start http server (address already in use)"); |
640 | | - std::process::exit(1); |
641 | 656 | } else { |
642 | 657 | tracing::error!("failed to start http server: {:?}", err); |
643 | | - std::process::exit(1); |
644 | 658 | } |
| 659 | + |
| 660 | + std::process::exit(1); |
645 | 661 | } |
646 | | - }, |
647 | | - router.into_make_service_with_connect_info::<SocketAddr>(), |
648 | | - ) |
649 | | - .await |
| 662 | + } |
| 663 | + } |
| 664 | + } else { |
| 665 | + #[cfg(unix)] |
650 | 666 | { |
651 | | - Ok(_) => {} |
652 | | - Err(err) => { |
653 | | - if err.kind() == std::io::ErrorKind::AddrInUse { |
654 | | - tracing::error!("failed to start http server (address already in use)"); |
655 | | - } else { |
656 | | - tracing::error!("failed to start http server: {:?}", err); |
657 | | - } |
| 667 | + let socket_path = &state.config.api.host; |
658 | 668 |
|
659 | | - std::process::exit(1); |
660 | | - } |
| 669 | + tracing::info!( |
| 670 | + "{} listening on {}", |
| 671 | + "http server".bright_red(), |
| 672 | + socket_path.cyan(), |
| 673 | + ); |
| 674 | + |
| 675 | + let router = router.layer(axum::middleware::from_fn( |
| 676 | + |mut req: Request, next: Next| async move { |
| 677 | + req.extensions_mut().insert(ConnectInfo(SocketAddr::from(( |
| 678 | + std::net::IpAddr::from([127, 0, 0, 1]), |
| 679 | + 0, |
| 680 | + )))); |
| 681 | + next.run(req).await |
| 682 | + }, |
| 683 | + )); |
| 684 | + |
| 685 | + let _ = tokio::fs::remove_file(socket_path).await; |
| 686 | + |
| 687 | + let listener = tokio::net::UnixListener::bind(socket_path).unwrap(); |
| 688 | + |
| 689 | + axum::serve(listener, router.into_make_service()) |
| 690 | + .await |
| 691 | + .unwrap(); |
| 692 | + } |
| 693 | + |
| 694 | + #[cfg(not(unix))] |
| 695 | + { |
| 696 | + tracing::error!("unix socket support is only available on unix systems"); |
| 697 | + std::process::exit(1); |
661 | 698 | } |
662 | 699 | } |
663 | 700 | } |
0 commit comments