forked from proxmox-mirrors/proxmox
testing a Router::api_dump method
Signed-off-by: Wolfgang Bumiller <w.bumiller@proxmox.com>
This commit is contained in:
parent
536072c712
commit
a64832aac2
@ -46,6 +46,12 @@ fn main() {
|
||||
let www_dir = args.next().expect("expected a www/ subdirectory");
|
||||
api::set_www_dir(www_dir.to_string());
|
||||
|
||||
// show our api info:
|
||||
println!(
|
||||
"{}",
|
||||
serde_json::to_string_pretty(&api::ROUTER.api_dump()).unwrap()
|
||||
);
|
||||
|
||||
// Construct our SocketAddr to listen on...
|
||||
let addr = ([0, 0, 0, 0], 3000).into();
|
||||
|
||||
|
@ -5,7 +5,7 @@ use std::sync::Once;
|
||||
|
||||
use failure::Error;
|
||||
use http::Response;
|
||||
use serde_json::Value;
|
||||
use serde_json::{json, Value};
|
||||
|
||||
/// Method entries in a `Router` are actually just `&dyn ApiMethodInfo` trait objects.
|
||||
/// This contains all the info required to call, document, or command-line-complete parameters for
|
||||
@ -31,6 +31,18 @@ pub struct Parameter {
|
||||
pub type_info: fn() -> &'static TypeInfo,
|
||||
}
|
||||
|
||||
impl Parameter {
|
||||
pub fn api_dump(&self) -> (&'static str, Value) {
|
||||
(
|
||||
self.name,
|
||||
json!({
|
||||
"description": self.description,
|
||||
"type": (self.type_info)().name,
|
||||
}),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/// Bare type info. Types themselves should also have a description, even if a method's parameter
|
||||
/// usually overrides it. Ideally we can hyperlink the parameter to the type information in the
|
||||
/// generated documentation.
|
||||
@ -40,6 +52,12 @@ pub struct TypeInfo {
|
||||
pub complete_fn: Option<CompleteFn>,
|
||||
}
|
||||
|
||||
impl TypeInfo {
|
||||
pub fn api_dump(&self) -> Value {
|
||||
Value::String(self.name.to_string())
|
||||
}
|
||||
}
|
||||
|
||||
/// Until we can slap `#[api]` onto all the functions we can start translating our existing
|
||||
/// `ApiMethod` structs to this new layout.
|
||||
/// Otherwise this is mostly there so we can run the tests in the tests subdirectory without
|
||||
@ -80,6 +98,25 @@ impl<Body> ApiMethodInfo<Body> for ApiMethod<Body> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<Body> dyn ApiMethodInfo<Body> + Send + Sync {
|
||||
pub fn api_dump(&self) -> Value {
|
||||
let parameters = Value::Object(std::iter::FromIterator::from_iter(
|
||||
self.parameters()
|
||||
.iter()
|
||||
.map(|p| p.api_dump())
|
||||
.map(|(name, value)| (name.to_string(), value)),
|
||||
));
|
||||
|
||||
json!({
|
||||
"description": self.description(),
|
||||
"protected": self.protected(),
|
||||
"reload-timezone": self.reload_timezone(),
|
||||
"parameters": parameters,
|
||||
//"returns": self.return_type().api_dump()?, <- add api_dump() to TypeInfo
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
/// We're supposed to only use types in the API which implement `ApiType`, which forces types ot
|
||||
/// have a `verify` method. The idea is that all parameters used in the API are documented
|
||||
/// somewhere with their formats and limits, which are checked when entering and leaving API entry
|
||||
|
@ -2,7 +2,8 @@
|
||||
|
||||
use std::collections::HashMap;
|
||||
|
||||
use serde_json::Value;
|
||||
use failure::Error;
|
||||
use serde_json::{json, Value};
|
||||
|
||||
use super::ApiMethodInfo;
|
||||
|
||||
@ -110,6 +111,58 @@ where
|
||||
Some((this, matched_params.map(Value::Object)))
|
||||
}
|
||||
|
||||
pub fn api_dump(&self) -> Value {
|
||||
let mut this = serde_json::Map::<String, Value>::new();
|
||||
|
||||
if let Some(get) = self.get {
|
||||
this.insert("GET".to_string(), get.api_dump());
|
||||
}
|
||||
|
||||
if let Some(put) = self.put {
|
||||
this.insert("PUT".to_string(), put.api_dump());
|
||||
}
|
||||
|
||||
if let Some(post) = self.post {
|
||||
this.insert("POST".to_string(), post.api_dump());
|
||||
}
|
||||
|
||||
if let Some(delete) = self.delete {
|
||||
this.insert("DELETE".to_string(), delete.api_dump());
|
||||
}
|
||||
|
||||
match &self.subroute {
|
||||
None => (),
|
||||
Some(SubRoute::Wildcard(name)) => {
|
||||
this.insert("wildcard".to_string(), Value::String(name.to_string()));
|
||||
}
|
||||
Some(SubRoute::Directories(subdirs)) => {
|
||||
for (dir, router) in subdirs.iter() {
|
||||
this.insert(dir.to_string(), router.api_dump());
|
||||
}
|
||||
}
|
||||
Some(SubRoute::Parameter(name, other)) => {
|
||||
this.insert(
|
||||
"sub-router".to_string(),
|
||||
json!({
|
||||
"parameter": name,
|
||||
"router": other.api_dump(),
|
||||
}),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
Value::Object(this)
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Router as a builder methods:
|
||||
//
|
||||
|
||||
impl<Body> Router<Body>
|
||||
where
|
||||
Self: Default,
|
||||
{
|
||||
/// Builder method to provide a `GET` method info.
|
||||
pub fn get<I>(mut self, method: &'static I) -> Self
|
||||
where
|
||||
|
Loading…
Reference in New Issue
Block a user