1 use std
::sync
::{Arc, Mutex}
;
2 use std
::collections
::HashMap
;
3 use std
::future
::Future
;
6 use anyhow
::{bail, format_err, Error}
;
7 use lazy_static
::lazy_static
;
9 use proxmox
::api
::{api, router::SubdirMap, Router, RpcEnvironmentType, UserInformation}
;
10 use proxmox
::list_subdirs_api_method
;
11 use proxmox_rest_server
::{ApiAuth, ApiConfig, AuthError, RestServer, RestEnvironment}
;
12 // Create a Dummy User info and auth system
13 // Normally this would check and authenticate the user
16 impl UserInformation
for DummyUserInfo
{
17 fn is_superuser(&self, _userid
: &str) -> bool
{
20 fn is_group_member(&self, _userid
: &str, group
: &str) -> bool
{
23 fn lookup_privs(&self, _userid
: &str, _path
: &[&str]) -> u64 {
30 impl ApiAuth
for DummyAuth
{
33 _headers
: &'a http
::HeaderMap
,
34 _method
: &'a hyper
::Method
,
35 ) -> Pin
<Box
<dyn Future
<Output
= Result
<(String
, Box
<dyn UserInformation
+ Sync
+ Send
>), AuthError
>> + Send
+ 'a
>> {
37 // get some global/cached userinfo
38 let userinfo
: Box
<dyn UserInformation
+ Sync
+ Send
> = Box
::new(DummyUserInfo
);
39 // Do some user checks, e.g. cookie/csrf
40 Ok(("User".to_string(), userinfo
))
45 // this should return the index page of the webserver
46 // iow. what the user browses to
49 _env
: RestEnvironment
,
50 _parts
: http
::request
::Parts
,
51 ) -> Pin
<Box
<dyn Future
<Output
= http
::Response
<hyper
::Body
>> + Send
+ 'a
>> {
53 // build an index page
54 http
::Response
::builder()
55 .body("hello world".into())
60 // a few examples on how to do api calls with the Router
63 /// A simple ping method. returns "pong"
64 fn ping() -> Result
<String
, Error
> {
65 Ok("pong".to_string())
69 static ref ITEM_MAP
: Mutex
<HashMap
<String
, String
>> = Mutex
::new(HashMap
::new());
73 /// Lists all current items
74 fn list_items() -> Result
<Vec
<String
>, Error
> {
75 Ok(ITEM_MAP
.lock().unwrap().keys().map(|k
| k
.clone()).collect())
83 description
: "The name",
87 description
: "The value",
92 /// creates a new item
93 fn create_item(name
: String
, value
: String
) -> Result
<(), Error
> {
94 let mut map
= ITEM_MAP
.lock().unwrap();
95 if map
.contains_key(&name
) {
96 bail
!("{} already exists", name
);
99 map
.insert(name
, value
);
109 description
: "The name",
114 /// returns the value of an item
115 fn get_item(name
: String
) -> Result
<String
, Error
> {
116 ITEM_MAP
.lock().unwrap().get(&name
).map(|s
| s
.to_string()).ok_or_else(|| format_err
!("no such item '{}'", name
))
124 description
: "The name",
128 description
: "The value",
134 fn update_item(name
: String
, value
: String
) -> Result
<(), Error
> {
135 if let Some(val
) = ITEM_MAP
.lock().unwrap().get_mut(&name
) {
138 bail
!("no such item '{}'", name
);
148 description
: "The name",
154 fn delete_item(name
: String
) -> Result
<(), Error
> {
155 if ITEM_MAP
.lock().unwrap().remove(&name
).is_none() {
156 bail
!("no such item '{}'", name
);
161 const ITEM_ROUTER
: Router
= Router
::new()
162 .get(&API_METHOD_GET_ITEM
)
163 .put(&API_METHOD_UPDATE_ITEM
)
164 .delete(&API_METHOD_DELETE_ITEM
);
166 const SUBDIRS
: SubdirMap
= &[
170 .get(&API_METHOD_LIST_ITEMS
)
171 .post(&API_METHOD_CREATE_ITEM
)
172 .match_all("name", &ITEM_ROUTER
)
177 .get(&API_METHOD_PING
)
181 const ROUTER
: Router
= Router
::new()
182 .get(&list_subdirs_api_method
!(SUBDIRS
))
185 async
fn run() -> Result
<(), Error
> {
187 // we first have to configure the api environment (basedir etc.)
189 let config
= ApiConfig
::new(
192 RpcEnvironmentType
::PUBLIC
,
193 Arc
::new(DummyAuth {}
),
196 let rest_server
= RestServer
::new(config
);
198 // then we have to create a daemon that listens, accepts and serves
199 // the api to clients
200 proxmox_rest_server
::daemon
::create_daemon(
201 ([127, 0, 0, 1], 65000).into(),
203 let incoming
= hyper
::server
::conn
::AddrIncoming
::from_listener(listener
)?
;
207 hyper
::Server
::builder(incoming
)
219 fn main() -> Result
<(), Error
> {
220 let rt
= tokio
::runtime
::Runtime
::new()?
;
221 rt
.block_on(async { run().await }
)