From: Otto Moerbeek Date: Tue, 28 Jan 2025 12:11:58 +0000 (+0100) Subject: Advice fomr clippy X-Git-Tag: dnsdist-2.0.0-alpha1~95^2~15 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=8e2f11358160287241f04cc4feb8bcfa871c9a74;p=thirdparty%2Fpdns.git Advice fomr clippy --- diff --git a/pdns/recursordist/settings/cxxsupport.cc b/pdns/recursordist/settings/cxxsupport.cc index 82dd3c8451..6ef3378bf7 100644 --- a/pdns/recursordist/settings/cxxsupport.cc +++ b/pdns/recursordist/settings/cxxsupport.cc @@ -1499,7 +1499,7 @@ void log(const std::unique_ptr& logger, pdns::rust::web::rec::Priority l log->info(static_cast(log_level), std::string(msg)); } - void error(const std::unique_ptr& logger, pdns::rust::web::rec::Priority log_level, ::rust::Str error, ::rust::Str msg, const ::rust::Vec& values) +void error(const std::unique_ptr& logger, pdns::rust::web::rec::Priority log_level, ::rust::Str error, ::rust::Str msg, const ::rust::Vec& values) { auto log = logger->get(); for (const auto& [key, value] : values) { diff --git a/pdns/recursordist/settings/rust/src/bridge.hh b/pdns/recursordist/settings/rust/src/bridge.hh index 1663e84995..b23d74872a 100644 --- a/pdns/recursordist/settings/rust/src/bridge.hh +++ b/pdns/recursordist/settings/rust/src/bridge.hh @@ -41,7 +41,6 @@ void setThreadName(::rust::Str str); class NetmaskGroup; union ComboAddress; - namespace pdns::rust::web::rec { using CredentialsHolder = ::CredentialsHolder; @@ -73,7 +72,7 @@ private: using NetmaskGroup = Wrapper<::NetmaskGroup>; using ComboAddress = Wrapper<::ComboAddress>; using Logger = Wrapper>; - + void apiServer(const Request& rustRequest, Response& rustResponse); void apiDiscovery(const Request& rustRequest, Response& rustResponse); void apiDiscoveryV1(const Request& rustRequest, Response& rustResponse); @@ -99,5 +98,5 @@ std::unique_ptr comboaddress(::rust::Str str); bool matches(const std::unique_ptr& nmg, const std::unique_ptr& address); std::unique_ptr withValue(const std::unique_ptr& logger, ::rust::Str key, ::rust::Str val); void log(const std::unique_ptr& logger, Priority log_level, ::rust::Str msg, const ::rust::Vec& values); - void error(const std::unique_ptr& logger, Priority log_level, ::rust::Str err, ::rust::Str msg, const ::rust::Vec& values); +void error(const std::unique_ptr& logger, Priority log_level, ::rust::Str err, ::rust::Str msg, const ::rust::Vec& values); } diff --git a/pdns/recursordist/settings/rust/src/bridge.rs b/pdns/recursordist/settings/rust/src/bridge.rs index 752b8830c8..e67931d464 100644 --- a/pdns/recursordist/settings/rust/src/bridge.rs +++ b/pdns/recursordist/settings/rust/src/bridge.rs @@ -217,7 +217,8 @@ fn validate_address_family( let sa = SocketAddr::from_str(addr_str); if sa.is_err() { let ip = IpAddr::from_str(addr_str); - if ip.is_err() { // It is likely a name + if ip.is_err() { + // It is likely a name continue; } let ip = ip.unwrap(); @@ -704,9 +705,13 @@ impl ForwardingCatalogZone { pub fn validate(&self, field: &str) -> Result<(), ValidationError> { self.xfr.tsig.validate(&(field.to_owned() + ".xfr.tsig"))?; if !self.xfr.addresses.is_empty() { - validate_address_family(&(field.to_owned() + ".xfr.addresses"), &(field.to_owned() + ".xfr.localAddress"), &self.xfr.addresses, &self.xfr.localAddress)?; - } - else { + validate_address_family( + &(field.to_owned() + ".xfr.addresses"), + &(field.to_owned() + ".xfr.localAddress"), + &self.xfr.addresses, + &self.xfr.localAddress, + )?; + } else { let msg = format!("{}.xfr.addresses: at least one address required", field); return Err(ValidationError { msg }); } diff --git a/pdns/recursordist/settings/rust/src/web.rs b/pdns/recursordist/settings/rust/src/web.rs index 081a82f013..876b5a22a9 100644 --- a/pdns/recursordist/settings/rust/src/web.rs +++ b/pdns/recursordist/settings/rust/src/web.rs @@ -14,19 +14,19 @@ TODO use std::net::SocketAddr; +use base64::prelude::*; use bytes::Bytes; use http_body_util::{BodyExt, Full}; use hyper::server::conn::http1; use hyper::service::service_fn; use hyper::{body::Incoming as IncomingBody, header, Method, Request, Response, StatusCode}; use hyper_util::rt::TokioIo; -use tokio::net::TcpListener; -use tokio::runtime::Builder; -use tokio::task::JoinSet; use std::io::ErrorKind; use std::str::FromStr; use std::sync::Arc; -use base64::prelude::*; +use tokio::net::TcpListener; +use tokio::runtime::Builder; +use tokio::task::JoinSet; type GenericError = Box; type MyResult = std::result::Result; @@ -42,8 +42,7 @@ fn full>(chunk: T) -> BoxBody { type Func = fn(&rustweb::Request, &mut rustweb::Response) -> Result<(), cxx::Exception>; -fn compare_authorization(ctx: &Context, reqheaders: &header::HeaderMap) -> bool -{ +fn compare_authorization(ctx: &Context, reqheaders: &header::HeaderMap) -> bool { let mut auth_ok = false; if !ctx.password_ch.is_null() { if let Some(authorization) = reqheaders.get("authorization") { @@ -68,9 +67,8 @@ fn compare_authorization(ctx: &Context, reqheaders: &header::HeaderMap) -> bool auth_ok } -fn unauthorized(response: &mut rustweb::Response, headers: &mut header::HeaderMap, auth: &str) -{ - let status = StatusCode::UNAUTHORIZED; +fn unauthorized(response: &mut rustweb::Response, headers: &mut header::HeaderMap, auth: &str) { + let status = StatusCode::UNAUTHORIZED; response.status = status.as_u16(); let val = format!("{} realm=\"PowerDNS\"", auth); headers.insert( @@ -86,31 +84,53 @@ fn nonapi_wrapper( request: &rustweb::Request, response: &mut rustweb::Response, reqheaders: &header::HeaderMap, - headers: &mut header::HeaderMap + headers: &mut header::HeaderMap, ) { let auth_ok = compare_authorization(ctx, reqheaders); if !auth_ok { - rustweb::log(request.logger, rustweb::Priority::Debug, "Authentication failed", - &vec!(rustweb::KeyValue{key: "urlpath".to_string(), value: request.uri.to_owned()})); + rustweb::log( + request.logger, + rustweb::Priority::Debug, + "Authentication failed", + &vec![rustweb::KeyValue { + key: "urlpath".to_string(), + value: request.uri.to_owned(), + }], + ); unauthorized(response, headers, "Basic"); return; } match handler(request, response) { Ok(_) => {} Err(_) => { - let status = StatusCode::UNPROCESSABLE_ENTITY; // 422 + let status = StatusCode::UNPROCESSABLE_ENTITY; // 422 response.status = status.as_u16(); response.body = status.canonical_reason().unwrap().as_bytes().to_vec(); } } } -fn file_wrapper(ctx: &Context, handler: FileFunc, method: &Method, path: &str, request: &rustweb::Request, response: &mut rustweb::Response, reqheaders: &header::HeaderMap, headers: &mut header::HeaderMap) -{ +fn file_wrapper( + ctx: &Context, + handler: FileFunc, + method: &Method, + path: &str, + request: &rustweb::Request, + response: &mut rustweb::Response, + reqheaders: &header::HeaderMap, + headers: &mut header::HeaderMap, +) { let auth_ok = compare_authorization(ctx, reqheaders); if !auth_ok { - rustweb::log(request.logger, rustweb::Priority::Debug, "Authentication failed", - &vec!(rustweb::KeyValue{key: "urlpath".to_string(), value: request.uri.to_owned()})); + rustweb::log( + request.logger, + rustweb::Priority::Debug, + "Authentication failed", + &vec![rustweb::KeyValue { + key: "urlpath".to_string(), + value: request.uri.to_owned(), + }], + ); unauthorized(response, headers, "Basic"); return; } @@ -125,17 +145,23 @@ fn api_wrapper( response: &mut rustweb::Response, reqheaders: &header::HeaderMap, headers: &mut header::HeaderMap, - allow_password: bool + allow_password: bool, ) { - // security headers headers.insert( header::ACCESS_CONTROL_ALLOW_ORIGIN, header::HeaderValue::from_static("*"), ); if ctx.api_ch.is_null() { - rustweb::log(logger, rustweb::Priority::Error, "Authentication failed, API Key missing in config", - &vec!(rustweb::KeyValue{key: "urlpath".to_string(), value: request.uri.to_owned()})); + rustweb::log( + logger, + rustweb::Priority::Error, + "Authentication failed, API Key missing in config", + &vec![rustweb::KeyValue { + key: "urlpath".to_string(), + value: request.uri.to_owned(), + }], + ); unauthorized(response, headers, "X-API-Key"); return; } @@ -159,15 +185,29 @@ fn api_wrapper( if !auth_ok && allow_password { auth_ok = compare_authorization(ctx, reqheaders); if !auth_ok { - rustweb::log(logger, rustweb::Priority::Debug, "Authentication failed", - &vec!(rustweb::KeyValue{key: "urlpath".to_string(), value: request.uri.to_owned()})); + rustweb::log( + logger, + rustweb::Priority::Debug, + "Authentication failed", + &vec![rustweb::KeyValue { + key: "urlpath".to_string(), + value: request.uri.to_owned(), + }], + ); unauthorized(response, headers, "Basic"); return; } } if !auth_ok { - rustweb::log(logger, rustweb::Priority::Error, "Authentication failed", - &vec!(rustweb::KeyValue{key: "urlpath".to_string(), value: request.uri.to_owned()})); + rustweb::log( + logger, + rustweb::Priority::Error, + "Authentication failed", + &vec![rustweb::KeyValue { + key: "urlpath".to_string(), + value: request.uri.to_owned(), + }], + ); unauthorized(response, headers, "X-API-Key"); return; } @@ -198,7 +238,7 @@ fn api_wrapper( match handler(request, response) { Ok(_) => {} Err(_) => { - let status = StatusCode::UNPROCESSABLE_ENTITY; // 422 + let status = StatusCode::UNPROCESSABLE_ENTITY; // 422 response.status = status.as_u16(); response.body = status.canonical_reason().unwrap().as_bytes().to_vec(); } @@ -216,19 +256,37 @@ struct Context { } // Serve a file -fn file(ctx: &Context, method: &Method, path: &str, request: &rustweb::Request, response: &mut rustweb::Response) -{ +fn file( + ctx: &Context, + method: &Method, + path: &str, + request: &rustweb::Request, + response: &mut rustweb::Response, +) { let mut uripath = path; if uripath == "/" { uripath = "/index.html"; } - let pos = ctx.urls.iter().position(|x| String::from("/") + x == uripath); + let pos = ctx + .urls + .iter() + .position(|x| String::from("/") + x == uripath); if pos.is_none() { - rustweb::log(&request.logger, rustweb::Priority::Debug, "not found", - &vec!( - rustweb::KeyValue{key: "method".to_string(), value: method.to_string()}, - rustweb::KeyValue{key: "uripath".to_string(), value: uripath.to_string()} - )); + rustweb::log( + request.logger, + rustweb::Priority::Debug, + "not found", + &vec![ + rustweb::KeyValue { + key: "method".to_string(), + value: method.to_string(), + }, + rustweb::KeyValue { + key: "uripath".to_string(), + value: uripath.to_string(), + }, + ], + ); } // This calls into C++ @@ -236,82 +294,122 @@ fn file(ctx: &Context, method: &Method, path: &str, request: &rustweb::Request, // Return 404 not found response. response.status = StatusCode::NOT_FOUND.as_u16(); response.body = NOTFOUND.to_vec(); - rustweb::log(&request.logger, rustweb::Priority::Debug, "not found case 2", - &vec!( - rustweb::KeyValue{key: "method".to_string(), value: method.to_string()}, - rustweb::KeyValue{key: "uripath".to_string(), value: uripath.to_string()} - )); + rustweb::log( + request.logger, + rustweb::Priority::Debug, + "not found case 2", + &vec![ + rustweb::KeyValue { + key: "method".to_string(), + value: method.to_string(), + }, + rustweb::KeyValue { + key: "uripath".to_string(), + value: uripath.to_string(), + }, + ], + ); } } -type FileFunc = fn(ctx: &Context, method: &Method, path: &str, request: &rustweb::Request, response: &mut rustweb::Response); +type FileFunc = fn( + ctx: &Context, + method: &Method, + path: &str, + request: &rustweb::Request, + response: &mut rustweb::Response, +); // Match a request and return the function that imlements it, this should probably be table based. -fn matcher(method: &Method, path: &str, apifunc: &mut Option, rawfunc: &mut Option, filefunc: &mut Option, allow_password: &mut bool, request: &mut rustweb::Request) -{ +fn matcher( + method: &Method, + path: &str, + apifunc: &mut Option, + rawfunc: &mut Option, + filefunc: &mut Option, + allow_password: &mut bool, + request: &mut rustweb::Request, +) { let path: Vec<_> = path.split('/').skip(1).collect(); match (method, &*path) { (&Method::GET, ["jsonstat"]) => { *allow_password = true; *apifunc = Some(rustweb::jsonstat); } - (&Method::PUT, ["api", "v1", "servers", "localhost", "cache", "flush"]) => - *apifunc = Some(rustweb::apiServerCacheFlush), - (&Method::PUT, ["api", "v1", "servers", "localhost", "config", "allow-from"]) => - *apifunc = Some(rustweb::apiServerConfigAllowFromPUT), - (&Method::GET, ["api", "v1", "servers", "localhost", "config", "allow-from"]) => - *apifunc = Some(rustweb::apiServerConfigAllowFromGET), - (&Method::PUT, ["api", "v1", "servers", "localhost", "config", "allow-notify-from"]) => - *apifunc = Some(rustweb::apiServerConfigAllowNotifyFromPUT), - (&Method::GET, ["api", "v1", "servers", "localhost", "config", "allow-notify-from"]) => - *apifunc = Some(rustweb::apiServerConfigAllowNotifyFromGET), - (&Method::GET, ["api", "v1", "servers", "localhost", "config"]) => - *apifunc = Some(rustweb::apiServerConfig), - (&Method::GET, ["api", "v1", "servers", "localhost", "rpzstatistics"]) => - *apifunc = Some(rustweb::apiServerRPZStats), - (&Method::GET, ["api", "v1", "servers", "localhost", "search-data"]) => - *apifunc = Some(rustweb::apiServerSearchData), + (&Method::PUT, ["api", "v1", "servers", "localhost", "cache", "flush"]) => { + *apifunc = Some(rustweb::apiServerCacheFlush) + } + (&Method::PUT, ["api", "v1", "servers", "localhost", "config", "allow-from"]) => { + *apifunc = Some(rustweb::apiServerConfigAllowFromPUT) + } + (&Method::GET, ["api", "v1", "servers", "localhost", "config", "allow-from"]) => { + *apifunc = Some(rustweb::apiServerConfigAllowFromGET) + } + (&Method::PUT, ["api", "v1", "servers", "localhost", "config", "allow-notify-from"]) => { + *apifunc = Some(rustweb::apiServerConfigAllowNotifyFromPUT) + } + (&Method::GET, ["api", "v1", "servers", "localhost", "config", "allow-notify-from"]) => { + *apifunc = Some(rustweb::apiServerConfigAllowNotifyFromGET) + } + (&Method::GET, ["api", "v1", "servers", "localhost", "config"]) => { + *apifunc = Some(rustweb::apiServerConfig) + } + (&Method::GET, ["api", "v1", "servers", "localhost", "rpzstatistics"]) => { + *apifunc = Some(rustweb::apiServerRPZStats) + } + (&Method::GET, ["api", "v1", "servers", "localhost", "search-data"]) => { + *apifunc = Some(rustweb::apiServerSearchData) + } (&Method::GET, ["api", "v1", "servers", "localhost", "zones", id]) => { - request.parameters.push(rustweb::KeyValue{key: String::from("id"), value: String::from(*id)}); + request.parameters.push(rustweb::KeyValue { + key: String::from("id"), + value: String::from(*id), + }); *apifunc = Some(rustweb::apiServerZoneDetailGET); } (&Method::PUT, ["api", "v1", "servers", "localhost", "zones", id]) => { - request.parameters.push(rustweb::KeyValue{key: String::from("id"), value: String::from(*id)}); + request.parameters.push(rustweb::KeyValue { + key: String::from("id"), + value: String::from(*id), + }); *apifunc = Some(rustweb::apiServerZoneDetailPUT); } (&Method::DELETE, ["api", "v1", "servers", "localhost", "zones", id]) => { - request.parameters.push(rustweb::KeyValue{key: String::from("id"), value: String::from(*id)}); + request.parameters.push(rustweb::KeyValue { + key: String::from("id"), + value: String::from(*id), + }); *apifunc = Some(rustweb::apiServerZoneDetailDELETE); } (&Method::GET, ["api", "v1", "servers", "localhost", "statistics"]) => { *allow_password = true; *apifunc = Some(rustweb::apiServerStatistics); } - (&Method::GET, ["api", "v1", "servers", "localhost", "zones"]) => - *apifunc = Some(rustweb::apiServerZonesGET), - (&Method::POST, ["api", "v1", "servers", "localhost", "zones"]) => - *apifunc = Some(rustweb::apiServerZonesPOST), + (&Method::GET, ["api", "v1", "servers", "localhost", "zones"]) => { + *apifunc = Some(rustweb::apiServerZonesGET) + } + (&Method::POST, ["api", "v1", "servers", "localhost", "zones"]) => { + *apifunc = Some(rustweb::apiServerZonesPOST) + } (&Method::GET, ["api", "v1", "servers", "localhost"]) => { *allow_password = true; *apifunc = Some(rustweb::apiServerDetail); } - (&Method::GET, ["api", "v1", "servers"]) => - *apifunc = Some(rustweb::apiServer), - (&Method::GET, ["api", "v1"]) => - *apifunc = Some(rustweb::apiDiscoveryV1), - (&Method::GET, ["api"]) => - *apifunc = Some(rustweb::apiDiscovery), - (&Method::GET, ["metrics"]) => - *rawfunc = Some(rustweb::prometheusMetrics), - _ => - *filefunc = Some(file), + (&Method::GET, ["api", "v1", "servers"]) => *apifunc = Some(rustweb::apiServer), + (&Method::GET, ["api", "v1"]) => *apifunc = Some(rustweb::apiDiscoveryV1), + (&Method::GET, ["api"]) => *apifunc = Some(rustweb::apiDiscovery), + (&Method::GET, ["metrics"]) => *rawfunc = Some(rustweb::prometheusMetrics), + _ => *filefunc = Some(file), } } // This constructs the answer to an OPTIONS query -fn collect_options(path: &str, response: &mut rustweb::Response, my_logger: &cxx::UniquePtr) -{ - let mut methods = vec!(); +fn collect_options( + path: &str, + response: &mut rustweb::Response, + my_logger: &cxx::UniquePtr, +) { + let mut methods = vec![]; for method in [Method::GET, Method::POST, Method::PUT, Method::DELETE] { let mut apifunc: Option = None; let mut rawfunc: Option<_> = None; @@ -324,8 +422,18 @@ fn collect_options(path: &str, response: &mut rustweb::Response, my_logger: &cxx parameters: vec![], logger: my_logger, }; - matcher(&method, path, &mut apifunc, &mut rawfunc, &mut filefunc, &mut allow_password, &mut request); - if apifunc.is_some() || rawfunc.is_some() /* || filefunc.is_some() */ { + matcher( + &method, + path, + &mut apifunc, + &mut rawfunc, + &mut filefunc, + &mut allow_password, + &mut request, + ); + if apifunc.is_some() || rawfunc.is_some() + /* || filefunc.is_some() */ + { methods.push(method.to_string()); } } @@ -335,66 +443,99 @@ fn collect_options(path: &str, response: &mut rustweb::Response, my_logger: &cxx } response.status = 200; methods.push(Method::OPTIONS.to_string()); - response.headers.push(rustweb::KeyValue{key: String::from("access-control-allow-origin"), value: String::from("*")}); - response.headers.push(rustweb::KeyValue{key: String::from("access-control-allow-headers"), value: String::from("Content-Type, X-API-Key")}); - response.headers.push(rustweb::KeyValue{key: String::from("access-control-max-age"), value: String::from("3600")}); - response.headers.push(rustweb::KeyValue{key: String::from("access-control-allow-methods"), value: methods.join(", ")}); - response.headers.push(rustweb::KeyValue{key: String::from("content-type"), value: String::from("text/plain")}); + response.headers.push(rustweb::KeyValue { + key: String::from("access-control-allow-origin"), + value: String::from("*"), + }); + response.headers.push(rustweb::KeyValue { + key: String::from("access-control-allow-headers"), + value: String::from("Content-Type, X-API-Key"), + }); + response.headers.push(rustweb::KeyValue { + key: String::from("access-control-max-age"), + value: String::from("3600"), + }); + response.headers.push(rustweb::KeyValue { + key: String::from("access-control-allow-methods"), + value: methods.join(", "), + }); + response.headers.push(rustweb::KeyValue { + key: String::from("content-type"), + value: String::from("text/plain"), + }); } -fn log_request(loglevel: rustweb::LogLevel, request: &rustweb::Request, remote: SocketAddr) -{ - if loglevel != rustweb::LogLevel::Detailed { +fn log_request(loglevel: rustweb::LogLevel, request: &rustweb::Request, remote: SocketAddr) { + if loglevel != rustweb::LogLevel::Detailed { return; } - let body; - match std::str::from_utf8(&request.body) { - Ok(cvt) => body = cvt, - Err(_) => body = "error: body is not utf8" - } - let mut vec = vec!( - rustweb::KeyValue{key: "remote".to_string(), value: remote.to_string()}, - rustweb::KeyValue{key: "body".to_string(), value: body.to_string()} - ); + let body = std::str::from_utf8(&request.body).unwrap_or("error: body is not utf8"); + let mut vec = vec![ + rustweb::KeyValue { + key: "remote".to_string(), + value: remote.to_string(), + }, + rustweb::KeyValue { + key: "body".to_string(), + value: body.to_string(), + }, + ]; let mut first = true; let mut str = "".to_string(); for var in &request.vars { if !first { - str.push_str(" "); + str.push(' '); } first = false; let snippet = var.key.to_owned() + "=" + &var.value; str.push_str(&snippet); } - vec.push(rustweb::KeyValue{key: "getVars".to_string(), value: str.to_string()}); - rustweb::log(&request.logger, rustweb::Priority::Info, "Request details", &vec); + vec.push(rustweb::KeyValue { + key: "getVars".to_string(), + value: str.to_string(), + }); + rustweb::log( + request.logger, + rustweb::Priority::Info, + "Request details", + &vec, + ); } -fn log_response(loglevel: rustweb::LogLevel, logger: &cxx::UniquePtr, response: &rustweb::Response, remote: SocketAddr) -{ +fn log_response( + loglevel: rustweb::LogLevel, + logger: &cxx::UniquePtr, + response: &rustweb::Response, + remote: SocketAddr, +) { if loglevel != rustweb::LogLevel::Detailed { return; } - let body; - match std::str::from_utf8(&response.body) { - Ok(cvt) => body = cvt, - Err(_) => body = "error: body is not utf8" - } - let mut vec = vec!( - rustweb::KeyValue{key: "remote".to_string(), value: remote.to_string()}, - rustweb::KeyValue{key: "body".to_string(), value: body.to_string()} - ); + let body = std::str::from_utf8(&response.body).unwrap_or("error: body is not utf8"); + let mut vec = vec![ + rustweb::KeyValue { + key: "remote".to_string(), + value: remote.to_string(), + }, + rustweb::KeyValue { + key: "body".to_string(), + value: body.to_string(), + }, + ]; let mut first = true; let mut str = "".to_string(); for var in &response.headers { if !first { - str.push_str(" "); + str.push(' '); } first = false; let snippet = var.key.to_owned() + "=" + &var.value; str.push_str(&snippet); } - vec.push(rustweb::KeyValue{key: "headers".to_string(), value: str.to_string()}); + vec.push(rustweb::KeyValue { + key: "headers".to_string(), + value: str.to_string(), + }); rustweb::log(logger, rustweb::Priority::Info, "Response details", &vec); } @@ -404,7 +545,6 @@ async fn process_request( ctx: Arc, remote: SocketAddr, ) -> MyResult> { - let unique = uuid::Uuid::new_v4(); let my_logger = rustweb::withValue(&ctx.logger, "uniqueid", &unique.to_string()); @@ -452,18 +592,25 @@ async fn process_request( if method == Method::OPTIONS { collect_options(&path, &mut response, &my_logger); - } - else { + } else { // Find the right function implementing what the request wants let mut matchmethod = method.clone(); if method == Method::HEAD { matchmethod = Method::GET; } - matcher(&matchmethod, &path, &mut apifunc, &mut rawfunc, &mut filefunc, &mut allow_password, &mut request); + matcher( + &matchmethod, + &path, + &mut apifunc, + &mut rawfunc, + &mut filefunc, + &mut allow_password, + &mut request, + ); if let Some(func) = apifunc { let reqheaders = rust_request.headers().clone(); - if rust_request.method()== Method::POST || rust_request.method() == Method::PUT { + if rust_request.method() == Method::POST || rust_request.method() == Method::PUT { request.body = rust_request.collect().await?.to_bytes().to_vec(); } // This calls indirectly into C++ @@ -475,18 +622,32 @@ async fn process_request( &mut response, &reqheaders, rust_response.headers_mut().expect("no headers?"), - allow_password + allow_password, ); - } - else if let Some(func) = rawfunc { + } else if let Some(func) = rawfunc { // Non-API func let reqheaders = rust_request.headers().clone(); - nonapi_wrapper(&ctx, func, &request, &mut response, &reqheaders, rust_response.headers_mut().expect("no headers?")); - } - else if let Some(func) = filefunc { + nonapi_wrapper( + &ctx, + func, + &request, + &mut response, + &reqheaders, + rust_response.headers_mut().expect("no headers?"), + ); + } else if let Some(func) = filefunc { // Server static file let reqheaders = rust_request.headers().clone(); - file_wrapper(&ctx, func, &method, rust_request.uri().path(), &request, &mut response, &reqheaders, rust_response.headers_mut().expect("no headers?")); + file_wrapper( + &ctx, + func, + &method, + rust_request.uri().path(), + &request, + &mut response, + &reqheaders, + rust_response.headers_mut().expect("no headers?"), + ); } } @@ -498,7 +659,7 @@ async fn process_request( // Throw away body for HEAD call let mut body = full(response.body); if method == Method::HEAD { - body = full(vec!()); + body = full(vec![]); } // Construct response based on what C++ gave us @@ -518,21 +679,47 @@ async fn process_request( ); if ctx.loglevel != rustweb::LogLevel::None { let version = format!("{:?}", version); - rustweb::log(&my_logger, rustweb::Priority::Notice, "Request", &vec!( - rustweb::KeyValue{key: "remote".to_string(), value: remote.to_string()}, - rustweb::KeyValue{key: "method".to_string(), value: method.to_string()}, - rustweb::KeyValue{key: "urlpath".to_string(), value: path.to_string()}, - rustweb::KeyValue{key: "HTTPVersion".to_string(), value: version}, - rustweb::KeyValue{key: "status".to_string(), value: response.status.to_string()}, - rustweb::KeyValue{key: "respsize".to_string(), value: len.to_string()}, - )); + rustweb::log( + &my_logger, + rustweb::Priority::Notice, + "Request", + &vec![ + rustweb::KeyValue { + key: "remote".to_string(), + value: remote.to_string(), + }, + rustweb::KeyValue { + key: "method".to_string(), + value: method.to_string(), + }, + rustweb::KeyValue { + key: "urlpath".to_string(), + value: path.to_string(), + }, + rustweb::KeyValue { + key: "HTTPVersion".to_string(), + value: version, + }, + rustweb::KeyValue { + key: "status".to_string(), + value: response.status.to_string(), + }, + rustweb::KeyValue { + key: "respsize".to_string(), + value: len.to_string(), + }, + ], + ); } Ok(rust_response) } -async fn serveweb_async(listener: TcpListener, config: crate::web::rustweb::IncomingTLS, ctx: Arc) -> MyResult<()> { - +async fn serveweb_async( + listener: TcpListener, + config: crate::web::rustweb::IncomingTLS, + ctx: Arc, +) -> MyResult<()> { if !config.certificate.is_empty() { let certs = load_certs(&config.certificate)?; let key = load_private_key(&config.key)?; @@ -553,12 +740,26 @@ async fn serveweb_async(listener: TcpListener, config: crate::web::rustweb::Inco address = addr; let combo = rustweb::comboaddress(&address.to_string()); if !rustweb::matches(&ctx.acl, &combo) { - rustweb::log(&ctx.logger, rustweb::Priority::Debug, "No ACL match", &vec!(rustweb::KeyValue{key: "address".to_string(), value: address.to_string()})); + rustweb::log( + &ctx.logger, + rustweb::Priority::Debug, + "No ACL match", + &vec![rustweb::KeyValue { + key: "address".to_string(), + value: address.to_string(), + }], + ); continue; } } Err(err) => { - rustweb::error(&ctx.logger, rustweb::Priority::Error, &err.to_string(), "Can't get peer address", &vec!()); + rustweb::error( + &ctx.logger, + rustweb::Priority::Error, + &err.to_string(), + "Can't get peer address", + &vec![], + ); continue; // If we can't determine the peer address, don't } } @@ -568,28 +769,41 @@ async fn serveweb_async(listener: TcpListener, config: crate::web::rustweb::Inco let tls_stream = match tls_acceptor.accept(stream).await { Ok(tls_stream) => tls_stream, Err(err) => { - rustweb::error(&ctx.logger, rustweb::Priority::Notice, &err.to_string(), "Failed to perform TLS handshake", &vec!()); + rustweb::error( + &ctx.logger, + rustweb::Priority::Notice, + &err.to_string(), + "Failed to perform TLS handshake", + &vec![], + ); continue; } }; let io = TokioIo::new(tls_stream); let my_logger = rustweb::withValue(&ctx.logger, "tls", "true"); - let fut = - http1::Builder::new().serve_connection(io, service_fn(move |req| { + let fut = http1::Builder::new().serve_connection( + io, + service_fn(move |req| { let ctx = Arc::clone(&ctx); process_request(req, ctx, address) - })); + }), + ); // Spawn a tokio task to serve the request tokio::task::spawn(async move { // Finally, we bind the incoming connection to our `process_request` service if let Err(err) = fut.await { - rustweb::error(&my_logger, rustweb::Priority::Notice, &err.to_string(), "Error serving web connection", &vec!()); + rustweb::error( + &my_logger, + rustweb::Priority::Notice, + &err.to_string(), + "Error serving web connection", + &vec![], + ); } }); } - } - else { + } else { // We start a loop to continuously accept incoming connections loop { let ctx = Arc::clone(&ctx); @@ -601,36 +815,65 @@ async fn serveweb_async(listener: TcpListener, config: crate::web::rustweb::Inco address = addr; let combo = rustweb::comboaddress(&address.to_string()); if !rustweb::matches(&ctx.acl, &combo) { - rustweb::log(&ctx.logger, rustweb::Priority::Debug, "No ACL match", &vec!(rustweb::KeyValue{key: "address".to_string(), value: address.to_string()})); + rustweb::log( + &ctx.logger, + rustweb::Priority::Debug, + "No ACL match", + &vec![rustweb::KeyValue { + key: "address".to_string(), + value: address.to_string(), + }], + ); continue; } } Err(err) => { - rustweb::error(&ctx.logger, rustweb::Priority::Error, &err.to_string(), "Can't get peer address", &vec!()); + rustweb::error( + &ctx.logger, + rustweb::Priority::Error, + &err.to_string(), + "Can't get peer address", + &vec![], + ); continue; // If we can't determine the peer address, don't } } let io = TokioIo::new(stream); let my_logger = rustweb::withValue(&ctx.logger, "tls", "false"); - let fut = - http1::Builder::new().serve_connection(io, service_fn(move |req| { + let fut = http1::Builder::new().serve_connection( + io, + service_fn(move |req| { let ctx = Arc::clone(&ctx); process_request(req, ctx, address) - })); + }), + ); // Spawn a tokio task to serve the request tokio::task::spawn(async move { // Finally, we bind the incoming connection to our `process_request` service if let Err(err) = fut.await { - rustweb::error(&my_logger, rustweb::Priority::Notice, &err.to_string(), "Error serving web connection", &vec!()); - } + rustweb::error( + &my_logger, + rustweb::Priority::Notice, + &err.to_string(), + "Error serving web connection", + &vec![], + ); + } }); } } } -pub fn serveweb(incoming: &Vec, urls: &[String], password_ch: cxx::UniquePtr, api_ch: cxx::UniquePtr, acl: cxx::UniquePtr, logger: cxx::UniquePtr, loglevel: rustweb::LogLevel) -> Result<(), std::io::Error> { - +pub fn serveweb( + incoming: &Vec, + urls: &[String], + password_ch: cxx::UniquePtr, + api_ch: cxx::UniquePtr, + acl: cxx::UniquePtr, + logger: cxx::UniquePtr, + loglevel: rustweb::LogLevel, +) -> Result<(), std::io::Error> { // Context, atomically reference counted let ctx = Arc::new(Context { urls: urls.to_vec(), @@ -652,7 +895,7 @@ pub fn serveweb(incoming: &Vec, urls: &[String], pass // waits (forever) for all of them to complete by joining them all. let mut set = JoinSet::new(); for config in incoming { - rustweb::log(&ctx.logger, rustweb::Priority::Warning, "Config", &vec!()); + rustweb::log(&ctx.logger, rustweb::Priority::Warning, "Config", &vec![]); for addr_str in &config.addresses { let addr = match SocketAddr::from_str(addr_str) { Ok(val) => val, @@ -675,17 +918,35 @@ pub fn serveweb(incoming: &Vec, urls: &[String], pass if !tls.certificate.is_empty() { tls_enabled = true; } - rustweb::log(&ctx.logger, rustweb::Priority::Info, "web service listening", - &vec!(rustweb::KeyValue{key: "address".to_string(), value: addr.to_string()}, - rustweb::KeyValue{key: "tls".to_string(), value: tls_enabled.to_string()} - ) + rustweb::log( + &ctx.logger, + rustweb::Priority::Info, + "web service listening", + &vec![ + rustweb::KeyValue { + key: "address".to_string(), + value: addr.to_string(), + }, + rustweb::KeyValue { + key: "tls".to_string(), + value: tls_enabled.to_string(), + }, + ], ); set.spawn_on(serveweb_async(val, tls, ctx), runtime.handle()); } Err(err) => { let msg = format!("Unable to bind web socket: {}", err); - rustweb::error(&ctx.logger, rustweb::Priority::Error, &err.to_string(), "Unable to bind to web socket", - &vec!(rustweb::KeyValue{key: "address".to_string(), value: addr.to_string()})); + rustweb::error( + &ctx.logger, + rustweb::Priority::Error, + &err.to_string(), + "Unable to bind to web socket", + &vec![rustweb::KeyValue { + key: "address".to_string(), + value: addr.to_string(), + }], + ); return Err(std::io::Error::new(ErrorKind::Other, msg)); } } @@ -697,7 +958,13 @@ pub fn serveweb(incoming: &Vec, urls: &[String], pass runtime.block_on(async { while let Some(res) = set.join_next().await { let msg = format!("{:?}", res); - rustweb::error(&ctx.logger, rustweb::Priority::Error, &msg, "rustweb thread exited", &vec!()); + rustweb::error( + &ctx.logger, + rustweb::Priority::Error, + &msg, + "rustweb thread exited", + &vec![], + ); } }); })?; @@ -707,8 +974,12 @@ pub fn serveweb(incoming: &Vec, urls: &[String], pass // Load public certificate from file. fn load_certs(filename: &str) -> std::io::Result>> { // Open certificate file. - let certfile = std::fs::File::open(filename) - .map_err(|e| std::io::Error::new(std::io::ErrorKind::Other, format!("failed to open {}: {}", filename, e)))?; + let certfile = std::fs::File::open(filename).map_err(|e| { + std::io::Error::new( + std::io::ErrorKind::Other, + format!("failed to open {}: {}", filename, e), + ) + })?; let mut reader = std::io::BufReader::new(certfile); // Load and return certificate. @@ -718,8 +989,12 @@ fn load_certs(filename: &str) -> std::io::Result std::io::Result> { // Open keyfile. - let keyfile = std::fs::File::open(filename) - .map_err(|e| std::io::Error::new(std::io::ErrorKind::Other, format!("failed to open {}: {}", filename, e)))?; + let keyfile = std::fs::File::open(filename).map_err(|e| { + std::io::Error::new( + std::io::ErrorKind::Other, + format!("failed to open {}: {}", filename, e), + ) + })?; let mut reader = std::io::BufReader::new(keyfile); // Load and return a single private key. @@ -758,7 +1033,15 @@ mod rustweb { */ extern "Rust" { // The main entry point, This function will return, but will setup thread(s) to handle requests. - fn serveweb(incoming: &Vec, urls: &[String], pwch: UniquePtr, apikeych: UniquePtr, acl: UniquePtr, logger: UniquePtr, loglevel: LogLevel) -> Result<()>; + fn serveweb( + incoming: &Vec, + urls: &[String], + pwch: UniquePtr, + apikeych: UniquePtr, + acl: UniquePtr, + logger: UniquePtr, + loglevel: LogLevel, + ) -> Result<()>; } struct KeyValue { @@ -788,12 +1071,12 @@ mod rustweb { Warning = 4, Notice = 5, Info = 6, - Debug = 7 + Debug = 7, } enum LogLevel { None, Normal, - Detailed + Detailed, } /* * Functions callable from Rust @@ -807,8 +1090,14 @@ mod rustweb { fn apiServerConfig(request: &Request, response: &mut Response) -> Result<()>; fn apiServerConfigAllowFromGET(request: &Request, response: &mut Response) -> Result<()>; fn apiServerConfigAllowFromPUT(request: &Request, response: &mut Response) -> Result<()>; - fn apiServerConfigAllowNotifyFromGET(request: &Request, response: &mut Response) -> Result<()>; - fn apiServerConfigAllowNotifyFromPUT(request: &Request, response: &mut Response) -> Result<()>; + fn apiServerConfigAllowNotifyFromGET( + request: &Request, + response: &mut Response, + ) -> Result<()>; + fn apiServerConfigAllowNotifyFromPUT( + request: &Request, + response: &mut Response, + ) -> Result<()>; fn apiServerDetail(requst: &Request, response: &mut Response) -> Result<()>; fn apiServerRPZStats(request: &Request, response: &mut Response) -> Result<()>; fn apiServerSearchData(request: &Request, response: &mut Response) -> Result<()>; @@ -827,6 +1116,12 @@ mod rustweb { fn matches(nmg: &UniquePtr, address: &UniquePtr) -> bool; // match is a keyword fn withValue(logger: &UniquePtr, key: &str, val: &str) -> UniquePtr; fn log(logger: &UniquePtr, prio: Priority, msg: &str, values: &Vec); - fn error(logger: &UniquePtr, prio: Priority, err: &str, msg: &str, values: &Vec); + fn error( + logger: &UniquePtr, + prio: Priority, + err: &str, + msg: &str, + values: &Vec, + ); } } diff --git a/pdns/recursordist/ws-recursor.cc b/pdns/recursordist/ws-recursor.cc index 9e2e1e515e..2cf169283f 100644 --- a/pdns/recursordist/ws-recursor.cc +++ b/pdns/recursordist/ws-recursor.cc @@ -1048,7 +1048,6 @@ static void fromCxxToRust(const HttpResponse& cxxresp, pdns::rust::web::rec::Res } } - // Convert what we receive from Rust into C++ data, call funtions and convert results back to Rust data static void rustWrapper(const std::function& func, const pdns::rust::web::rec::Request& rustRequest, pdns::rust::web::rec::Response& rustResponse) {