mirror of
https://git.proxmox.com/git/proxmox
synced 2025-05-29 17:15:57 +00:00
api-test: comments/cleanup
Signed-off-by: Wolfgang Bumiller <w.bumiller@errno.eu>
This commit is contained in:
parent
bb2639bf40
commit
6705d13424
@ -13,76 +13,9 @@ use tokio::io::AsyncReadExt;
|
|||||||
|
|
||||||
use proxmox::api::{api, router};
|
use proxmox::api::{api, router};
|
||||||
|
|
||||||
async fn run_request(request: Request<Body>) -> Result<http::Response<Body>, hyper::Error> {
|
//
|
||||||
match route_request(request).await {
|
// Configuration:
|
||||||
Ok(r) => Ok(r),
|
//
|
||||||
Err(err) => Ok(Response::builder()
|
|
||||||
.status(400)
|
|
||||||
.body(Body::from(format!("ERROR: {}", err)))
|
|
||||||
.expect("building an error response...")),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
async fn route_request(request: Request<Body>) -> Result<http::Response<Body>, Error> {
|
|
||||||
let path = request.uri().path();
|
|
||||||
|
|
||||||
let (target, params) = ROUTER
|
|
||||||
.lookup(path)
|
|
||||||
.ok_or_else(|| format_err!("missing path: {}", path))?;
|
|
||||||
|
|
||||||
target
|
|
||||||
.get
|
|
||||||
.as_ref()
|
|
||||||
.ok_or_else(|| format_err!("no GET method for: {}", path))?
|
|
||||||
.call(params.unwrap_or(Value::Null))
|
|
||||||
.await
|
|
||||||
}
|
|
||||||
|
|
||||||
async fn main_do(www_dir: String) {
|
|
||||||
// Construct our SocketAddr to listen on...
|
|
||||||
let addr = ([0, 0, 0, 0], 3000).into();
|
|
||||||
|
|
||||||
// And a MakeService to handle each connection...
|
|
||||||
let service = make_service_fn(|_| async { Ok::<_, hyper::Error>(service_fn(run_request)) });
|
|
||||||
|
|
||||||
// Then bind and serve...
|
|
||||||
let server = Server::bind(&addr).serve(service);
|
|
||||||
|
|
||||||
println!("Serving {} under http://localhost:3000/www/", www_dir);
|
|
||||||
|
|
||||||
if let Err(e) = server.await {
|
|
||||||
eprintln!("server error: {}", e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn main() {
|
|
||||||
// We expect a path, where to find our files we expose via the www/ dir:
|
|
||||||
let mut args = std::env::args();
|
|
||||||
|
|
||||||
// real code should have better error handling
|
|
||||||
let _program_name = args.next();
|
|
||||||
let www_dir = args.next().expect("expected a www/ subdirectory");
|
|
||||||
set_www_dir(www_dir.to_string());
|
|
||||||
|
|
||||||
// show our api info:
|
|
||||||
println!(
|
|
||||||
"{}",
|
|
||||||
serde_json::to_string_pretty(&ROUTER.api_dump()).unwrap()
|
|
||||||
);
|
|
||||||
|
|
||||||
let rt = tokio::runtime::Runtime::new().unwrap();
|
|
||||||
rt.block_on(main_do(www_dir));
|
|
||||||
}
|
|
||||||
|
|
||||||
#[api({
|
|
||||||
description: "Hello API call",
|
|
||||||
})]
|
|
||||||
async fn hello() -> Result<Response<Body>, Error> {
|
|
||||||
Ok(http::Response::builder()
|
|
||||||
.status(200)
|
|
||||||
.header("content-type", "text/html")
|
|
||||||
.body(Body::from("Hello"))?)
|
|
||||||
}
|
|
||||||
|
|
||||||
static mut WWW_DIR: Option<String> = None;
|
static mut WWW_DIR: Option<String> = None;
|
||||||
|
|
||||||
@ -103,6 +36,30 @@ pub fn set_www_dir(dir: String) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// API methods
|
||||||
|
//
|
||||||
|
|
||||||
|
router! {
|
||||||
|
pub static ROUTER: Router<Body> = {
|
||||||
|
GET: hello,
|
||||||
|
/www/{path}*: { GET: get_www },
|
||||||
|
/api/1: {
|
||||||
|
// fill with more stuff
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#[api({
|
||||||
|
description: "Hello API call",
|
||||||
|
})]
|
||||||
|
async fn hello() -> Result<Response<Body>, Error> {
|
||||||
|
Ok(http::Response::builder()
|
||||||
|
.status(200)
|
||||||
|
.header("content-type", "text/html")
|
||||||
|
.body(Body::from("Hello"))?)
|
||||||
|
}
|
||||||
|
|
||||||
#[api({
|
#[api({
|
||||||
description: "Get a file from the www/ subdirectory.",
|
description: "Get a file from the www/ subdirectory.",
|
||||||
parameters: {
|
parameters: {
|
||||||
@ -114,6 +71,7 @@ async fn get_www(path: String) -> Result<Response<Body>, Error> {
|
|||||||
bail!("illegal path");
|
bail!("illegal path");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// FIXME: Add support for an ApiError type for 404s etc. to reduce error handling code size:
|
||||||
let mut file = match tokio::fs::File::open(format!("{}/{}", www_dir(), path)).await {
|
let mut file = match tokio::fs::File::open(format!("{}/{}", www_dir(), path)).await {
|
||||||
Ok(file) => file,
|
Ok(file) => file,
|
||||||
Err(ref err) if err.kind() == io::ErrorKind::NotFound => {
|
Err(ref err) if err.kind() == io::ErrorKind::NotFound => {
|
||||||
@ -145,11 +103,77 @@ async fn get_www(path: String) -> Result<Response<Body>, Error> {
|
|||||||
Ok(response.body(Body::from(data))?)
|
Ok(response.body(Body::from(data))?)
|
||||||
}
|
}
|
||||||
|
|
||||||
router! {
|
//
|
||||||
pub static ROUTER: Router<Body> = {
|
// Hyper glue
|
||||||
GET: hello,
|
//
|
||||||
/www/{path}*: { GET: get_www },
|
|
||||||
/api/1: {
|
async fn route_request(request: Request<Body>) -> Result<http::Response<Body>, Error> {
|
||||||
}
|
let path = request.uri().path();
|
||||||
|
|
||||||
|
let (target, params) = ROUTER
|
||||||
|
.lookup(path)
|
||||||
|
.ok_or_else(|| format_err!("missing path: {}", path))?;
|
||||||
|
|
||||||
|
use hyper::Method;
|
||||||
|
let method = match *request.method() {
|
||||||
|
Method::GET => target.get.as_ref(),
|
||||||
|
Method::PUT => target.put.as_ref(),
|
||||||
|
Method::POST => target.post.as_ref(),
|
||||||
|
Method::DELETE => target.delete.as_ref(),
|
||||||
|
_ => bail!("unexpected method type"),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
method
|
||||||
|
.ok_or_else(|| format_err!("no GET method for: {}", path))?
|
||||||
|
.call(params.unwrap_or(Value::Null))
|
||||||
|
.await
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn service_func(request: Request<Body>) -> Result<http::Response<Body>, hyper::Error> {
|
||||||
|
match route_request(request).await {
|
||||||
|
Ok(r) => Ok(r),
|
||||||
|
Err(err) => Ok(Response::builder()
|
||||||
|
.status(400)
|
||||||
|
.body(Body::from(format!("ERROR: {}", err)))
|
||||||
|
.expect("building an error response...")),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Main entry point
|
||||||
|
//
|
||||||
|
async fn main_do(www_dir: String) {
|
||||||
|
// Construct our SocketAddr to listen on...
|
||||||
|
let addr = ([0, 0, 0, 0], 3000).into();
|
||||||
|
|
||||||
|
// And a MakeService to handle each connection...
|
||||||
|
let service = make_service_fn(|_| async { Ok::<_, hyper::Error>(service_fn(service_func)) });
|
||||||
|
|
||||||
|
// Then bind and serve...
|
||||||
|
let server = Server::bind(&addr).serve(service);
|
||||||
|
|
||||||
|
println!("Serving {} under http://localhost:3000/www/", www_dir);
|
||||||
|
|
||||||
|
if let Err(e) = server.await {
|
||||||
|
eprintln!("server error: {}", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
// We expect a path, where to find our files we expose via the www/ dir:
|
||||||
|
let mut args = std::env::args();
|
||||||
|
|
||||||
|
// real code should have better error handling
|
||||||
|
let _program_name = args.next();
|
||||||
|
let www_dir = args.next().expect("expected a www/ subdirectory");
|
||||||
|
set_www_dir(www_dir.to_string());
|
||||||
|
|
||||||
|
// show our api info:
|
||||||
|
println!(
|
||||||
|
"{}",
|
||||||
|
serde_json::to_string_pretty(&ROUTER.api_dump()).unwrap()
|
||||||
|
);
|
||||||
|
|
||||||
|
let rt = tokio::runtime::Runtime::new().unwrap();
|
||||||
|
rt.block_on(main_do(www_dir));
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user