[pbs-devel] [PATCH proxmox 15/17] proxmox-rest-server: fix and extend example

Fabian Grünbichler f.gruenbichler at proxmox.com
Wed Mar 26 16:23:19 CET 2025


enabling logging while we are at it (useful when debugging things like
the graceful shutdown implementation).

Signed-off-by: Fabian Grünbichler <f.gruenbichler at proxmox.com>
---
 proxmox-rest-server/Cargo.toml                |  2 +-
 .../examples/minimal-rest-server.rs           | 43 ++++++++++++++++---
 2 files changed, 38 insertions(+), 7 deletions(-)

diff --git a/proxmox-rest-server/Cargo.toml b/proxmox-rest-server/Cargo.toml
index ee253b4f..4a65415c 100644
--- a/proxmox-rest-server/Cargo.toml
+++ b/proxmox-rest-server/Cargo.toml
@@ -31,7 +31,7 @@ percent-encoding.workspace = true
 regex.workspace = true
 serde = { workspace = true, features = [ "derive" ] }
 serde_json.workspace = true
-tokio = { workspace = true, features = ["signal", "process"] }
+tokio = { workspace = true, features = ["macros", "signal", "process"] }
 tokio-openssl.workspace = true
 tokio-stream.workspace = true
 tracing.workspace = true
diff --git a/proxmox-rest-server/examples/minimal-rest-server.rs b/proxmox-rest-server/examples/minimal-rest-server.rs
index 454430fb..7ff2008a 100644
--- a/proxmox-rest-server/examples/minimal-rest-server.rs
+++ b/proxmox-rest-server/examples/minimal-rest-server.rs
@@ -1,20 +1,24 @@
 use std::collections::HashMap;
 use std::future::Future;
 use std::pin::Pin;
-use std::sync::{LazyLock, Mutex};
+use std::sync::{Arc, LazyLock, Mutex};
 
 use anyhow::{bail, format_err, Error};
+use futures::future;
 use http::request::Parts;
 use http::HeaderMap;
 use hyper::{Method, Response};
 
+use hyper_util::server::graceful::GracefulShutdown;
 use proxmox_http::Body;
+use proxmox_log::LevelFilter;
 use proxmox_router::{
     list_subdirs_api_method, Router, RpcEnvironmentType, SubdirMap, UserInformation,
 };
 use proxmox_schema::api;
 
 use proxmox_rest_server::{ApiConfig, AuthError, RestEnvironment, RestServer};
+use tokio::net::TcpListener;
 
 // Create a Dummy User information system
 struct DummyUserInfo;
@@ -191,21 +195,46 @@ const ROUTER: Router = Router::new()
 async fn run() -> Result<(), Error> {
     // we first have to configure the api environment (basedir etc.)
 
+    proxmox_log::Logger::from_env("RUST_LOG", LevelFilter::INFO)
+        .stderr()
+        .init()?;
+
     let config = ApiConfig::new("/var/tmp/", RpcEnvironmentType::PUBLIC)
         .default_api2_handler(&ROUTER)
         .auth_handler_func(check_auth)
         .index_handler_func(get_index);
     let rest_server = RestServer::new(config);
 
+    proxmox_daemon::catch_shutdown_signal(future::pending())?;
+
+    log::info!("creating server..");
+
     // then we have to create a daemon that listens, accepts and serves the api to clients
     proxmox_daemon::server::create_daemon(
         ([127, 0, 0, 1], 65000).into(),
-        move |listener| {
-            let incoming = hyper::server::conn::AddrIncoming::from_listener(listener)?;
-
+        move |listener: TcpListener| {
             Ok(async move {
-                hyper::Server::builder(incoming).serve(rest_server).await?;
-
+                let graceful = Arc::new(GracefulShutdown::new());
+                loop {
+                    let graceful2 = Arc::clone(&graceful);
+                    tokio::select! {
+                        incoming = listener.accept() => {
+                            log::info!("accepted new connection!");
+                            let (conn, _) = incoming?;
+                            let api_service = rest_server.api_service(&conn)?;
+                            tokio::spawn(async move { let res = api_service.serve(conn, Some(graceful2)).await; log::info!("connection finished: {res:?}") });
+                        },
+                        _shutdown = proxmox_daemon::shutdown_future() => {
+                            log::info!("shutdown future triggered!");
+                            break;
+                        }
+                    }
+                }
+                log::info!("count {}", Arc::strong_count(&graceful));
+                if let Some(shutdown) = Arc::into_inner(graceful) {
+                    log::info!("shutting down..");
+                    shutdown.shutdown().await
+                }
                 Ok(())
             })
         },
@@ -213,6 +242,8 @@ async fn run() -> Result<(), Error> {
     )
     .await?;
 
+    log::info!("done - exit server");
+
     Ok(())
 }
 
-- 
2.39.5





More information about the pbs-devel mailing list