2 use std
::collections
::HashMap
;
3 use std
::future
::Future
;
6 use anyhow
::{bail, format_err, Error}
;
7 use lazy_static
::lazy_static
;
8 use hyper
::{Body, Response, Method}
;
9 use http
::request
::Parts
;
12 use proxmox_schema
::api
;
13 use proxmox_router
::{list_subdirs_api_method, SubdirMap, Router, RpcEnvironmentType, UserInformation}
;
15 use proxmox_rest_server
::{ServerAdapter, ApiConfig, AuthError, RestServer, RestEnvironment}
;
17 // Create a Dummy User information system
20 impl UserInformation
for DummyUserInfo
{
21 fn is_superuser(&self, _userid
: &str) -> bool
{
22 // Always return true here, so we have access to everthing
25 fn is_group_member(&self, _userid
: &str, group
: &str) -> bool
{
28 fn lookup_privs(&self, _userid
: &str, _path
: &[&str]) -> u64 {
35 // implement the server adapter
36 impl ServerAdapter
for MinimalServer
{
38 // normally this would check and authenticate the user
43 ) -> Pin
<Box
<dyn Future
<Output
= Result
<(String
, Box
<dyn UserInformation
+ Sync
+ Send
>), AuthError
>> + Send
>> {
45 // get some global/cached userinfo
46 let userinfo
: Box
<dyn UserInformation
+ Sync
+ Send
> = Box
::new(DummyUserInfo
);
47 // Do some user checks, e.g. cookie/csrf
48 Ok(("User".to_string(), userinfo
))
52 // this should return the index page of the webserver
53 // iow. what the user browses to
56 _env
: RestEnvironment
,
58 ) -> Pin
<Box
<dyn Future
<Output
= Response
<Body
>> + Send
>> {
60 // build an index page
61 http
::Response
::builder()
62 .body("hello world".into())
68 // a few examples on how to do api calls with the Router
71 /// A simple ping method. returns "pong"
72 fn ping() -> Result
<String
, Error
> {
73 Ok("pong".to_string())
77 static ref ITEM_MAP
: Mutex
<HashMap
<String
, String
>> = Mutex
::new(HashMap
::new());
81 /// Lists all current items
82 fn list_items() -> Result
<Vec
<String
>, Error
> {
83 Ok(ITEM_MAP
.lock().unwrap().keys().map(|k
| k
.clone()).collect())
91 description
: "The name",
95 description
: "The value",
100 /// creates a new item
101 fn create_item(name
: String
, value
: String
) -> Result
<(), Error
> {
102 let mut map
= ITEM_MAP
.lock().unwrap();
103 if map
.contains_key(&name
) {
104 bail
!("{} already exists", name
);
107 map
.insert(name
, value
);
117 description
: "The name",
122 /// returns the value of an item
123 fn get_item(name
: String
) -> Result
<String
, Error
> {
124 ITEM_MAP
.lock().unwrap().get(&name
).map(|s
| s
.to_string()).ok_or_else(|| format_err
!("no such item '{}'", name
))
132 description
: "The name",
136 description
: "The value",
142 fn update_item(name
: String
, value
: String
) -> Result
<(), Error
> {
143 if let Some(val
) = ITEM_MAP
.lock().unwrap().get_mut(&name
) {
146 bail
!("no such item '{}'", name
);
156 description
: "The name",
162 fn delete_item(name
: String
) -> Result
<(), Error
> {
163 if ITEM_MAP
.lock().unwrap().remove(&name
).is_none() {
164 bail
!("no such item '{}'", name
);
169 const ITEM_ROUTER
: Router
= Router
::new()
170 .get(&API_METHOD_GET_ITEM
)
171 .put(&API_METHOD_UPDATE_ITEM
)
172 .delete(&API_METHOD_DELETE_ITEM
);
174 const SUBDIRS
: SubdirMap
= &[
178 .get(&API_METHOD_LIST_ITEMS
)
179 .post(&API_METHOD_CREATE_ITEM
)
180 .match_all("name", &ITEM_ROUTER
)
185 .get(&API_METHOD_PING
)
189 const ROUTER
: Router
= Router
::new()
190 .get(&list_subdirs_api_method
!(SUBDIRS
))
193 async
fn run() -> Result
<(), Error
> {
195 // we first have to configure the api environment (basedir etc.)
197 let config
= ApiConfig
::new(
200 RpcEnvironmentType
::PUBLIC
,
203 let rest_server
= RestServer
::new(config
);
205 // then we have to create a daemon that listens, accepts and serves
206 // the api to clients
207 proxmox_rest_server
::daemon
::create_daemon(
208 ([127, 0, 0, 1], 65000).into(),
210 let incoming
= hyper
::server
::conn
::AddrIncoming
::from_listener(listener
)?
;
214 hyper
::Server
::builder(incoming
)
226 fn main() -> Result
<(), Error
> {
227 let rt
= tokio
::runtime
::Runtime
::new()?
;
228 rt
.block_on(async { run().await }
)