router: make hyper/http optional

but enable it by default.

Signed-off-by: Fabian Grünbichler <f.gruenbichler@proxmox.com>
This commit is contained in:
Fabian Grünbichler 2022-08-03 14:44:53 +02:00
parent f92c8f92cc
commit 66ace63618
5 changed files with 24 additions and 4 deletions

View File

@ -11,8 +11,8 @@ exclude = [ "debian" ]
[dependencies] [dependencies]
anyhow = "1.0" anyhow = "1.0"
env_logger = { version = "0.9", optional = true } env_logger = { version = "0.9", optional = true }
http = "0.2" http = { version = "0.2", optional = true }
hyper = { version = "0.14", features = [ "full" ] } hyper = { version = "0.14", features = [ "full" ], optional = true }
nix = "0.24.1" nix = "0.24.1"
percent-encoding = "2.1" percent-encoding = "2.1"
serde_json = "1.0" serde_json = "1.0"
@ -29,6 +29,7 @@ proxmox-schema = { path = "../proxmox-schema", version = "1.1" }
proxmox-async = { path = "../proxmox-async", version = "0.4.1" } proxmox-async = { path = "../proxmox-async", version = "0.4.1" }
[features] [features]
default = [ "cli" ] default = [ "cli", "server" ]
cli = [ "dep:env_logger", "dep:libc", "dep:rustyline", "dep:tokio" ] cli = [ "dep:env_logger", "dep:libc", "dep:rustyline", "dep:tokio" ]
server = [ "dep:http", "dep:hyper" ]
test-harness = [ "proxmox-schema/test-harness" ] test-harness = [ "proxmox-schema/test-harness" ]

View File

@ -68,6 +68,7 @@ async fn handle_simple_command_future(
ApiHandler::StreamingAsync(handler) => (handler)(params, cli_cmd.info, &mut rpcenv) ApiHandler::StreamingAsync(handler) => (handler)(params, cli_cmd.info, &mut rpcenv)
.await .await
.and_then(|r| r.to_value().map_err(Error::from)), .and_then(|r| r.to_value().map_err(Error::from)),
#[cfg(feature = "server")]
ApiHandler::AsyncHttp(_) => { ApiHandler::AsyncHttp(_) => {
let err_msg = "CliHandler does not support ApiHandler::AsyncHttp - internal error"; let err_msg = "CliHandler does not support ApiHandler::AsyncHttp - internal error";
print_simple_usage_error(prefix, cli_cmd, err_msg); print_simple_usage_error(prefix, cli_cmd, err_msg);
@ -119,6 +120,7 @@ fn handle_simple_command(
print_simple_usage_error(prefix, cli_cmd, err_msg); print_simple_usage_error(prefix, cli_cmd, err_msg);
return Err(format_err!("{}", err_msg)); return Err(format_err!("{}", err_msg));
} }
#[cfg(feature = "server")]
ApiHandler::AsyncHttp(_) => { ApiHandler::AsyncHttp(_) => {
let err_msg = "CliHandler does not support ApiHandler::AsyncHttp - internal error"; let err_msg = "CliHandler does not support ApiHandler::AsyncHttp - internal error";
print_simple_usage_error(prefix, cli_cmd, err_msg); print_simple_usage_error(prefix, cli_cmd, err_msg);

View File

@ -7,7 +7,9 @@ use anyhow::Error;
use proxmox_schema::format::*; use proxmox_schema::format::*;
use proxmox_schema::ObjectSchemaType; use proxmox_schema::ObjectSchemaType;
use crate::{ApiHandler, ApiMethod}; #[cfg(feature = "server")]
use crate::ApiHandler;
use crate::ApiMethod;
fn dump_method_definition(method: &str, path: &str, def: Option<&ApiMethod>) -> Option<String> { fn dump_method_definition(method: &str, path: &str, def: Option<&ApiMethod>) -> Option<String> {
let style = ParameterDisplayStyle::Config; let style = ParameterDisplayStyle::Config;
@ -19,8 +21,12 @@ fn dump_method_definition(method: &str, path: &str, def: Option<&ApiMethod>) ->
let return_descr = dump_api_return_schema(&api_method.returns, style); let return_descr = dump_api_return_schema(&api_method.returns, style);
#[cfg(feature = "server")]
let mut method = method; let mut method = method;
#[cfg(not(feature = "server"))]
let method = method;
#[cfg(feature = "server")]
if let ApiHandler::AsyncHttp(_) = api_method.handler { if let ApiHandler::AsyncHttp(_) = api_method.handler {
method = if method == "POST" { "UPLOAD" } else { method }; method = if method == "POST" { "UPLOAD" } else { method };
method = if method == "GET" { "DOWNLOAD" } else { method }; method = if method == "GET" { "DOWNLOAD" } else { method };

View File

@ -7,6 +7,7 @@ pub mod cli;
// this is public so the `http_err!` macro can access `http::StatusCode` through it // this is public so the `http_err!` macro can access `http::StatusCode` through it
#[doc(hidden)] #[doc(hidden)]
#[cfg(feature = "server")]
pub mod error; pub mod error;
mod permission; mod permission;
@ -15,6 +16,7 @@ mod rpc_environment;
mod serializable_return; mod serializable_return;
#[doc(inline)] #[doc(inline)]
#[cfg(feature = "server")]
pub use error::HttpError; pub use error::HttpError;
pub use permission::*; pub use permission::*;

View File

@ -4,8 +4,11 @@ use std::future::Future;
use std::pin::Pin; use std::pin::Pin;
use anyhow::Error; use anyhow::Error;
#[cfg(feature = "server")]
use http::request::Parts; use http::request::Parts;
#[cfg(feature = "server")]
use http::{Method, Response}; use http::{Method, Response};
#[cfg(feature = "server")]
use hyper::Body; use hyper::Body;
use percent_encoding::percent_decode_str; use percent_encoding::percent_decode_str;
use serde_json::Value; use serde_json::Value;
@ -176,6 +179,7 @@ pub type StreamingApiFuture<'a> = Pin<
/// &ObjectSchema::new("Hello World Example (low level)", &[]) /// &ObjectSchema::new("Hello World Example (low level)", &[])
/// ); /// );
/// ``` /// ```
#[cfg(feature = "server")]
pub type ApiAsyncHttpHandlerFn = &'static (dyn Fn( pub type ApiAsyncHttpHandlerFn = &'static (dyn Fn(
Parts, Parts,
Body, Body,
@ -188,15 +192,18 @@ pub type ApiAsyncHttpHandlerFn = &'static (dyn Fn(
+ 'static); + 'static);
/// The output of an asynchronous API handler is a future yielding a `Response`. /// The output of an asynchronous API handler is a future yielding a `Response`.
#[cfg(feature = "server")]
pub type ApiResponseFuture = pub type ApiResponseFuture =
Pin<Box<dyn Future<Output = Result<Response<Body>, anyhow::Error>> + Send>>; Pin<Box<dyn Future<Output = Result<Response<Body>, anyhow::Error>> + Send>>;
/// Enum for different types of API handler functions. /// Enum for different types of API handler functions.
#[non_exhaustive]
pub enum ApiHandler { pub enum ApiHandler {
Sync(ApiHandlerFn), Sync(ApiHandlerFn),
StreamingSync(StreamingApiHandlerFn), StreamingSync(StreamingApiHandlerFn),
Async(ApiAsyncHandlerFn), Async(ApiAsyncHandlerFn),
StreamingAsync(StreamingApiAsyncHandlerFn), StreamingAsync(StreamingApiAsyncHandlerFn),
#[cfg(feature = "server")]
AsyncHttp(ApiAsyncHttpHandlerFn), AsyncHttp(ApiAsyncHttpHandlerFn),
} }
@ -220,6 +227,7 @@ impl PartialEq for ApiHandler {
(ApiHandler::StreamingAsync(l), ApiHandler::StreamingAsync(r)) => { (ApiHandler::StreamingAsync(l), ApiHandler::StreamingAsync(r)) => {
core::mem::transmute::<_, usize>(l) == core::mem::transmute::<_, usize>(r) core::mem::transmute::<_, usize>(l) == core::mem::transmute::<_, usize>(r)
} }
#[cfg(feature = "server")]
(ApiHandler::AsyncHttp(l), ApiHandler::AsyncHttp(r)) => { (ApiHandler::AsyncHttp(l), ApiHandler::AsyncHttp(r)) => {
core::mem::transmute::<_, usize>(l) == core::mem::transmute::<_, usize>(r) core::mem::transmute::<_, usize>(l) == core::mem::transmute::<_, usize>(r)
} }
@ -431,6 +439,7 @@ impl Router {
/// - `components`: Path, split into individual components. /// - `components`: Path, split into individual components.
/// - `method`: The HTTP method. /// - `method`: The HTTP method.
/// - `uri_param`: Mutable hash map to store parameter from `MatchAll` router. /// - `uri_param`: Mutable hash map to store parameter from `MatchAll` router.
#[cfg(feature = "server")]
pub fn find_method( pub fn find_method(
&self, &self,
components: &[&str], components: &[&str],