public inbox for pbs-devel@lists.proxmox.com
 help / color / mirror / Atom feed
* [pbs-devel] [PATCH proxmox-backup v3 0/3] add rest_server example
@ 2021-09-29  7:04 Dominik Csapak
  2021-09-29  7:04 ` [pbs-devel] [PATCH proxmox-backup v3 1/4] rest-server: use hypers AddrIncoming for proxmox-backup-api Dominik Csapak
                   ` (4 more replies)
  0 siblings, 5 replies; 7+ messages in thread
From: Dominik Csapak @ 2021-09-29  7:04 UTC (permalink / raw)
  To: pbs-devel

adds a rest_server example to the proxmox-rest-server crate.

changes from v2:
* don't use pbs_runtime, but use a stock tokio runtime (cuts the
  pbs-runtime dependency)
* improve commit messages (explain hyper addrincoming, and api call
  paths)
* use proxmox "0.13" dev-dependency instead of "0.13.5"
* use explicit hyper version dependency (0.14.5)

changes from v1:
* added patches so we can remove the (now) unused srt/tools/async_io.rs.
  this enables us to don't have any dependencies on the top-level crate
  for the example, and we can move it into proxmox-rest-server
* use hypers AddrStream for the example

Dominik Csapak (4):
  rest-server: use hypers AddrIncoming for proxmox-backup-api
  remove tools/async_io.rs
  examples: add example for a simple rest server with a small api
  fixup! rest-server: use hypers AddrIncoming for proxmox-backup-api

 proxmox-rest-server/Cargo.toml              |   7 +-
 proxmox-rest-server/examples/rest_server.rs | 220 ++++++++++++++++++++
 proxmox-rest-server/src/rest.rs             |  18 +-
 src/bin/proxmox-backup-api.rs               |   3 +-
 src/tools/async_io.rs                       |  83 --------
 src/tools/mod.rs                            |   1 -
 6 files changed, 236 insertions(+), 96 deletions(-)
 create mode 100644 proxmox-rest-server/examples/rest_server.rs
 delete mode 100644 src/tools/async_io.rs

-- 
2.30.2





^ permalink raw reply	[flat|nested] 7+ messages in thread

* [pbs-devel] [PATCH proxmox-backup v3 1/4] rest-server: use hypers AddrIncoming for proxmox-backup-api
  2021-09-29  7:04 [pbs-devel] [PATCH proxmox-backup v3 0/3] add rest_server example Dominik Csapak
@ 2021-09-29  7:04 ` Dominik Csapak
  2021-09-29  7:04 ` [pbs-devel] [PATCH proxmox-backup v3 2/4] remove tools/async_io.rs Dominik Csapak
                   ` (3 subsequent siblings)
  4 siblings, 0 replies; 7+ messages in thread
From: Dominik Csapak @ 2021-09-29  7:04 UTC (permalink / raw)
  To: pbs-devel

this has a 'from_listener' (tokio::net::TcpListener) since hyper 0.14.5 in
the 'tcp' feature (we use 'full', which includes that; since 0.14.13
it is not behind a feature flag anymore).

this makes it possible to create a hyper server without our
'StaticIncoming' wrapper and thus makes it unnecessary.

The only other thing we have to do is to change the Service impl from
tokio::net::TcpStream to hyper::server::conn::AddStream to fulfill the trait
requirements.

Signed-off-by: Dominik Csapak <d.csapak@proxmox.com>
---
 proxmox-rest-server/src/rest.rs | 18 ++++++++----------
 src/bin/proxmox-backup-api.rs   |  3 ++-
 2 files changed, 10 insertions(+), 11 deletions(-)

diff --git a/proxmox-rest-server/src/rest.rs b/proxmox-rest-server/src/rest.rs
index ba2edf11..8c1e34a3 100644
--- a/proxmox-rest-server/src/rest.rs
+++ b/proxmox-rest-server/src/rest.rs
@@ -93,7 +93,7 @@ impl tower_service::Service<&Pin<Box<tokio_openssl::SslStream<tokio::net::TcpStr
     }
 }
 
-impl tower_service::Service<&tokio::net::TcpStream> for RestServer {
+impl tower_service::Service<&hyper::server::conn::AddrStream> for RestServer {
     type Response = ApiService;
     type Error = Error;
     type Future = Pin<Box<dyn Future<Output = Result<ApiService, Error>> + Send>>;
@@ -102,15 +102,13 @@ impl tower_service::Service<&tokio::net::TcpStream> for RestServer {
         Poll::Ready(Ok(()))
     }
 
-    fn call(&mut self, ctx: &tokio::net::TcpStream) -> Self::Future {
-        match ctx.peer_addr() {
-            Err(err) => future::err(format_err!("unable to get peer address - {}", err)).boxed(),
-            Ok(peer) => future::ok(ApiService {
-                peer,
-                api_config: self.api_config.clone(),
-            })
-            .boxed(),
-        }
+    fn call(&mut self, ctx: &hyper::server::conn::AddrStream) -> Self::Future {
+        let peer =  ctx.remote_addr();
+        future::ok(ApiService {
+            peer,
+            api_config: self.api_config.clone(),
+        })
+        .boxed()
     }
 }
 
diff --git a/src/bin/proxmox-backup-api.rs b/src/bin/proxmox-backup-api.rs
index 86650de6..e3f2531f 100644
--- a/src/bin/proxmox-backup-api.rs
+++ b/src/bin/proxmox-backup-api.rs
@@ -108,7 +108,8 @@ async fn run() -> Result<(), Error> {
     let server = daemon::create_daemon(
         ([127,0,0,1], 82).into(),
         move |listener, ready| {
-            let incoming = proxmox_backup::tools::async_io::StaticIncoming::from(listener);
+            let incoming = hyper::server::conn::AddrIncoming::from_listener(listener)?;
+
             Ok(ready
                 .and_then(|_| hyper::Server::builder(incoming)
                     .serve(rest_server)
-- 
2.30.2





^ permalink raw reply	[flat|nested] 7+ messages in thread

* [pbs-devel] [PATCH proxmox-backup v3 2/4] remove tools/async_io.rs
  2021-09-29  7:04 [pbs-devel] [PATCH proxmox-backup v3 0/3] add rest_server example Dominik Csapak
  2021-09-29  7:04 ` [pbs-devel] [PATCH proxmox-backup v3 1/4] rest-server: use hypers AddrIncoming for proxmox-backup-api Dominik Csapak
@ 2021-09-29  7:04 ` Dominik Csapak
  2021-09-29  7:04 ` [pbs-devel] [PATCH proxmox-backup v3 3/4] examples: add example for a simple rest server with a small api Dominik Csapak
                   ` (2 subsequent siblings)
  4 siblings, 0 replies; 7+ messages in thread
From: Dominik Csapak @ 2021-09-29  7:04 UTC (permalink / raw)
  To: pbs-devel

nothing from here is used anymore, so remove it

Signed-off-by: Dominik Csapak <d.csapak@proxmox.com>
---
 src/tools/async_io.rs | 83 -------------------------------------------
 src/tools/mod.rs      |  1 -
 2 files changed, 84 deletions(-)
 delete mode 100644 src/tools/async_io.rs

diff --git a/src/tools/async_io.rs b/src/tools/async_io.rs
deleted file mode 100644
index 66d38094..00000000
--- a/src/tools/async_io.rs
+++ /dev/null
@@ -1,83 +0,0 @@
-//! AsyncRead/AsyncWrite utilities.
-
-use std::os::unix::io::{AsRawFd, RawFd};
-use std::pin::Pin;
-use std::task::{Context, Poll};
-
-use futures::stream::{Stream, TryStream};
-use futures::ready;
-use tokio::io::{AsyncRead, AsyncWrite};
-use tokio::net::TcpListener;
-
-
-/// Tokio's `Incoming` now is a reference type and hyper's `AddrIncoming` misses some standard
-/// stuff like `AsRawFd`, so here's something implementing hyper's `Accept` from a `TcpListener`
-pub struct StaticIncoming(TcpListener);
-
-impl From<TcpListener> for StaticIncoming {
-    fn from(inner: TcpListener) -> Self {
-        Self(inner)
-    }
-}
-
-impl AsRawFd for StaticIncoming {
-    fn as_raw_fd(&self) -> RawFd {
-        self.0.as_raw_fd()
-    }
-}
-
-impl hyper::server::accept::Accept for StaticIncoming {
-    type Conn = tokio::net::TcpStream;
-    type Error = std::io::Error;
-
-    fn poll_accept(
-        self: Pin<&mut Self>,
-        cx: &mut Context,
-    ) -> Poll<Option<Result<Self::Conn, Self::Error>>> {
-        let this = self.get_mut();
-        loop {
-            match ready!(this.0.poll_accept(cx)) {
-                Ok((conn, _addr)) => return Poll::Ready(Some(Ok(conn))),
-                Err(err) => {
-                    eprintln!("error accepting connection: {}", err);
-                    continue;
-                }
-            }
-        }
-    }
-}
-
-/// We also implement TryStream for this, as tokio doesn't do this anymore either and we want to be
-/// able to map connections to then add eg. ssl to them. This support code makes the changes
-/// required for hyper 0.13 a bit less annoying to read.
-impl Stream for StaticIncoming {
-    type Item = std::io::Result<(tokio::net::TcpStream, std::net::SocketAddr)>;
-
-    fn poll_next(self: Pin<&mut Self>, cx: &mut Context) -> Poll<Option<Self::Item>> {
-        match self.get_mut().0.poll_accept(cx) {
-            Poll::Pending => Poll::Pending,
-            Poll::Ready(result) => Poll::Ready(Some(result)),
-        }
-    }
-}
-
-/// Implement hyper's `Accept` for any `TryStream` of sockets:
-pub struct HyperAccept<T>(pub T);
-
-
-impl<T, I> hyper::server::accept::Accept for HyperAccept<T>
-where
-    T: TryStream<Ok = I> + Unpin,
-    I: AsyncRead + AsyncWrite,
-{
-    type Conn = I;
-    type Error = T::Error;
-
-    fn poll_accept(
-        self: Pin<&mut Self>,
-        cx: &mut Context,
-    ) -> Poll<Option<Result<Self::Conn, Self::Error>>> {
-        let this = Pin::new(&mut self.get_mut().0);
-        this.try_poll_next(cx)
-    }
-}
diff --git a/src/tools/mod.rs b/src/tools/mod.rs
index 5dc129f0..d8ed7275 100644
--- a/src/tools/mod.rs
+++ b/src/tools/mod.rs
@@ -13,7 +13,6 @@ use proxmox_http::{
 };
 
 pub mod apt;
-pub mod async_io;
 pub mod config;
 pub mod disks;
 
-- 
2.30.2





^ permalink raw reply	[flat|nested] 7+ messages in thread

* [pbs-devel] [PATCH proxmox-backup v3 3/4] examples: add example for a simple rest server with a small api
  2021-09-29  7:04 [pbs-devel] [PATCH proxmox-backup v3 0/3] add rest_server example Dominik Csapak
  2021-09-29  7:04 ` [pbs-devel] [PATCH proxmox-backup v3 1/4] rest-server: use hypers AddrIncoming for proxmox-backup-api Dominik Csapak
  2021-09-29  7:04 ` [pbs-devel] [PATCH proxmox-backup v3 2/4] remove tools/async_io.rs Dominik Csapak
@ 2021-09-29  7:04 ` Dominik Csapak
  2021-09-29  7:04 ` [pbs-devel] [PATCH proxmox-backup v3 4/4] fixup! rest-server: use hypers AddrIncoming for proxmox-backup-api Dominik Csapak
  2021-09-29  7:49 ` [pbs-devel] applied-series: [PATCH proxmox-backup v3 0/3] add rest_server example Thomas Lamprecht
  4 siblings, 0 replies; 7+ messages in thread
From: Dominik Csapak @ 2021-09-29  7:04 UTC (permalink / raw)
  To: pbs-devel

show how to generally start a daemon that serves a rest api + index page

api calls are (prefixed with either /api2/json or /api2/extjs):
/		GET	listing
/ping		GET	returns "pong"
/items		GET	lists existing items
		POST	lets user create new items
/items/{id}	GET	returns the content of a single item
		PUT	updates an item
		DELETE	deletes an item

Contains a small dummy user/authinfo

Signed-off-by: Dominik Csapak <d.csapak@proxmox.com>
---
 proxmox-rest-server/Cargo.toml              |   5 +
 proxmox-rest-server/examples/rest_server.rs | 220 ++++++++++++++++++++
 2 files changed, 225 insertions(+)
 create mode 100644 proxmox-rest-server/examples/rest_server.rs

diff --git a/proxmox-rest-server/Cargo.toml b/proxmox-rest-server/Cargo.toml
index b0e53d19..dedeef73 100644
--- a/proxmox-rest-server/Cargo.toml
+++ b/proxmox-rest-server/Cargo.toml
@@ -5,6 +5,11 @@ authors = ["Proxmox Support Team <support@proxmox.com>"]
 edition = "2018"
 description = "REST server implementation"
 
+# for example
+[dev-dependencies]
+proxmox = { version = "0.13", features = ["router","api-macro"] }
+tokio = { version = "1.6", features = [ "rt-multi-thread", "signal", "process" ] }
+
 [dependencies]
 anyhow = "1.0"
 futures = "0.3"
diff --git a/proxmox-rest-server/examples/rest_server.rs b/proxmox-rest-server/examples/rest_server.rs
new file mode 100644
index 00000000..4d0dac35
--- /dev/null
+++ b/proxmox-rest-server/examples/rest_server.rs
@@ -0,0 +1,220 @@
+use std::sync::{Arc, Mutex};
+use std::collections::HashMap;
+
+use anyhow::{bail, format_err, Error};
+use futures::{FutureExt, TryFutureExt};
+use lazy_static::lazy_static;
+
+use proxmox::api::{api, router::SubdirMap, Router, RpcEnvironmentType, UserInformation};
+use proxmox::list_subdirs_api_method;
+use proxmox_rest_server::{ApiAuth, ApiConfig, AuthError, RestServer};
+
+// Create a Dummy User info and auth system
+// Normally this would check and authenticate the user
+struct DummyUserInfo;
+
+impl UserInformation for DummyUserInfo {
+    fn is_superuser(&self, _userid: &str) -> bool {
+        true
+    }
+    fn is_group_member(&self, _userid: &str, group: &str) -> bool {
+        group == "Group"
+    }
+    fn lookup_privs(&self, _userid: &str, _path: &[&str]) -> u64 {
+        u64::MAX
+    }
+}
+
+struct DummyAuth;
+
+impl ApiAuth for DummyAuth {
+    fn check_auth(
+        &self,
+        _headers: &http::HeaderMap,
+        _method: &hyper::Method,
+    ) -> Result<(String, Box<dyn UserInformation + Sync + Send>), AuthError> {
+        // get some global/cached userinfo
+        let userinfo = DummyUserInfo;
+        // Do some user checks, e.g. cookie/csrf
+        Ok(("User".to_string(), Box::new(userinfo)))
+    }
+}
+
+// this should return the index page of the webserver
+// iow. what the user browses to
+
+fn get_index(
+    _auth_id: Option<String>,
+    _language: Option<String>,
+    _api: &ApiConfig,
+    _parts: http::request::Parts,
+) -> http::Response<hyper::Body> {
+    // build an index page
+    http::Response::builder()
+        .body("hello world".into())
+        .unwrap()
+}
+
+// a few examples on how to do api calls with the Router
+
+#[api]
+/// A simple ping method. returns "pong"
+fn ping() -> Result<String, Error> {
+    Ok("pong".to_string())
+}
+
+lazy_static! {
+    static ref ITEM_MAP: Mutex<HashMap<String, String>> = Mutex::new(HashMap::new());
+}
+
+#[api]
+/// Lists all current items
+fn list_items() -> Result<Vec<String>, Error> {
+    Ok(ITEM_MAP.lock().unwrap().keys().map(|k| k.clone()).collect())
+}
+
+#[api(
+    input: {
+        properties: {
+            name: {
+                type: String,
+                description: "The name",
+            },
+            value: {
+                type: String,
+                description: "The value",
+            },
+        },
+    },
+)]
+/// creates a new item
+fn create_item(name: String, value: String) -> Result<(), Error> {
+    let mut map = ITEM_MAP.lock().unwrap();
+    if map.contains_key(&name) {
+        bail!("{} already exists", name);
+    }
+
+    map.insert(name, value);
+
+    Ok(())
+}
+
+#[api(
+    input: {
+        properties: {
+            name: {
+                type: String,
+                description: "The name",
+            },
+        },
+    },
+)]
+/// returns the value of an item
+fn get_item(name: String) -> Result<String, Error> {
+    ITEM_MAP.lock().unwrap().get(&name).map(|s| s.to_string()).ok_or_else(|| format_err!("no such item '{}'", name))
+}
+
+#[api(
+    input: {
+        properties: {
+            name: {
+                type: String,
+                description: "The name",
+            },
+            value: {
+                type: String,
+                description: "The value",
+            },
+        },
+    },
+)]
+/// updates an item
+fn update_item(name: String, value: String) -> Result<(), Error> {
+    if let Some(val) = ITEM_MAP.lock().unwrap().get_mut(&name) {
+        *val = value;
+    } else {
+        bail!("no such item '{}'", name);
+    }
+    Ok(())
+}
+
+#[api(
+    input: {
+        properties: {
+            name: {
+                type: String,
+                description: "The name",
+            },
+        },
+    },
+)]
+/// deletes an item
+fn delete_item(name: String) -> Result<(), Error> {
+    if ITEM_MAP.lock().unwrap().remove(&name).is_none() {
+        bail!("no such item '{}'", name);
+    }
+    Ok(())
+}
+
+const ITEM_ROUTER: Router = Router::new()
+    .get(&API_METHOD_GET_ITEM)
+    .put(&API_METHOD_UPDATE_ITEM)
+    .delete(&API_METHOD_DELETE_ITEM);
+
+const SUBDIRS: SubdirMap = &[
+    (
+        "items",
+        &Router::new()
+            .get(&API_METHOD_LIST_ITEMS)
+            .post(&API_METHOD_CREATE_ITEM)
+            .match_all("name", &ITEM_ROUTER)
+    ),
+    (
+        "ping",
+        &Router::new()
+            .get(&API_METHOD_PING)
+    ),
+];
+
+const ROUTER: Router = Router::new()
+    .get(&list_subdirs_api_method!(SUBDIRS))
+    .subdirs(SUBDIRS);
+
+async fn run() -> Result<(), Error> {
+
+    // we first have to configure the api environment (basedir etc.)
+
+    let config = ApiConfig::new(
+        "/var/tmp/",
+        &ROUTER,
+        RpcEnvironmentType::PUBLIC,
+        Arc::new(DummyAuth {}),
+        get_index,
+    )?;
+    let rest_server = RestServer::new(config);
+
+    // then we have to create a daemon that listens, accepts and serves
+    // the api to clients
+    proxmox_rest_server::daemon::create_daemon(
+        ([127, 0, 0, 1], 65000).into(),
+        move |listener, ready| {
+            let incoming = hyper::server::conn::AddrIncoming::from_listener(listener)?;
+
+            Ok(ready
+                .and_then(|_| hyper::Server::builder(incoming)
+                    .serve(rest_server)
+                    .map_err(Error::from)
+                )
+                .map_err(|err| eprintln!("ERR: {}", err))
+                .map(|test| println!("OK: {}", test.is_ok())))
+        },
+        "example_server",
+    ).await?;
+
+    Ok(())
+}
+
+fn main() -> Result<(), Error> {
+    let rt = tokio::runtime::Runtime::new()?;
+    rt.block_on(async { run().await })
+}
-- 
2.30.2





^ permalink raw reply	[flat|nested] 7+ messages in thread

* [pbs-devel] [PATCH proxmox-backup v3 4/4] fixup! rest-server: use hypers AddrIncoming for proxmox-backup-api
  2021-09-29  7:04 [pbs-devel] [PATCH proxmox-backup v3 0/3] add rest_server example Dominik Csapak
                   ` (2 preceding siblings ...)
  2021-09-29  7:04 ` [pbs-devel] [PATCH proxmox-backup v3 3/4] examples: add example for a simple rest server with a small api Dominik Csapak
@ 2021-09-29  7:04 ` Dominik Csapak
  2021-09-29  7:07   ` Dominik Csapak
  2021-09-29  7:49 ` [pbs-devel] applied-series: [PATCH proxmox-backup v3 0/3] add rest_server example Thomas Lamprecht
  4 siblings, 1 reply; 7+ messages in thread
From: Dominik Csapak @ 2021-09-29  7:04 UTC (permalink / raw)
  To: pbs-devel

Signed-off-by: Dominik Csapak <d.csapak@proxmox.com>
---
 proxmox-rest-server/Cargo.toml | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/proxmox-rest-server/Cargo.toml b/proxmox-rest-server/Cargo.toml
index dedeef73..8fa1a79f 100644
--- a/proxmox-rest-server/Cargo.toml
+++ b/proxmox-rest-server/Cargo.toml
@@ -15,7 +15,7 @@ anyhow = "1.0"
 futures = "0.3"
 handlebars = "3.0"
 http = "0.2"
-hyper = { version = "0.14", features = [ "full" ] }
+hyper = { version = "0.14.5", features = [ "full" ] }
 lazy_static = "1.4"
 libc = "0.2"
 log = "0.4"
-- 
2.30.2





^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [pbs-devel] [PATCH proxmox-backup v3 4/4] fixup! rest-server: use hypers AddrIncoming for proxmox-backup-api
  2021-09-29  7:04 ` [pbs-devel] [PATCH proxmox-backup v3 4/4] fixup! rest-server: use hypers AddrIncoming for proxmox-backup-api Dominik Csapak
@ 2021-09-29  7:07   ` Dominik Csapak
  0 siblings, 0 replies; 7+ messages in thread
From: Dominik Csapak @ 2021-09-29  7:07 UTC (permalink / raw)
  To: pbs-devel

sorry i did miss a
'git rebase -i master --autosquash' before sending... should i send a v4 
for that?




^ permalink raw reply	[flat|nested] 7+ messages in thread

* [pbs-devel] applied-series: [PATCH proxmox-backup v3 0/3] add rest_server example
  2021-09-29  7:04 [pbs-devel] [PATCH proxmox-backup v3 0/3] add rest_server example Dominik Csapak
                   ` (3 preceding siblings ...)
  2021-09-29  7:04 ` [pbs-devel] [PATCH proxmox-backup v3 4/4] fixup! rest-server: use hypers AddrIncoming for proxmox-backup-api Dominik Csapak
@ 2021-09-29  7:49 ` Thomas Lamprecht
  4 siblings, 0 replies; 7+ messages in thread
From: Thomas Lamprecht @ 2021-09-29  7:49 UTC (permalink / raw)
  To: Proxmox Backup Server development discussion, Dominik Csapak

On 29.09.21 09:04, Dominik Csapak wrote:
> adds a rest_server example to the proxmox-rest-server crate.
> 
> changes from v2:
> * don't use pbs_runtime, but use a stock tokio runtime (cuts the
>   pbs-runtime dependency)
> * improve commit messages (explain hyper addrincoming, and api call
>   paths)
> * use proxmox "0.13" dev-dependency instead of "0.13.5"
> * use explicit hyper version dependency (0.14.5)
> 
> changes from v1:
> * added patches so we can remove the (now) unused srt/tools/async_io.rs.
>   this enables us to don't have any dependencies on the top-level crate
>   for the example, and we can move it into proxmox-rest-server
> * use hypers AddrStream for the example
> 
> Dominik Csapak (4):
>   rest-server: use hypers AddrIncoming for proxmox-backup-api
>   remove tools/async_io.rs
>   examples: add example for a simple rest server with a small api
>   fixup! rest-server: use hypers AddrIncoming for proxmox-backup-api
> 
>  proxmox-rest-server/Cargo.toml              |   7 +-
>  proxmox-rest-server/examples/rest_server.rs | 220 ++++++++++++++++++++
>  proxmox-rest-server/src/rest.rs             |  18 +-
>  src/bin/proxmox-backup-api.rs               |   3 +-
>  src/tools/async_io.rs                       |  83 --------
>  src/tools/mod.rs                            |   1 -
>  6 files changed, 236 insertions(+), 96 deletions(-)
>  create mode 100644 proxmox-rest-server/examples/rest_server.rs
>  delete mode 100644 src/tools/async_io.rs
> 



applied, thanks! FYI: I `rebase --fixup`'d the series and renamed the example to
minimal-rest-server for now.




^ permalink raw reply	[flat|nested] 7+ messages in thread

end of thread, other threads:[~2021-09-29  7:50 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-09-29  7:04 [pbs-devel] [PATCH proxmox-backup v3 0/3] add rest_server example Dominik Csapak
2021-09-29  7:04 ` [pbs-devel] [PATCH proxmox-backup v3 1/4] rest-server: use hypers AddrIncoming for proxmox-backup-api Dominik Csapak
2021-09-29  7:04 ` [pbs-devel] [PATCH proxmox-backup v3 2/4] remove tools/async_io.rs Dominik Csapak
2021-09-29  7:04 ` [pbs-devel] [PATCH proxmox-backup v3 3/4] examples: add example for a simple rest server with a small api Dominik Csapak
2021-09-29  7:04 ` [pbs-devel] [PATCH proxmox-backup v3 4/4] fixup! rest-server: use hypers AddrIncoming for proxmox-backup-api Dominik Csapak
2021-09-29  7:07   ` Dominik Csapak
2021-09-29  7:49 ` [pbs-devel] applied-series: [PATCH proxmox-backup v3 0/3] add rest_server example Thomas Lamprecht

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
Service provided by Proxmox Server Solutions GmbH | Privacy | Legal