From c1ac6de53cdef6eb006e89a04bc6684f29b616f3 Mon Sep 17 00:00:00 2001 From: David Pacheco Date: Fri, 27 Sep 2024 09:19:51 -0700 Subject: [PATCH 01/20] commonize HTTP/HTTPS paths and use more structured errors internally --- Cargo.lock | 9 +- dropshot/Cargo.toml | 1 + dropshot/src/server.rs | 484 +++++++++++++++++------------------------ 3 files changed, 203 insertions(+), 291 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 06d7bcfb..bb345814 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -396,6 +396,7 @@ dependencies = [ "slog-term", "subprocess", "tempfile", + "thiserror", "tokio", "tokio-rustls", "tokio-tungstenite", @@ -1838,18 +1839,18 @@ dependencies = [ [[package]] name = "thiserror" -version = "1.0.56" +version = "1.0.64" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d54378c645627613241d077a3a79db965db602882668f9136ac42af9ecb730ad" +checksum = "d50af8abc119fb8bb6dbabcfa89656f46f84aa0ac7688088608076ad2b459a84" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.56" +version = "1.0.64" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa0faa943b50f3db30a20aa7e265dbc66076993efed8463e8de414e5d06d3471" +checksum = "08904e7672f5eb876eaaf87e0ce17857500934f4981c4a0ab2b4aa98baac7fc3" dependencies = [ "proc-macro2", "quote", diff --git a/dropshot/Cargo.toml b/dropshot/Cargo.toml index 21c908a8..f41d22a0 100644 --- a/dropshot/Cargo.toml +++ b/dropshot/Cargo.toml @@ -42,6 +42,7 @@ slog-async = "2.8.0" slog-bunyan = "2.5.0" slog-json = "2.6.1" slog-term = "2.9.1" +thiserror = "1.0.64" tokio-rustls = "0.25.0" toml = "0.8.19" waitgroup = "0.1.2" diff --git a/dropshot/src/server.rs b/dropshot/src/server.rs index 8816c9f7..8272a64d 100644 --- a/dropshot/src/server.rs +++ b/dropshot/src/server.rs @@ -43,6 +43,7 @@ use waitgroup::WaitGroup; use crate::config::HandlerTaskMode; use crate::RequestInfo; use slog::Logger; +use thiserror::Error; // TODO Replace this with something else? type GenericError = Box; @@ -106,8 +107,9 @@ pub struct ServerConfig { pub struct HttpServerStarter { app_state: Arc>, local_addr: SocketAddr, - wrapped: WrappedHttpServerStarter, handler_waitgroup: WaitGroup, + incoming: HttpAcceptor, + tls_acceptor: Option>>, } impl HttpServerStarter { @@ -127,6 +129,17 @@ impl HttpServerStarter { log: &Logger, tls: Option, ) -> Result, GenericError> { + HttpServerStarter::new_internal(config, api, private, log, tls) + .map_err(|e| Box::new(e) as GenericError) + } + + fn new_internal( + config: &ConfigDropshot, + api: ApiDescription, + private: C, + log: &Logger, + tls: Option, + ) -> Result, BuildError> { let server_config = ServerConfig { // We start aggressively to ensure test coverage. request_body_max_bytes: config.request_body_max_bytes, @@ -135,68 +148,150 @@ impl HttpServerStarter { default_handler_task_mode: config.default_handler_task_mode, log_headers: config.log_headers.clone(), }; - let handler_waitgroup = WaitGroup::new(); - let starter = match &tls { - Some(tls) => { - let (starter, app_state, local_addr) = - InnerHttpsServerStarter::new( - config, - server_config, - api, - private, - log, - tls, - handler_waitgroup.worker(), - )?; - HttpServerStarter { - app_state, - local_addr, - wrapped: WrappedHttpServerStarter::Https(starter), - handler_waitgroup, - } - } - None => { - let (starter, app_state, local_addr) = - InnerHttpServerStarter::new( - config, - server_config, - api, - private, - log, - handler_waitgroup.worker(), - )?; - HttpServerStarter { - app_state, - local_addr, - wrapped: WrappedHttpServerStarter::Http(starter), - handler_waitgroup, - } - } - }; - for (path, method, _) in &starter.app_state.router { - debug!(starter.app_state.log, "registered endpoint"; + let std_listener = std::net::TcpListener::bind(&config.bind_address) + .map_err(|e| BuildError::bind_error(e, config.bind_address))?; + std_listener.set_nonblocking(true).map_err(|e| { + BuildError::generic_system(e, "setting non-blocking") + })?; + // We use `from_std` instead of just calling `bind` here directly + // to avoid invoking an async function. + let tcp = TcpListener::from_std(std_listener).map_err(|e| { + BuildError::generic_system(e, "creating TCP listener") + })?; + let local_addr = tcp.local_addr().map_err(|e| { + BuildError::generic_system(e, "getting local TCP address") + })?; + let incoming = HttpAcceptor { tcp, log: log.clone() }; + + let log = log.new(o!("local_addr" => local_addr)); + + let tls_acceptor = tls + .as_ref() + .map(|tls| { + Ok(Arc::new(Mutex::new(TlsAcceptor::from(Arc::new( + rustls::ServerConfig::try_from(tls)?, + ))))) + }) + .transpose()?; + + let app_state = Arc::new(DropshotState { + private, + config: server_config, + router: api.into_router(), + log: log.clone(), + local_addr, + tls_acceptor: tls_acceptor.clone(), + handler_waitgroup_worker: DebugIgnore(handler_waitgroup.worker()), + }); + + for (path, method, _) in &app_state.router { + debug!(&log, "registered endpoint"; "method" => &method, "path" => &path ); } - Ok(starter) + Ok(HttpServerStarter { + app_state, + local_addr, + handler_waitgroup, + incoming, + tls_acceptor, + }) } pub fn start(self) -> HttpServer { - let (tx, rx) = tokio::sync::oneshot::channel::<()>(); - let log_close = self.app_state.log.new(o!()); - let join_handle = match self.wrapped { - WrappedHttpServerStarter::Http(http) => http.start(rx, log_close), - WrappedHttpServerStarter::Https(https) => { - https.start(rx, log_close) - } - }; - info!(self.app_state.log, "listening"); + let HttpServerStarter { + app_state, + local_addr, + handler_waitgroup, + tls_acceptor, + incoming, // XXX-dap rename + } = self; + + let make_service = ServerConnectionHandler::new(Arc::clone(&app_state)); + + let (tx, mut rx) = tokio::sync::oneshot::channel::<()>(); + + let log = &app_state.log; + let log_close = log.clone(); + let join_handle = tokio::spawn(async move { + use hyper_util::rt::{TokioExecutor, TokioIo, TokioTimer}; + use hyper_util::server::conn::auto; + + let mut builder = auto::Builder::new(TokioExecutor::new()); + // http/1 settings + builder.http1().timer(TokioTimer::new()); + // XXX-dap previously, the TLS one did NOT do this http2 step + // http/2 settings + builder.http2().timer(TokioTimer::new()); + + // Use a graceful watcher to keep track of all existing connections, + // and when the close_signal is trigger, force all known conns + // to start a graceful shutdown. + let graceful = + hyper_util::server::graceful::GracefulShutdown::new(); + + // The following code looks superficially similar between the HTTP + // and HTTPS paths. However, the concrete types of various objects + // are different and so it's not easy to actually share the code. + let log = log_close; + match tls_acceptor { + Some(tls_acceptor) => { + let mut https_acceptor = + HttpsAcceptor::new(log.clone(), tls_acceptor, incoming); + loop { + tokio::select! { + Some(Ok(sock)) = https_acceptor.accept() => { + let remote_addr = sock.remote_addr(); + let handler = make_service + .make_http_request_handler(remote_addr); + let fut = builder + .serve_connection_with_upgrades( + TokioIo::new(sock), + handler, + ); + let fut = graceful.watch(fut.into_owned()); + tokio::spawn(fut); + }, + + _ = &mut rx => { + info!(log, "beginning graceful shutdown"); + break; + } + } + } + } + None => loop { + tokio::select! { + (sock, remote_addr) = incoming.accept() => { + let handler = make_service + .make_http_request_handler(remote_addr); + let fut = builder + .serve_connection_with_upgrades( + TokioIo::new(sock), + handler, + ); + let fut = graceful.watch(fut.into_owned()); + tokio::spawn(fut); + }, + + _ = &mut rx => { + info!(log, "beginning graceful shutdown"); + break; + } + } + }, + }; + + // optional: could use another select on a timeout + graceful.shutdown().await + }); + + info!(log, "listening"); - let handler_waitgroup = self.handler_waitgroup; let join_handle = async move { // After the server shuts down, we also want to wait for any // detached handler futures to complete. @@ -210,139 +305,31 @@ impl HttpServerStarter { #[cfg(feature = "usdt-probes")] let probe_registration = match usdt::register_probes() { Ok(_) => { - debug!( - self.app_state.log, - "successfully registered DTrace USDT probes" - ); + debug!(&log, "successfully registered DTrace USDT probes"); ProbeRegistration::Succeeded } Err(e) => { let msg = e.to_string(); - error!( - self.app_state.log, - "failed to register DTrace USDT probes: {}", msg - ); + error!(&log, "failed to register DTrace USDT probes: {}", msg); ProbeRegistration::Failed(msg) } }; #[cfg(not(feature = "usdt-probes"))] let probe_registration = { - debug!( - self.app_state.log, - "DTrace USDT probes compiled out, not registering" - ); + debug!(&log, "DTrace USDT probes compiled out, not registering"); ProbeRegistration::Disabled }; HttpServer { probe_registration, - app_state: self.app_state, - local_addr: self.local_addr, + app_state, + local_addr, closer: CloseHandle { close_channel: Some(tx) }, join_future: join_handle.boxed().shared(), } } } -enum WrappedHttpServerStarter { - Http(InnerHttpServerStarter), - Https(InnerHttpsServerStarter), -} - -struct InnerHttpServerStarter( - HttpAcceptor, - ServerConnectionHandler, -); - -type InnerHttpServerStarterNewReturn = - (InnerHttpServerStarter, Arc>, SocketAddr); - -impl InnerHttpServerStarter { - /// Begins execution of the underlying Http server. - fn start( - self, - mut close_signal: tokio::sync::oneshot::Receiver<()>, - log_close: Logger, - ) -> tokio::task::JoinHandle<()> { - use hyper_util::rt::{TokioExecutor, TokioIo, TokioTimer}; - use hyper_util::server::conn::auto; - - tokio::spawn(async move { - let mut builder = auto::Builder::new(TokioExecutor::new()); - // http/1 settings - builder.http1().timer(TokioTimer::new()); - // http/2 settings - builder.http2().timer(TokioTimer::new()); - - // Use a graceful watcher to keep track of all existing connections, - // and when the close_signal is trigger, force all known conns - // to start a graceful shutdown. - let graceful = - hyper_util::server::graceful::GracefulShutdown::new(); - - loop { - tokio::select! { - (sock, remote_addr) = self.0.accept() => { - let fut = builder.serve_connection_with_upgrades( - TokioIo::new(sock), - self.1.make_http_request_handler(remote_addr), - ); - let fut = graceful.watch(fut.into_owned()); - tokio::spawn(fut); - }, - - _ = &mut close_signal => { - info!(log_close, "received request to begin graceful shutdown"); - break; - } - } - } - - // optional: could use another select on a timeout - graceful.shutdown().await - }) - } - - /// Set up an HTTP server bound on the specified address that runs - /// registered handlers. You must invoke `start()` on the returned instance - /// of `HttpServerStarter` (and await the result) to actually start the - /// server. - fn new( - config: &ConfigDropshot, - server_config: ServerConfig, - api: ApiDescription, - private: C, - log: &Logger, - handler_waitgroup_worker: waitgroup::Worker, - ) -> Result, std::io::Error> { - // We use `from_std` instead of just calling `bind` here directly - // to avoid invoking an async function. - let std_listener = std::net::TcpListener::bind(&config.bind_address)?; - std_listener.set_nonblocking(true)?; - let tcp = TcpListener::from_std(std_listener)?; - let local_addr = tcp.local_addr()?; - let incoming = - HttpAcceptor { tcp, log: log.new(o!("local_addr" => local_addr)) }; - - let app_state = Arc::new(DropshotState { - private, - config: server_config, - router: api.into_router(), - log: log.new(o!("local_addr" => local_addr)), - local_addr, - tls_acceptor: None, - handler_waitgroup_worker: DebugIgnore(handler_waitgroup_worker), - }); - - let make_service = ServerConnectionHandler::new(app_state.clone()); - Ok(( - InnerHttpServerStarter(incoming, make_service), - app_state, - local_addr, - )) - } -} - /// Accepts TCP connections like a `TcpListener`, but ignores transient errors rather than propagating them to the caller struct HttpAcceptor { tcp: TcpListener, @@ -508,16 +495,11 @@ impl HttpsAcceptor { } } -struct InnerHttpsServerStarter( - HttpsAcceptor, - ServerConnectionHandler, -); - /// Create a TLS configuration from the Dropshot config structure. impl TryFrom<&ConfigTls> for rustls::ServerConfig { - type Error = std::io::Error; + type Error = BuildError; - fn try_from(config: &ConfigTls) -> std::io::Result { + fn try_from(config: &ConfigTls) -> Result { let (mut cert_reader, mut key_reader): ( Box, Box, @@ -532,25 +514,17 @@ impl TryFrom<&ConfigTls> for rustls::ServerConfig { ConfigTls::AsFile { cert_file, key_file } => { let certfile = Box::new(std::io::BufReader::new( std::fs::File::open(cert_file).map_err(|e| { - std::io::Error::new( - std::io::ErrorKind::Other, - format!( - "failed to open {}: {}", - cert_file.display(), - e - ), + BuildError::generic_system( + e, + format!("opening {}", cert_file.display()), ) })?, )); let keyfile = Box::new(std::io::BufReader::new( std::fs::File::open(key_file).map_err(|e| { - std::io::Error::new( - std::io::ErrorKind::Other, - format!( - "failed to open {}: {}", - key_file.display(), - e - ), + BuildError::generic_system( + e, + format!("opening {}", key_file.display()), ) })?, )); @@ -561,17 +535,17 @@ impl TryFrom<&ConfigTls> for rustls::ServerConfig { let certs = rustls_pemfile::certs(&mut cert_reader) .collect::, _>>() .map_err(|err| { - io_error(format!("failed to load certificate: {err}")) + BuildError::generic_system(err, "loading TLS certificates") })?; let keys = rustls_pemfile::pkcs8_private_keys(&mut key_reader) .collect::, _>>() .map_err(|err| { - io_error(format!("failed to load private key: {err}")) + BuildError::generic_system(err, "loading TLS private key") })?; let mut keys_iter = keys.into_iter(); let (Some(private_key), None) = (keys_iter.next(), keys_iter.next()) else { - return Err(io_error("expected a single private key".into())); + return Err(BuildError::NotOnePrivateKey); }; let mut cfg = rustls::ServerConfig::builder() @@ -583,102 +557,6 @@ impl TryFrom<&ConfigTls> for rustls::ServerConfig { } } -type InnerHttpsServerStarterNewReturn = - (InnerHttpsServerStarter, Arc>, SocketAddr); - -impl InnerHttpsServerStarter { - /// Begins execution of the underlying Http server. - fn start( - mut self, - mut close_signal: tokio::sync::oneshot::Receiver<()>, - log_close: Logger, - ) -> tokio::task::JoinHandle<()> { - use hyper_util::rt::{TokioExecutor, TokioIo, TokioTimer}; - use hyper_util::server::conn::auto; - - tokio::spawn(async move { - let mut builder = auto::Builder::new(TokioExecutor::new()); - // http/1 settings - builder.http1().timer(TokioTimer::new()); - - // Use a graceful watcher to keep track of all existing connections, - // and when the close_signal is trigger, force all known conns - // to start a graceful shutdown. - let graceful = - hyper_util::server::graceful::GracefulShutdown::new(); - - loop { - tokio::select! { - Some(Ok(sock)) = self.0.accept() => { - let remote_addr = sock.remote_addr(); - let fut = builder.serve_connection_with_upgrades( - TokioIo::new(sock), - self.1.make_http_request_handler(remote_addr), - ); - let fut = graceful.watch(fut.into_owned()); - tokio::spawn(fut); - }, - - _ = &mut close_signal => { - info!(log_close, "received request to begin graceful shutdown"); - break; - } - } - } - - // optional: could use another select on a timeout - graceful.shutdown().await - }) - } - - fn new( - config: &ConfigDropshot, - server_config: ServerConfig, - api: ApiDescription, - private: C, - log: &Logger, - tls: &ConfigTls, - handler_waitgroup_worker: waitgroup::Worker, - ) -> Result, GenericError> { - let acceptor = Arc::new(Mutex::new(TlsAcceptor::from(Arc::new( - rustls::ServerConfig::try_from(tls)?, - )))); - - let tcp = { - let listener = std::net::TcpListener::bind(&config.bind_address)?; - listener.set_nonblocking(true)?; - // We use `from_std` instead of just calling `bind` here directly - // to avoid invoking an async function, to match the interface - // provided by `HttpServerStarter::new`. - TcpListener::from_std(listener)? - }; - - let local_addr = tcp.local_addr()?; - let logger = log.new(o!("local_addr" => local_addr)); - let tcp = HttpAcceptor { tcp, log: logger.clone() }; - let https_acceptor = - HttpsAcceptor::new(logger.clone(), acceptor.clone(), tcp); - - let app_state = Arc::new(DropshotState { - private, - config: server_config, - router: api.into_router(), - log: logger, - local_addr, - tls_acceptor: Some(acceptor), - handler_waitgroup_worker: DebugIgnore(handler_waitgroup_worker), - }); - - let make_service = ServerConnectionHandler::new(Arc::clone(&app_state)); - - Ok(( - InnerHttpsServerStarter(https_acceptor, make_service), - app_state, - local_addr, - )) - } -} - type SharedBoxFuture = Shared + Send>>>; /// Future returned by [`HttpServer::wait_for_shutdown()`]. @@ -1142,8 +1020,40 @@ impl Service> } } -fn io_error(err: String) -> std::io::Error { - std::io::Error::new(std::io::ErrorKind::Other, err) +/// Errors encountered while configuring a Dropshot server +#[derive(Debug, Error)] +pub enum BuildError { + #[error("failed to bind to {address}")] + BindError { + address: SocketAddr, + #[source] + error: std::io::Error, + }, + #[error("expected exactly one TLS private key")] + NotOnePrivateKey, + #[error("must register an API")] + MissingApi, + #[error("only one API can be registered with a server")] + TooManyApis, + #[error("{context}")] + SystemError { + context: String, + #[source] + error: std::io::Error, + }, +} + +impl BuildError { + fn bind_error(error: std::io::Error, address: SocketAddr) -> BuildError { + BuildError::BindError { address, error } + } + + fn generic_system>( + error: std::io::Error, + context: S, + ) -> BuildError { + BuildError::SystemError { context: context.into(), error } + } } #[cfg(test)] From eb0685dad04753060012d2f057e8512ecb545d8d Mon Sep 17 00:00:00 2001 From: David Pacheco Date: Fri, 27 Sep 2024 10:04:25 -0700 Subject: [PATCH 02/20] nits --- dropshot/src/server.rs | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/dropshot/src/server.rs b/dropshot/src/server.rs index 8272a64d..52c89807 100644 --- a/dropshot/src/server.rs +++ b/dropshot/src/server.rs @@ -108,7 +108,7 @@ pub struct HttpServerStarter { app_state: Arc>, local_addr: SocketAddr, handler_waitgroup: WaitGroup, - incoming: HttpAcceptor, + http_acceptor: HttpAcceptor, tls_acceptor: Option>>, } @@ -197,7 +197,7 @@ impl HttpServerStarter { app_state, local_addr, handler_waitgroup, - incoming, + http_acceptor: incoming, tls_acceptor, }) } @@ -208,7 +208,7 @@ impl HttpServerStarter { local_addr, handler_waitgroup, tls_acceptor, - incoming, // XXX-dap rename + http_acceptor, } = self; let make_service = ServerConnectionHandler::new(Arc::clone(&app_state)); @@ -240,8 +240,11 @@ impl HttpServerStarter { let log = log_close; match tls_acceptor { Some(tls_acceptor) => { - let mut https_acceptor = - HttpsAcceptor::new(log.clone(), tls_acceptor, incoming); + let mut https_acceptor = HttpsAcceptor::new( + log.clone(), + tls_acceptor, + http_acceptor, + ); loop { tokio::select! { Some(Ok(sock)) = https_acceptor.accept() => { @@ -266,7 +269,7 @@ impl HttpServerStarter { } None => loop { tokio::select! { - (sock, remote_addr) = incoming.accept() => { + (sock, remote_addr) = http_acceptor.accept() => { let handler = make_service .make_http_request_handler(remote_addr); let fut = builder From 979bdbaa432735da5aaddac05e44338ef830cc35 Mon Sep 17 00:00:00 2001 From: David Pacheco Date: Fri, 27 Sep 2024 10:09:15 -0700 Subject: [PATCH 03/20] more cleanup --- dropshot/src/server.rs | 49 ++++++++++++++++++++++-------------------- 1 file changed, 26 insertions(+), 23 deletions(-) diff --git a/dropshot/src/server.rs b/dropshot/src/server.rs index 52c89807..6ec5fbf4 100644 --- a/dropshot/src/server.rs +++ b/dropshot/src/server.rs @@ -140,6 +140,27 @@ impl HttpServerStarter { log: &Logger, tls: Option, ) -> Result, BuildError> { + let tcp = { + let std_listener = std::net::TcpListener::bind( + &config.bind_address, + ) + .map_err(|e| BuildError::bind_error(e, config.bind_address))?; + std_listener.set_nonblocking(true).map_err(|e| { + BuildError::generic_system(e, "setting non-blocking") + })?; + // We use `from_std` instead of just calling `bind` here directly + // to avoid invoking an async function. + TcpListener::from_std(std_listener).map_err(|e| { + BuildError::generic_system(e, "creating TCP listener") + })? + }; + + let local_addr = tcp.local_addr().map_err(|e| { + BuildError::generic_system(e, "getting local TCP address") + })?; + + let log = log.new(o!("local_addr" => local_addr)); + let server_config = ServerConfig { // We start aggressively to ensure test coverage. request_body_max_bytes: config.request_body_max_bytes, @@ -148,24 +169,6 @@ impl HttpServerStarter { default_handler_task_mode: config.default_handler_task_mode, log_headers: config.log_headers.clone(), }; - let handler_waitgroup = WaitGroup::new(); - - let std_listener = std::net::TcpListener::bind(&config.bind_address) - .map_err(|e| BuildError::bind_error(e, config.bind_address))?; - std_listener.set_nonblocking(true).map_err(|e| { - BuildError::generic_system(e, "setting non-blocking") - })?; - // We use `from_std` instead of just calling `bind` here directly - // to avoid invoking an async function. - let tcp = TcpListener::from_std(std_listener).map_err(|e| { - BuildError::generic_system(e, "creating TCP listener") - })?; - let local_addr = tcp.local_addr().map_err(|e| { - BuildError::generic_system(e, "getting local TCP address") - })?; - let incoming = HttpAcceptor { tcp, log: log.clone() }; - - let log = log.new(o!("local_addr" => local_addr)); let tls_acceptor = tls .as_ref() @@ -175,7 +178,7 @@ impl HttpServerStarter { ))))) }) .transpose()?; - + let handler_waitgroup = WaitGroup::new(); let app_state = Arc::new(DropshotState { private, config: server_config, @@ -193,11 +196,13 @@ impl HttpServerStarter { ); } + let http_acceptor = HttpAcceptor { tcp, log: log.clone() }; + Ok(HttpServerStarter { app_state, local_addr, handler_waitgroup, - http_acceptor: incoming, + http_acceptor, tls_acceptor, }) } @@ -211,10 +216,8 @@ impl HttpServerStarter { http_acceptor, } = self; - let make_service = ServerConnectionHandler::new(Arc::clone(&app_state)); - let (tx, mut rx) = tokio::sync::oneshot::channel::<()>(); - + let make_service = ServerConnectionHandler::new(Arc::clone(&app_state)); let log = &app_state.log; let log_close = log.clone(); let join_handle = tokio::spawn(async move { From 0e28f15a7f3dc7945c4a3b03811c692ce15ded90 Mon Sep 17 00:00:00 2001 From: David Pacheco Date: Fri, 27 Sep 2024 11:11:43 -0700 Subject: [PATCH 04/20] add builder interface for making servers --- CHANGELOG.adoc | 31 ++++++++ dropshot/examples/api-trait-alternate.rs | 14 +--- dropshot/examples/api-trait-websocket.rs | 14 +--- dropshot/examples/api-trait.rs | 14 +--- dropshot/examples/basic.rs | 21 +++--- dropshot/examples/https.rs | 28 ++----- dropshot/src/handler.rs | 4 +- dropshot/src/lib.rs | 21 ++---- dropshot/src/server.rs | 95 +++++++++++++++++++++++- dropshot/tests/test_tls.rs | 38 +++++----- 10 files changed, 177 insertions(+), 103 deletions(-) diff --git a/CHANGELOG.adoc b/CHANGELOG.adoc index 1c1cd048..4b1e442c 100644 --- a/CHANGELOG.adoc +++ b/CHANGELOG.adoc @@ -15,6 +15,37 @@ https://github.com/oxidecomputer/dropshot/compare/v0.12.0\...HEAD[Full list of commits] +* https://github.com/oxidecomputer/dropshot/pull/1122[#1122]Adds a new `ServerBuilder` as the primary way of constructing a Dropshot server. This replaces `HttpServerStarter::new()` and `HttpServerStarter::new_with_tls()`. These older functions still exist for compatibility. They may be removed in an upcoming release, along with the `HttpServerStarter`. ++ +In this release, the builder interface is not especially nicer than these older functions. As we look at adding new construction-time options (e.g., for API versioning), those will only be added to the builder. ++ +The builder also provides structured errors rather than the `GenericError` provided by these older functions. ++ +To switch to the new `ServerBuilder`, if you were using `HttpServerStarter::new()`, replace: ++ +```rust +HttpServerStarter::new(config, api, private, log) +``` ++ +with: ++ +```rust +ServerBuilder::new(api, private, log.clone()).config(config.clone()) +``` ++ +To switch to the new `ServerBuilder` if you were using `HttpServerStarter::new_with_tls()`, replace: ++ +```rust +HttpServerStarter::new_with_tls(config, api, private, log, tls) +``` ++ +with: ++ +```rust +ServerBuilder::new(api, private, log.clone()).config(config.clone()).tls(tls) +``` + + == 0.12.0 (released 2024-09-26) https://github.com/oxidecomputer/dropshot/compare/v0.11.0\...v0.12.0[Full list of commits] diff --git a/dropshot/examples/api-trait-alternate.rs b/dropshot/examples/api-trait-alternate.rs index 733442a8..8d4be075 100644 --- a/dropshot/examples/api-trait-alternate.rs +++ b/dropshot/examples/api-trait-alternate.rs @@ -74,7 +74,7 @@ //! [`AsyncWrite`](tokio::io::AsyncWrite) with a blanket impl. In that case, the //! behavior of methods like `AsyncWriteExt::write_all` cannot be overridden. -use dropshot::{ConfigLogging, ConfigLoggingLevel, HttpServerStarter}; +use dropshot::{ConfigLogging, ConfigLoggingLevel, ServerBuilder}; /// The interface. mod api { @@ -203,7 +203,6 @@ mod imp { #[tokio::main] async fn main() -> Result<(), String> { - let config_dropshot = Default::default(); // For simplicity, we'll configure an "info"-level logger that writes to // stderr assuming that it's a terminal. let config_logging = @@ -218,14 +217,9 @@ async fn main() -> Result<(), String> { let my_api = api::counter_api_mod::api_description::().unwrap(); - let server = HttpServerStarter::new( - &config_dropshot, - my_api, - imp::AtomicCounter::new(), - &log, - ) - .map_err(|error| format!("failed to create server: {}", error))? - .start(); + let server = ServerBuilder::new(my_api, imp::AtomicCounter::new(), log) + .start() + .map_err(|error| format!("failed to create server: {}", error))?; server.await } diff --git a/dropshot/examples/api-trait-websocket.rs b/dropshot/examples/api-trait-websocket.rs index 9f2d923d..c2713f05 100644 --- a/dropshot/examples/api-trait-websocket.rs +++ b/dropshot/examples/api-trait-websocket.rs @@ -2,7 +2,7 @@ //! Example use of `dropshot::api_description` with a WebSocket endpoint. -use dropshot::{ConfigLogging, ConfigLoggingLevel, HttpServerStarter}; +use dropshot::{ConfigLogging, ConfigLoggingLevel, ServerBuilder}; /// The interface. mod api { @@ -133,7 +133,6 @@ mod imp { #[tokio::main] async fn main() -> Result<(), String> { - let config_dropshot = Default::default(); // For simplicity, we'll configure an "info"-level logger that writes to // stderr assuming that it's a terminal. let config_logging = @@ -148,14 +147,9 @@ async fn main() -> Result<(), String> { let my_server = api::counter_api_mod::api_description::().unwrap(); - let server = HttpServerStarter::new( - &config_dropshot, - my_server, - imp::AtomicCounter::new(), - &log, - ) - .map_err(|error| format!("failed to create server: {}", error))? - .start(); + let server = ServerBuilder::new(my_server, imp::AtomicCounter::new(), log) + .start() + .map_err(|error| format!("failed to create server: {}", error))?; server.await } diff --git a/dropshot/examples/api-trait.rs b/dropshot/examples/api-trait.rs index e68684de..8054307f 100644 --- a/dropshot/examples/api-trait.rs +++ b/dropshot/examples/api-trait.rs @@ -15,7 +15,7 @@ //! //! This example puts the interface and implementation in separate modules. -use dropshot::{ConfigLogging, ConfigLoggingLevel, HttpServerStarter}; +use dropshot::{ConfigLogging, ConfigLoggingLevel, ServerBuilder}; /// The interface. mod api { @@ -134,7 +134,6 @@ mod imp { #[tokio::main] async fn main() -> Result<(), String> { - let config_dropshot = Default::default(); // For simplicity, we'll configure an "info"-level logger that writes to // stderr assuming that it's a terminal. let config_logging = @@ -151,14 +150,9 @@ async fn main() -> Result<(), String> { // type parameter. let my_api = api::counter_api_mod::api_description::().unwrap(); - let server = HttpServerStarter::new( - &config_dropshot, - my_api, - imp::AtomicCounter::new(), - &log, - ) - .map_err(|error| format!("failed to create server: {}", error))? - .start(); + let server = ServerBuilder::new(my_api, imp::AtomicCounter::new(), log) + .start() + .map_err(|error| format!("failed to create server: {}", error))?; server.await } diff --git a/dropshot/examples/basic.rs b/dropshot/examples/basic.rs index dbd7ea4d..6dc4a819 100644 --- a/dropshot/examples/basic.rs +++ b/dropshot/examples/basic.rs @@ -3,14 +3,13 @@ use dropshot::endpoint; use dropshot::ApiDescription; -use dropshot::ConfigDropshot; use dropshot::ConfigLogging; use dropshot::ConfigLoggingLevel; use dropshot::HttpError; use dropshot::HttpResponseOk; use dropshot::HttpResponseUpdatedNoContent; -use dropshot::HttpServerStarter; use dropshot::RequestContext; +use dropshot::ServerBuilder; use dropshot::TypedBody; use schemars::JsonSchema; use serde::Deserialize; @@ -20,12 +19,6 @@ use std::sync::atomic::Ordering; #[tokio::main] async fn main() -> Result<(), String> { - // We must specify a configuration with a bind address. We'll use 127.0.0.1 - // since it's available and won't expose this server outside the host. We - // request port 0, which allows the operating system to pick any available - // port. - let config_dropshot: ConfigDropshot = Default::default(); - // For simplicity, we'll configure an "info"-level logger that writes to // stderr assuming that it's a terminal. let config_logging = @@ -43,10 +36,14 @@ async fn main() -> Result<(), String> { let api_context = ExampleContext::new(); // Set up the server. - let server = - HttpServerStarter::new(&config_dropshot, api, api_context, &log) - .map_err(|error| format!("failed to create server: {}", error))? - .start(); + // + // We use the default configuration here, which uses 127.0.0.1 since it's + // always available and won't expose this server outside the host. It also + // uses port 0, which allows the operating system to pick any available + // port. + let server = ServerBuilder::new(api, api_context, log) + .start() + .map_err(|error| format!("failed to create server: {}", error))?; // Wait for the server to stop. Note that there's not any code to shut down // this server, so we should never get past this point. diff --git a/dropshot/examples/https.rs b/dropshot/examples/https.rs index 72900c3a..5e2245ba 100644 --- a/dropshot/examples/https.rs +++ b/dropshot/examples/https.rs @@ -4,15 +4,14 @@ use dropshot::endpoint; use dropshot::ApiDescription; -use dropshot::ConfigDropshot; use dropshot::ConfigLogging; use dropshot::ConfigLoggingLevel; use dropshot::ConfigTls; use dropshot::HttpError; use dropshot::HttpResponseOk; use dropshot::HttpResponseUpdatedNoContent; -use dropshot::HttpServerStarter; use dropshot::RequestContext; +use dropshot::ServerBuilder; use dropshot::TypedBody; use schemars::JsonSchema; use serde::Deserialize; @@ -52,17 +51,9 @@ fn generate_keys() -> Result<(NamedTempFile, NamedTempFile), String> { #[tokio::main] async fn main() -> Result<(), String> { - // Begin by generating TLS certificates and keys. A normal application would - // just pass the paths to these via ConfigDropshot. + // Begin by generating TLS certificates and keys and stuffing them into a + // TLS configuration. let (cert_file, key_file) = generate_keys()?; - - // We must specify a configuration with a bind address. We'll use 127.0.0.1 - // since it's available and won't expose this server outside the host. We - // request port 0, which allows the operating system to pick any available - // port. - // - // In addition, we'll make this an HTTPS server. - let config_dropshot = ConfigDropshot::default(); let config_tls = Some(ConfigTls::AsFile { cert_file: cert_file.path().to_path_buf(), key_file: key_file.path().to_path_buf(), @@ -85,15 +76,10 @@ async fn main() -> Result<(), String> { let api_context = ExampleContext::new(); // Set up the server. - let server = HttpServerStarter::new_with_tls( - &config_dropshot, - api, - api_context, - &log, - config_tls, - ) - .map_err(|error| format!("failed to create server: {}", error))? - .start(); + let server = ServerBuilder::new(api, api_context, log) + .tls(config_tls) + .start() + .map_err(|error| format!("failed to create server: {}", error))?; // Wait for the server to stop. Note that there's not any code to shut down // this server, so we should never get past this point. diff --git a/dropshot/src/handler.rs b/dropshot/src/handler.rs index b2faba7e..7e17f74a 100644 --- a/dropshot/src/handler.rs +++ b/dropshot/src/handler.rs @@ -567,8 +567,8 @@ impl HttpResponse for Response { } } -/// Wraps a [dropshot::Body] so that it can be used with coded response types such -/// as [HttpResponseOk]. +/// Wraps a [`Body`] so that it can be used with coded response types such as +/// [HttpResponseOk]. pub struct FreeformBody(pub Body); impl From for FreeformBody { diff --git a/dropshot/src/lib.rs b/dropshot/src/lib.rs index 8716777d..10f8d967 100644 --- a/dropshot/src/lib.rs +++ b/dropshot/src/lib.rs @@ -49,7 +49,7 @@ //! use dropshot::ConfigLogging; //! use dropshot::ConfigLoggingLevel; //! use dropshot::HandlerTaskMode; -//! use dropshot::HttpServerStarter; +//! use dropshot::ServerBuilder; //! use std::sync::Arc; //! //! #[tokio::main] @@ -67,20 +67,9 @@ //! // Register API functions -- see detailed example or ApiDescription docs. //! //! // Start the server. -//! let server = -//! HttpServerStarter::new( -//! &ConfigDropshot { -//! bind_address: "127.0.0.1:0".parse().unwrap(), -//! request_body_max_bytes: 1024, -//! default_handler_task_mode: HandlerTaskMode::Detached, -//! log_headers: Default::default(), -//! }, -//! api, -//! Arc::new(()), -//! &log, -//! ) -//! .map_err(|error| format!("failed to start server: {}", error))? -//! .start(); +//! let server = ServerBuilder::new(api, Arc::new(()), log) +//! .start() +//! .map_err(|error| format!("failed to start server: {}", error))?; //! //! server.await //! } @@ -836,6 +825,8 @@ pub use pagination::PaginationOrder; pub use pagination::PaginationParams; pub use pagination::ResultsPage; pub use pagination::WhichPage; +pub use server::BuildError; +pub use server::ServerBuilder; pub use server::ServerContext; pub use server::ShutdownWaitFuture; pub use server::{HttpServer, HttpServerStarter}; diff --git a/dropshot/src/server.rs b/dropshot/src/server.rs index 6ec5fbf4..0978c613 100644 --- a/dropshot/src/server.rs +++ b/dropshot/src/server.rs @@ -104,6 +104,10 @@ pub struct ServerConfig { pub log_headers: Vec, } +/// See [`ServerBuilder`] instead. +// It would be nice to remove this structure altogether once we've got +// confidence that no consumers actually need to distinguish between the +// configuration and start steps. pub struct HttpServerStarter { app_state: Arc>, local_addr: SocketAddr, @@ -113,15 +117,23 @@ pub struct HttpServerStarter { } impl HttpServerStarter { + /// Make an `HttpServerStarter` to start an `HttpServer` + /// + /// This function exists for backwards compatibility. You should use + /// [`ServerBuilder`] instead. pub fn new( config: &ConfigDropshot, api: ApiDescription, private: C, log: &Logger, ) -> Result, GenericError> { - Self::new_with_tls(config, api, private, log, None) + HttpServerStarter::new_with_tls(config, api, private, log, None) } + /// Make an `HttpServerStarter` to start an `HttpServer` + /// + /// This function exists for backwards compatibility. You should use + /// [`ServerBuilder`] instead. pub fn new_with_tls( config: &ConfigDropshot, api: ApiDescription, @@ -129,7 +141,10 @@ impl HttpServerStarter { log: &Logger, tls: Option, ) -> Result, GenericError> { - HttpServerStarter::new_internal(config, api, private, log, tls) + ServerBuilder::new(api, private, log.clone()) + .config(config.clone()) + .tls(tls) + .build_starter() .map_err(|e| Box::new(e) as GenericError) } @@ -336,7 +351,8 @@ impl HttpServerStarter { } } -/// Accepts TCP connections like a `TcpListener`, but ignores transient errors rather than propagating them to the caller +/// Accepts TCP connections like a `TcpListener`, but ignores transient errors +/// rather than propagating them to the caller struct HttpAcceptor { tcp: TcpListener, log: slog::Logger, @@ -1050,10 +1066,15 @@ pub enum BuildError { } impl BuildError { + /// Generate an error for failure to bind to `address` fn bind_error(error: std::io::Error, address: SocketAddr) -> BuildError { BuildError::BindError { address, error } } + /// Generate an error for any kind of `std::io::Error` + /// + /// `context` describes more about what we were trying to do that generated + /// the error. fn generic_system>( error: std::io::Error, context: S, @@ -1062,6 +1083,74 @@ impl BuildError { } } +/// Start configuring a Dropshot server +#[derive(Debug)] +pub struct ServerBuilder { + // required caller-provided values + private: C, + log: Logger, + api: DebugIgnore>, + + // optional caller-provided values + config: ConfigDropshot, + tls: Option, +} + +impl ServerBuilder { + /// Start configuring a new Dropshot server + /// + /// * `api`: the API to be hosted on this server + /// * `private`: your private data that will be made available in + /// `RequestContext` + /// * `log`: a slog logger for all server events + pub fn new( + api: ApiDescription, + private: C, + log: Logger, + ) -> ServerBuilder { + ServerBuilder { + private, + log, + api: DebugIgnore(api), + config: Default::default(), + tls: Default::default(), + } + } + + /// Specify the server configuration + pub fn config(mut self, config: ConfigDropshot) -> Self { + self.config = config; + self + } + + /// Specify the TLS configuration, if any + /// + /// `None` (the default) means no TLS. The server will listen for plain + /// HTTP. + pub fn tls(mut self, tls: Option) -> Self { + self.tls = tls; + self + } + + /// Start the server + pub fn start(self) -> Result, BuildError> { + Ok(self.build_starter()?.start()) + } + + /// Build an `HttpServerStarter` that can be used to start the server + /// + /// Most consumers probably want to use `start()` instead. + pub fn build_starter(self) -> Result, BuildError> { + HttpServerStarter::new_internal( + &self.config, + self.api.0, + self.private, + &self.log, + self.tls, + ) + } +} + #[cfg(test)] mod test { use super::*; diff --git a/dropshot/tests/test_tls.rs b/dropshot/tests/test_tls.rs index 3b6f14d7..9ac700ca 100644 --- a/dropshot/tests/test_tls.rs +++ b/dropshot/tests/test_tls.rs @@ -4,8 +4,8 @@ //! mode, including certificate loading and supported modes. use dropshot::{ - ConfigDropshot, ConfigTls, HandlerTaskMode, HttpResponseOk, - HttpServerStarter, + ConfigDropshot, ConfigTls, HandlerTaskMode, HttpResponseOk, HttpServer, + ServerBuilder, }; use slog::{o, Logger}; use std::convert::TryFrom; @@ -112,10 +112,10 @@ fn make_https_client< } fn make_server( - log: &Logger, + log: Logger, cert_file: &Path, key_file: &Path, -) -> HttpServerStarter { +) -> HttpServer { let config = ConfigDropshot { bind_address: "127.0.0.1:0".parse().unwrap(), request_body_max_bytes: 1024, @@ -126,14 +126,11 @@ fn make_server( cert_file: cert_file.to_path_buf(), key_file: key_file.to_path_buf(), }); - HttpServerStarter::new_with_tls( - &config, - dropshot::ApiDescription::new(), - 0, - log, - config_tls, - ) - .unwrap() + ServerBuilder::new(dropshot::ApiDescription::new(), 0, log) + .config(config) + .tls(config_tls) + .start() + .unwrap() } fn make_pki_verifier( @@ -155,7 +152,7 @@ async fn test_tls_certificate_loading() { let (certs, key) = common::generate_tls_key(); let (cert_file, key_file) = common::tls_key_to_file(&certs, &key); - let server = make_server(&log, cert_file.path(), key_file.path()).start(); + let server = make_server(log, cert_file.path(), key_file.path()); let port = server.local_addr().port(); let uri: hyper::Uri = @@ -210,7 +207,7 @@ async fn test_tls_only() { let (certs, key) = common::generate_tls_key(); let (cert_file, key_file) = common::tls_key_to_file(&certs, &key); - let server = make_server(&log, cert_file.path(), key_file.path()).start(); + let server = make_server(log, cert_file.path(), key_file.path()); let port = server.local_addr().port(); let https_uri: hyper::Uri = @@ -264,7 +261,7 @@ async fn test_tls_refresh_certificates() { let (certs, key) = generate_tls_key(); let (cert_file, key_file) = common::tls_key_to_file(&certs, &key); - let server = make_server(&log, cert_file.path(), key_file.path()).start(); + let server = make_server(log, cert_file.path(), key_file.path()); let port = server.local_addr().port(); let https_uri: hyper::Uri = @@ -356,7 +353,7 @@ async fn test_tls_aborted_negotiation() { let (certs, key) = common::generate_tls_key(); let (cert_file, key_file) = common::tls_key_to_file(&certs, &key); - let server = make_server(&log, cert_file.path(), key_file.path()).start(); + let server = make_server(log, cert_file.path(), key_file.path()); let port = server.local_addr().port(); let uri: hyper::Uri = @@ -445,10 +442,11 @@ async fn test_server_is_https() { }); let mut api = dropshot::ApiDescription::new(); api.register(tls_check_handler).unwrap(); - let server = - HttpServerStarter::new_with_tls(&config, api, 0, &log, config_tls) - .unwrap() - .start(); + let server = ServerBuilder::new(api, 0, log) + .tls(config_tls) + .config(config) + .start() + .unwrap(); let port = server.local_addr().port(); let https_client = make_https_client(make_pki_verifier(&certs)); From f70f667ba18cbe174944042de1a94dd48a1349d9 Mon Sep 17 00:00:00 2001 From: David Pacheco Date: Fri, 27 Sep 2024 11:13:20 -0700 Subject: [PATCH 05/20] nits --- CHANGELOG.adoc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.adoc b/CHANGELOG.adoc index 4b1e442c..aff1112b 100644 --- a/CHANGELOG.adoc +++ b/CHANGELOG.adoc @@ -15,9 +15,9 @@ https://github.com/oxidecomputer/dropshot/compare/v0.12.0\...HEAD[Full list of commits] -* https://github.com/oxidecomputer/dropshot/pull/1122[#1122]Adds a new `ServerBuilder` as the primary way of constructing a Dropshot server. This replaces `HttpServerStarter::new()` and `HttpServerStarter::new_with_tls()`. These older functions still exist for compatibility. They may be removed in an upcoming release, along with the `HttpServerStarter`. +* https://github.com/oxidecomputer/dropshot/pull/1122[#1122] Adds a new `ServerBuilder` as the primary way of constructing a Dropshot server. This replaces `HttpServerStarter::new()` and `HttpServerStarter::new_with_tls()`. These older functions still exist for compatibility. They may be removed in an upcoming release, along with the `HttpServerStarter`. + -In this release, the builder interface is not especially nicer than these older functions. As we look at adding new construction-time options (e.g., for API versioning), those will only be added to the builder. +In this release, using the builder interface is not very different from using these older functions. But as we look at adding new construction-time options (e.g., for API versioning), those will only be added to the builder. + The builder also provides structured errors rather than the `GenericError` provided by these older functions. + From 87c77b5635ae814ad8aa67dd3953da8a19b2dfbe Mon Sep 17 00:00:00 2001 From: David Pacheco Date: Fri, 27 Sep 2024 11:18:12 -0700 Subject: [PATCH 06/20] remove unnecessary XXX --- dropshot/src/server.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/dropshot/src/server.rs b/dropshot/src/server.rs index 6ec5fbf4..339c3db3 100644 --- a/dropshot/src/server.rs +++ b/dropshot/src/server.rs @@ -227,7 +227,6 @@ impl HttpServerStarter { let mut builder = auto::Builder::new(TokioExecutor::new()); // http/1 settings builder.http1().timer(TokioTimer::new()); - // XXX-dap previously, the TLS one did NOT do this http2 step // http/2 settings builder.http2().timer(TokioTimer::new()); From 517b35bdd9edcca4bc25abd5eb687d11aaa23829 Mon Sep 17 00:00:00 2001 From: David Pacheco Date: Mon, 30 Sep 2024 13:52:08 -0700 Subject: [PATCH 07/20] fix the rest of the tests and examples --- CHANGELOG.adoc | 31 ++++++++++++++----- dropshot/examples/api-trait-alternate.rs | 3 +- dropshot/examples/api-trait-websocket.rs | 3 +- dropshot/examples/api-trait.rs | 3 +- dropshot/examples/file_server.rs | 22 +++---------- dropshot/examples/https.rs | 9 ++---- dropshot/examples/index.rs | 22 +++---------- dropshot/examples/module-basic.rs | 23 +++----------- dropshot/examples/module-shared-context.rs | 25 +++------------ dropshot/examples/multipart.rs | 22 +++---------- dropshot/examples/multiple-servers.rs | 15 ++++----- dropshot/examples/pagination-basic.rs | 10 +++--- .../examples/pagination-multiple-resources.rs | 10 +++--- .../examples/pagination-multiple-sorts.rs | 10 +++--- dropshot/examples/request-headers.rs | 12 +++---- dropshot/examples/self-referential.rs | 13 +++----- dropshot/examples/websocket.rs | 22 +++---------- dropshot/examples/well-tagged.rs | 24 +++++--------- dropshot/src/test_util.rs | 10 +++--- dropshot/tests/test_config.rs | 22 ++++++------- dropshot_endpoint/src/api_trait.rs | 12 +++---- .../tests/output/api_trait_basic.rs | 12 +++---- .../tests/output/api_trait_no_endpoints.rs | 12 +++---- .../output/api_trait_with_custom_params.rs | 12 +++---- 24 files changed, 132 insertions(+), 227 deletions(-) diff --git a/CHANGELOG.adoc b/CHANGELOG.adoc index aff1112b..43f6ed64 100644 --- a/CHANGELOG.adoc +++ b/CHANGELOG.adoc @@ -21,30 +21,47 @@ In this release, using the builder interface is not very different from using th + The builder also provides structured errors rather than the `GenericError` provided by these older functions. + -To switch to the new `ServerBuilder`, if you were using `HttpServerStarter::new()`, replace: +Most non-TLS callers were using `HttpServerStarter::new()` and then calling `start()` right away. In that case, you can replace: + ```rust -HttpServerStarter::new(config, api, private, log) +HttpServerStarter::new(&config, api, private, &log).map_err(...)?.start() ``` + with: + ```rust -ServerBuilder::new(api, private, log.clone()).config(config.clone()) +ServerBuilder::new(api, private, log).config(config).start().map_err(...)? ``` + -To switch to the new `ServerBuilder` if you were using `HttpServerStarter::new_with_tls()`, replace: +If you were using `HttpServerStarter::new_with_tls()`, you'd similarly replace: + ```rust -HttpServerStarter::new_with_tls(config, api, private, log, tls) +HttpServerStarter::new_with_tls(&config, api, private, &log, tls).map_err(...)?.start() ``` + with: + ```rust -ServerBuilder::new(api, private, log.clone()).config(config.clone()).tls(tls) +ServerBuilder::new(api, private, log).config(config).tls(tls).start().map_err(...)? ``` - ++ +If you were _not_ invoking `start()` immediately before, you can still construct an intermediate starter object with `build_starter()`. If you were doing this: ++ +```rust` +let starter = HttpServerStarter::new(&config, api, private, &log).map_err(...)?; +... +starter.start() +``` ++ +Then you can now do: ++ +```rust +let starter = ServerBuilder::new(api, private, log).config(config).build_starter().map_err(...)?; +... +starter.start() +``` ++ +We'd like to remove the `HttpServerStarter` altogether, so let us know if you're still using it for some reason. == 0.12.0 (released 2024-09-26) diff --git a/dropshot/examples/api-trait-alternate.rs b/dropshot/examples/api-trait-alternate.rs index 8d4be075..74cc5598 100644 --- a/dropshot/examples/api-trait-alternate.rs +++ b/dropshot/examples/api-trait-alternate.rs @@ -203,8 +203,7 @@ mod imp { #[tokio::main] async fn main() -> Result<(), String> { - // For simplicity, we'll configure an "info"-level logger that writes to - // stderr assuming that it's a terminal. + // See dropshot/examples/basic.rs for more details on most of these pieces. let config_logging = ConfigLogging::StderrTerminal { level: ConfigLoggingLevel::Info }; let log = config_logging diff --git a/dropshot/examples/api-trait-websocket.rs b/dropshot/examples/api-trait-websocket.rs index c2713f05..9ef21e6a 100644 --- a/dropshot/examples/api-trait-websocket.rs +++ b/dropshot/examples/api-trait-websocket.rs @@ -133,8 +133,7 @@ mod imp { #[tokio::main] async fn main() -> Result<(), String> { - // For simplicity, we'll configure an "info"-level logger that writes to - // stderr assuming that it's a terminal. + // See dropshot/examples/basic.rs for more details on most of these pieces. let config_logging = ConfigLogging::StderrTerminal { level: ConfigLoggingLevel::Info }; let log = config_logging diff --git a/dropshot/examples/api-trait.rs b/dropshot/examples/api-trait.rs index 8054307f..6ab0c4a3 100644 --- a/dropshot/examples/api-trait.rs +++ b/dropshot/examples/api-trait.rs @@ -134,8 +134,7 @@ mod imp { #[tokio::main] async fn main() -> Result<(), String> { - // For simplicity, we'll configure an "info"-level logger that writes to - // stderr assuming that it's a terminal. + // See dropshot/examples/basic.rs for more details on most of these pieces. let config_logging = ConfigLogging::StderrTerminal { level: ConfigLoggingLevel::Info }; let log = config_logging diff --git a/dropshot/examples/file_server.rs b/dropshot/examples/file_server.rs index c9d6fdd9..58ae830d 100644 --- a/dropshot/examples/file_server.rs +++ b/dropshot/examples/file_server.rs @@ -7,8 +7,8 @@ use dropshot::Body; use dropshot::ConfigLogging; use dropshot::ConfigLoggingLevel; use dropshot::HttpError; -use dropshot::HttpServerStarter; use dropshot::RequestContext; +use dropshot::ServerBuilder; use dropshot::{endpoint, Path}; use http::{Response, StatusCode}; use schemars::JsonSchema; @@ -22,34 +22,22 @@ struct FileServerContext { #[tokio::main] async fn main() -> Result<(), String> { - // We must specify a configuration with a bind address. We'll use 127.0.0.1 - // since it's available and won't expose this server outside the host. We - // request port 0, which allows the operating system to pick any available - // port. - let config_dropshot = Default::default(); - - // For simplicity, we'll configure an "info"-level logger that writes to - // stderr assuming that it's a terminal. + // See dropshot/examples/basic.rs for more details on most of these pieces. let config_logging = ConfigLogging::StderrTerminal { level: ConfigLoggingLevel::Info }; let log = config_logging .to_logger("example-basic") .map_err(|error| format!("failed to create logger: {}", error))?; - // Build a description of the API -- in this case it's not much of an API!. let mut api = ApiDescription::new(); api.register(static_content).unwrap(); - // Specify the directory we want to serve. let context = FileServerContext { base: PathBuf::from(".") }; - // Set up the server. - let server = HttpServerStarter::new(&config_dropshot, api, context, &log) - .map_err(|error| format!("failed to create server: {}", error))? - .start(); + let server = ServerBuilder::new(api, context, log) + .start() + .map_err(|error| format!("failed to create server: {}", error))?; - // Wait for the server to stop. Note that there's not any code to shut down - // this server, so we should never get past this point. server.await } diff --git a/dropshot/examples/https.rs b/dropshot/examples/https.rs index 5e2245ba..7a17ba1e 100644 --- a/dropshot/examples/https.rs +++ b/dropshot/examples/https.rs @@ -59,30 +59,25 @@ async fn main() -> Result<(), String> { key_file: key_file.path().to_path_buf(), }); - // For simplicity, we'll configure an "info"-level logger that writes to - // stderr assuming that it's a terminal. + // See dropshot/examples/basic.rs for more details on most of these pieces. let config_logging = ConfigLogging::StderrTerminal { level: ConfigLoggingLevel::Info }; let log = config_logging .to_logger("example-basic") .map_err(|error| format!("failed to create logger: {}", error))?; - // Build a description of the API. let mut api = ApiDescription::new(); api.register(example_api_get_counter).unwrap(); api.register(example_api_put_counter).unwrap(); - // The functions that implement our API endpoints will share this context. let api_context = ExampleContext::new(); - // Set up the server. let server = ServerBuilder::new(api, api_context, log) + // This differs from the basic example: provide the TLS configuration. .tls(config_tls) .start() .map_err(|error| format!("failed to create server: {}", error))?; - // Wait for the server to stop. Note that there's not any code to shut down - // this server, so we should never get past this point. server.await } diff --git a/dropshot/examples/index.rs b/dropshot/examples/index.rs index 1fceee5e..54c9ef3c 100644 --- a/dropshot/examples/index.rs +++ b/dropshot/examples/index.rs @@ -3,12 +3,11 @@ use dropshot::ApiDescription; use dropshot::Body; -use dropshot::ConfigDropshot; use dropshot::ConfigLogging; use dropshot::ConfigLoggingLevel; use dropshot::HttpError; -use dropshot::HttpServerStarter; use dropshot::RequestContext; +use dropshot::ServerBuilder; use dropshot::{endpoint, Path}; use http::{Response, StatusCode}; use schemars::JsonSchema; @@ -16,31 +15,20 @@ use serde::Deserialize; #[tokio::main] async fn main() -> Result<(), String> { - // We must specify a configuration with a bind address. We'll use 127.0.0.1 - // since it's available and won't expose this server outside the host. We - // request port 0, which allows the operating system to pick any available - // port. - let config_dropshot: ConfigDropshot = Default::default(); - - // For simplicity, we'll configure an "info"-level logger that writes to - // stderr assuming that it's a terminal. + // See dropshot/examples/basic.rs for more details on most of these pieces. let config_logging = ConfigLogging::StderrTerminal { level: ConfigLoggingLevel::Info }; let log = config_logging .to_logger("example-basic") .map_err(|error| format!("failed to create logger: {}", error))?; - // Build a description of the API. let mut api = ApiDescription::new(); api.register(index).unwrap(); - // Set up the server. - let server = HttpServerStarter::new(&config_dropshot, api, (), &log) - .map_err(|error| format!("failed to create server: {}", error))? - .start(); + let server = ServerBuilder::new(api, (), log) + .start() + .map_err(|error| format!("failed to create server: {}", error))?; - // Wait for the server to stop. Note that there's not any code to shut down - // this server, so we should never get past this point. server.await } diff --git a/dropshot/examples/module-basic.rs b/dropshot/examples/module-basic.rs index 4b95d6f0..43373347 100644 --- a/dropshot/examples/module-basic.rs +++ b/dropshot/examples/module-basic.rs @@ -4,7 +4,7 @@ use dropshot::ApiDescription; use dropshot::ConfigLogging; use dropshot::ConfigLoggingLevel; -use dropshot::HttpServerStarter; +use dropshot::ServerBuilder; use schemars::JsonSchema; use serde::Deserialize; use serde::Serialize; @@ -12,36 +12,23 @@ use std::sync::atomic::AtomicU64; #[tokio::main] async fn main() -> Result<(), String> { - // We must specify a configuration with a bind address. We'll use 127.0.0.1 - // since it's available and won't expose this server outside the host. We - // request port 0, which allows the operating system to pick any available - // port. - let config_dropshot = Default::default(); - - // For simplicity, we'll configure an "info"-level logger that writes to - // stderr assuming that it's a terminal. + // See dropshot/examples/basic.rs for more details on most of these pieces. let config_logging = ConfigLogging::StderrTerminal { level: ConfigLoggingLevel::Info }; let log = config_logging .to_logger("example-basic") .map_err(|error| format!("failed to create logger: {}", error))?; - // Build a description of the API. let mut api = ApiDescription::new(); api.register(routes::example_api_get_counter).unwrap(); api.register(routes::example_api_put_counter).unwrap(); - // The functions that implement our API endpoints will share this context. let api_context = ExampleContext::new(); - // Set up the server. - let server = - HttpServerStarter::new(&config_dropshot, api, api_context, &log) - .map_err(|error| format!("failed to create server: {}", error))? - .start(); + let server = ServerBuilder::new(api, api_context, log) + .start() + .map_err(|error| format!("failed to create server: {}", error))?; - // Wait for the server to stop. Note that there's not any code to shut down - // this server, so we should never get past this point. server.await } diff --git a/dropshot/examples/module-shared-context.rs b/dropshot/examples/module-shared-context.rs index 3d9ecdf0..b1becf33 100644 --- a/dropshot/examples/module-shared-context.rs +++ b/dropshot/examples/module-shared-context.rs @@ -8,8 +8,8 @@ use dropshot::ConfigLogging; use dropshot::ConfigLoggingLevel; use dropshot::HttpError; use dropshot::HttpResponseOk; -use dropshot::HttpServerStarter; use dropshot::RequestContext; +use dropshot::ServerBuilder; use futures::FutureExt; use schemars::JsonSchema; use serde::Deserialize; @@ -20,36 +20,21 @@ use std::sync::Arc; #[tokio::main] async fn main() -> Result<(), String> { - // We must specify a configuration with a bind address. We'll use 127.0.0.1 - // since it's available and won't expose this server outside the host. We - // request port 0, which allows the operating system to pick any available - // port. - let config_dropshot = Default::default(); - - // For simplicity, we'll configure an "info"-level logger that writes to - // stderr assuming that it's a terminal. + // See dropshot/examples/basic.rs for more details on most of these pieces. let config_logging = ConfigLogging::StderrTerminal { level: ConfigLoggingLevel::Info }; let log = config_logging .to_logger("example-basic") .map_err(|error| format!("failed to create logger: {}", error))?; - // Build a description of the API. let mut api = ApiDescription::new(); api.register(example_api_get_counter).unwrap(); - // The functions that implement our API endpoints will share this context. let api_context = Arc::new(ExampleContext::new()); - // Set up the server. - let server = HttpServerStarter::new( - &config_dropshot, - api, - api_context.clone(), - &log, - ) - .map_err(|error| format!("failed to create server: {}", error))? - .start(); + let server = ServerBuilder::new(api, api_context.clone(), log) + .start() + .map_err(|error| format!("failed to create server: {}", error))?; // Wait for the server to stop. Note that there's not any code to shut down // this server, so we should never get past this point. diff --git a/dropshot/examples/multipart.rs b/dropshot/examples/multipart.rs index b61649db..211d400f 100644 --- a/dropshot/examples/multipart.rs +++ b/dropshot/examples/multipart.rs @@ -4,42 +4,30 @@ use dropshot::endpoint; use dropshot::ApiDescription; use dropshot::Body; -use dropshot::ConfigDropshot; use dropshot::ConfigLogging; use dropshot::ConfigLoggingLevel; use dropshot::HttpError; -use dropshot::HttpServerStarter; use dropshot::MultipartBody; use dropshot::RequestContext; +use dropshot::ServerBuilder; use http::{Response, StatusCode}; #[tokio::main] async fn main() -> Result<(), String> { - // We must specify a configuration with a bind address. We'll use 127.0.0.1 - // since it's available and won't expose this server outside the host. We - // request port 0, which allows the operating system to pick any available - // port. - let config_dropshot: ConfigDropshot = Default::default(); - - // For simplicity, we'll configure an "info"-level logger that writes to - // stderr assuming that it's a terminal. + // See dropshot/examples/basic.rs for more details on most of these pieces. let config_logging = ConfigLogging::StderrTerminal { level: ConfigLoggingLevel::Info }; let log = config_logging .to_logger("example-basic") .map_err(|error| format!("failed to create logger: {}", error))?; - // Build a description of the API. let mut api = ApiDescription::new(); api.register(index).unwrap(); - // Set up the server. - let server = HttpServerStarter::new(&config_dropshot, api, (), &log) - .map_err(|error| format!("failed to create server: {}", error))? - .start(); + let server = ServerBuilder::new(api, (), log) + .start() + .map_err(|error| format!("failed to create server: {}", error))?; - // Wait for the server to stop. Note that there's not any code to shut down - // this server, so we should never get past this point. server.await } diff --git a/dropshot/examples/multiple-servers.rs b/dropshot/examples/multiple-servers.rs index 1f11098c..b3810fec 100644 --- a/dropshot/examples/multiple-servers.rs +++ b/dropshot/examples/multiple-servers.rs @@ -77,9 +77,9 @@ use dropshot::HttpResponseCreated; use dropshot::HttpResponseDeleted; use dropshot::HttpResponseOk; use dropshot::HttpServer; -use dropshot::HttpServerStarter; use dropshot::Path; use dropshot::RequestContext; +use dropshot::ServerBuilder; use dropshot::TypedBody; use futures::future::BoxFuture; use futures::stream::FuturesUnordered; @@ -191,16 +191,13 @@ impl SharedMultiServerContext { Entry::Vacant(slot) => slot, }; - // For simplicity, we'll configure an "info"-level logger that writes to - // stderr assuming that it's a terminal. + // See dropshot/examples/basic.rs for more details on most of these pieces. let config_logging = ConfigLogging::StderrTerminal { level: ConfigLoggingLevel::Info }; let log = config_logging .to_logger(format!("example-multiserver-{name}")) .map_err(|error| format!("failed to create logger: {}", error))?; - // Build a description of the API. - // // TODO: Could `ApiDescription` implement `Clone`, or could we pass an // `Arc` instead? let mut api = ApiDescription::new(); @@ -218,10 +215,10 @@ impl SharedMultiServerContext { name: name.to_string(), log: log.clone(), }; - let server = - HttpServerStarter::new(&config_dropshot, api, context, &log) - .map_err(|error| format!("failed to create server: {}", error))? - .start(); + let server = ServerBuilder::new(api, context, log) + .config(config_dropshot) + .start() + .map_err(|error| format!("failed to create server: {}", error))?; let shutdown_handle = server.wait_for_shutdown(); slot.insert(server); diff --git a/dropshot/examples/pagination-basic.rs b/dropshot/examples/pagination-basic.rs index 38c0344c..395cca31 100644 --- a/dropshot/examples/pagination-basic.rs +++ b/dropshot/examples/pagination-basic.rs @@ -68,11 +68,11 @@ use dropshot::ConfigLoggingLevel; use dropshot::EmptyScanParams; use dropshot::HttpError; use dropshot::HttpResponseOk; -use dropshot::HttpServerStarter; use dropshot::PaginationParams; use dropshot::Query; use dropshot::RequestContext; use dropshot::ResultsPage; +use dropshot::ServerBuilder; use dropshot::WhichPage; use schemars::JsonSchema; use serde::Deserialize; @@ -146,6 +146,7 @@ async fn example_list_projects( #[tokio::main] async fn main() -> Result<(), String> { + // See dropshot/examples/basic.rs for more details on most of these pieces. let port = std::env::args() .nth(1) .map(|p| p.parse::()) @@ -174,8 +175,9 @@ async fn main() -> Result<(), String> { .map_err(|error| format!("failed to create logger: {}", error))?; let mut api = ApiDescription::new(); api.register(example_list_projects).unwrap(); - let server = HttpServerStarter::new(&config_dropshot, api, ctx, &log) - .map_err(|error| format!("failed to create server: {}", error))? - .start(); + let server = ServerBuilder::new(api, ctx, log) + .config(config_dropshot) + .start() + .map_err(|error| format!("failed to create server: {}", error))?; server.await } diff --git a/dropshot/examples/pagination-multiple-resources.rs b/dropshot/examples/pagination-multiple-resources.rs index f4afea27..63775551 100644 --- a/dropshot/examples/pagination-multiple-resources.rs +++ b/dropshot/examples/pagination-multiple-resources.rs @@ -10,7 +10,6 @@ use dropshot::ConfigLogging; use dropshot::ConfigLoggingLevel; use dropshot::HttpError; use dropshot::HttpResponseOk; -use dropshot::HttpServerStarter; use dropshot::PaginationOrder; use dropshot::PaginationOrder::Ascending; use dropshot::PaginationOrder::Descending; @@ -18,6 +17,7 @@ use dropshot::PaginationParams; use dropshot::Query; use dropshot::RequestContext; use dropshot::ResultsPage; +use dropshot::ServerBuilder; use dropshot::WhichPage; use schemars::JsonSchema; use serde::Deserialize; @@ -276,6 +276,7 @@ async fn main() -> Result<(), String> { .unwrap_or(0); // Run the Dropshot server. + // See dropshot/examples/basic.rs for more details on most of these pieces. let ctx = DataCollection::new(); let config_dropshot = ConfigDropshot { bind_address: SocketAddr::from((Ipv4Addr::LOCALHOST, port)), @@ -290,9 +291,10 @@ async fn main() -> Result<(), String> { api.register(example_list_projects).unwrap(); api.register(example_list_disks).unwrap(); api.register(example_list_instances).unwrap(); - let server = HttpServerStarter::new(&config_dropshot, api, ctx, &log) - .map_err(|error| format!("failed to create server: {}", error))? - .start(); + let server = ServerBuilder::new(api, ctx, log) + .config(config_dropshot) + .start() + .map_err(|error| format!("failed to create server: {}", error))?; server.await } diff --git a/dropshot/examples/pagination-multiple-sorts.rs b/dropshot/examples/pagination-multiple-sorts.rs index 7f673f74..133cb0f7 100644 --- a/dropshot/examples/pagination-multiple-sorts.rs +++ b/dropshot/examples/pagination-multiple-sorts.rs @@ -98,7 +98,6 @@ use dropshot::ConfigLogging; use dropshot::ConfigLoggingLevel; use dropshot::HttpError; use dropshot::HttpResponseOk; -use dropshot::HttpServerStarter; use dropshot::PaginationOrder; use dropshot::PaginationOrder::Ascending; use dropshot::PaginationOrder::Descending; @@ -106,6 +105,7 @@ use dropshot::PaginationParams; use dropshot::Query; use dropshot::RequestContext; use dropshot::ResultsPage; +use dropshot::ServerBuilder; use dropshot::WhichPage; use hyper::Uri; use schemars::JsonSchema; @@ -292,6 +292,7 @@ async fn main() -> Result<(), String> { .unwrap_or(0); // Run the Dropshot server. + // See dropshot/examples/basic.rs for more details on most of these pieces. let ctx = ProjectCollection::new(); let config_dropshot = ConfigDropshot { bind_address: SocketAddr::from((Ipv4Addr::LOCALHOST, port)), @@ -304,9 +305,10 @@ async fn main() -> Result<(), String> { .map_err(|error| format!("failed to create logger: {}", error))?; let mut api = ApiDescription::new(); api.register(example_list_projects).unwrap(); - let server = HttpServerStarter::new(&config_dropshot, api, ctx, &log) - .map_err(|error| format!("failed to create server: {}", error))? - .start(); + let server = ServerBuilder::new(api, ctx, log.clone()) + .config(config_dropshot) + .start() + .map_err(|error| format!("failed to create server: {}", error))?; // Print out some example requests to start with. print_example_requests(log, &server.local_addr()); diff --git a/dropshot/examples/request-headers.rs b/dropshot/examples/request-headers.rs index a32916d5..0c09f9d2 100644 --- a/dropshot/examples/request-headers.rs +++ b/dropshot/examples/request-headers.rs @@ -12,17 +12,16 @@ use dropshot::endpoint; use dropshot::ApiDescription; -use dropshot::ConfigDropshot; use dropshot::ConfigLogging; use dropshot::ConfigLoggingLevel; use dropshot::HttpError; use dropshot::HttpResponseOk; -use dropshot::HttpServerStarter; use dropshot::RequestContext; +use dropshot::ServerBuilder; #[tokio::main] async fn main() -> Result<(), String> { - let config_dropshot: ConfigDropshot = Default::default(); + // See dropshot/examples/basic.rs for more details on most of these pieces. let config_logging = ConfigLogging::StderrTerminal { level: ConfigLoggingLevel::Info }; let log = config_logging @@ -32,10 +31,9 @@ async fn main() -> Result<(), String> { api.register(example_api_get_header_generic).unwrap(); let api_context = (); - let server = - HttpServerStarter::new(&config_dropshot, api, api_context, &log) - .map_err(|error| format!("failed to create server: {}", error))? - .start(); + let server = ServerBuilder::new(api, api_context, log) + .start() + .map_err(|error| format!("failed to create server: {}", error))?; server.await } diff --git a/dropshot/examples/self-referential.rs b/dropshot/examples/self-referential.rs index fb7d7c2f..9334f3a2 100644 --- a/dropshot/examples/self-referential.rs +++ b/dropshot/examples/self-referential.rs @@ -4,13 +4,12 @@ use dropshot::endpoint; use dropshot::ApiDescription; -use dropshot::ConfigDropshot; use dropshot::ConfigLogging; use dropshot::ConfigLoggingLevel; use dropshot::HttpError; use dropshot::HttpResponseOk; -use dropshot::HttpServerStarter; use dropshot::RequestContext; +use dropshot::ServerBuilder; use schemars::JsonSchema; use serde::Deserialize; use serde::Serialize; @@ -20,7 +19,7 @@ use std::sync::Arc; #[tokio::main] async fn main() -> Result<(), String> { - let config_dropshot: ConfigDropshot = Default::default(); + // See dropshot/examples/basic.rs for more details on most of these pieces. let config_logging = ConfigLogging::StderrTerminal { level: ConfigLoggingLevel::Info }; let log = config_logging @@ -32,11 +31,9 @@ async fn main() -> Result<(), String> { let api_context = Arc::new(ExampleContext::new()); - // Set up the server. - let server = - HttpServerStarter::new(&config_dropshot, api, api_context, &log) - .map_err(|error| format!("failed to create server: {}", error))? - .start(); + let server = ServerBuilder::new(api, api_context, log) + .start() + .map_err(|error| format!("failed to create server: {}", error))?; let shutdown = server.wait_for_shutdown(); tokio::task::spawn(async move { diff --git a/dropshot/examples/websocket.rs b/dropshot/examples/websocket.rs index 5fa128cd..1bcec4de 100644 --- a/dropshot/examples/websocket.rs +++ b/dropshot/examples/websocket.rs @@ -3,12 +3,11 @@ use dropshot::channel; use dropshot::ApiDescription; -use dropshot::ConfigDropshot; use dropshot::ConfigLogging; use dropshot::ConfigLoggingLevel; -use dropshot::HttpServerStarter; use dropshot::Query; use dropshot::RequestContext; +use dropshot::ServerBuilder; use dropshot::WebsocketConnection; use futures::SinkExt; use schemars::JsonSchema; @@ -18,31 +17,20 @@ use tokio_tungstenite::tungstenite::Message; #[tokio::main] async fn main() -> Result<(), String> { - // We must specify a configuration with a bind address. We'll use 127.0.0.1 - // since it's available and won't expose this server outside the host. We - // request port 0, which allows the operating system to pick any available - // port. - let config_dropshot: ConfigDropshot = Default::default(); - - // For simplicity, we'll configure an "info"-level logger that writes to - // stderr assuming that it's a terminal. + // See dropshot/examples/basic.rs for more details on most of these pieces. let config_logging = ConfigLogging::StderrTerminal { level: ConfigLoggingLevel::Info }; let log = config_logging .to_logger("example-basic") .map_err(|error| format!("failed to create logger: {}", error))?; - // Build a description of the API. let mut api = ApiDescription::new(); api.register(example_api_websocket_counter).unwrap(); - // Set up the server. - let server = HttpServerStarter::new(&config_dropshot, api, (), &log) - .map_err(|error| format!("failed to create server: {}", error))? - .start(); + let server = ServerBuilder::new(api, (), log) + .start() + .map_err(|error| format!("failed to create server: {}", error))?; - // Wait for the server to stop. Note that there's not any code to shut down - // this server, so we should never get past this point. server.await } diff --git a/dropshot/examples/well-tagged.rs b/dropshot/examples/well-tagged.rs index 84c69a94..354aaa69 100644 --- a/dropshot/examples/well-tagged.rs +++ b/dropshot/examples/well-tagged.rs @@ -7,8 +7,8 @@ use dropshot::{ endpoint, ApiDescription, ConfigLogging, ConfigLoggingLevel, - EndpointTagPolicy, HttpError, HttpResponseOk, HttpServerStarter, - RequestContext, TagConfig, TagDetails, TagExternalDocs, + EndpointTagPolicy, HttpError, HttpResponseOk, RequestContext, + ServerBuilder, TagConfig, TagDetails, TagExternalDocs, }; #[endpoint { @@ -46,21 +46,14 @@ async fn get_fryism( #[tokio::main] async fn main() -> Result<(), String> { - // We must specify a configuration with a bind address. We'll use 127.0.0.1 - // since it's available and won't expose this server outside the host. We - // request port 0, which allows the operating system to pick any available - // port. - let config_dropshot = Default::default(); - - // For simplicity, we'll configure an "info"-level logger that writes to - // stderr assuming that it's a terminal. + // See dropshot/examples/basic.rs for more details on most of these pieces. let config_logging = ConfigLogging::StderrTerminal { level: ConfigLoggingLevel::Info }; let log = config_logging .to_logger("example-basic") .map_err(|error| format!("failed to create logger: {}", error))?; - // Build a description of the API -- in this case it's not much of an API!. + // Build a description of the API -- in this case it's not much of an API! let mut api = ApiDescription::new().tag_config(TagConfig { allow_other_tags: false, policy: EndpointTagPolicy::ExactlyOne, @@ -98,12 +91,9 @@ async fn main() -> Result<(), String> { api.register(get_barneyism).unwrap(); api.register(get_fryism).unwrap(); - // Set up the server. - let server = HttpServerStarter::new(&config_dropshot, api, (), &log) - .map_err(|error| format!("failed to create server: {}", error))? - .start(); + let server = ServerBuilder::new(api, (), log) + .start() + .map_err(|error| format!("failed to create server: {}", error))?; - // Wait for the server to stop. Note that there's not any code to shut down - // this server, so we should never get past this point. server.await } diff --git a/dropshot/src/test_util.rs b/dropshot/src/test_util.rs index caff1cbc..ce6b23d3 100644 --- a/dropshot/src/test_util.rs +++ b/dropshot/src/test_util.rs @@ -32,7 +32,7 @@ use crate::error::HttpErrorResponseBody; use crate::http_util::CONTENT_TYPE_URL_ENCODED; use crate::logging::ConfigLogging; use crate::pagination::ResultsPage; -use crate::server::{HttpServer, HttpServerStarter, ServerContext}; +use crate::server::{HttpServer, ServerBuilder, ServerContext}; enum AllowedValue<'a> { Any, @@ -490,10 +490,10 @@ impl TestContext { ); // Set up the server itself. - let server = - HttpServerStarter::new(&config_dropshot, api, private, &log) - .unwrap() - .start(); + let server = ServerBuilder::new(api, private, log.clone()) + .config(config_dropshot.clone()) + .start() + .unwrap(); let server_addr = server.local_addr(); let client_log = log.new(o!("http_client" => "dropshot test suite")); diff --git a/dropshot/tests/test_config.rs b/dropshot/tests/test_config.rs index bff8c663..f2b71d7b 100644 --- a/dropshot/tests/test_config.rs +++ b/dropshot/tests/test_config.rs @@ -8,7 +8,7 @@ use dropshot::{ ConfigDropshot, ConfigTls, HandlerTaskMode, HttpError, HttpResponseOk, RequestContext, }; -use dropshot::{HttpServer, HttpServerStarter}; +use dropshot::{HttpServer, ServerBuilder}; use slog::o; use slog::Logger; use std::str::FromStr; @@ -89,14 +89,15 @@ fn make_server( log: &Logger, tls: Option, api_description: Option>, -) -> HttpServerStarter { - HttpServerStarter::new_with_tls( - config, +) -> HttpServer { + ServerBuilder::new( api_description.unwrap_or_else(dropshot::ApiDescription::new), context, - log, - tls, + log.clone(), ) + .config(config.clone()) + .tls(tls) + .start() .unwrap() } @@ -221,7 +222,7 @@ async fn test_config_bind_address_http() { bind_port, HandlerTaskMode::CancelOnDisconnect, ); - make_server(0, &config, &self.log, None, None).start() + make_server(0, &config, &self.log, None, None) } } @@ -293,7 +294,7 @@ async fn test_config_bind_address_https() { bind_port, HandlerTaskMode::CancelOnDisconnect, ); - make_server(0, &config, &self.log, tls, None).start() + make_server(0, &config, &self.log, tls, None) } } @@ -374,7 +375,7 @@ async fn test_config_bind_address_https_buffer() { bind_port, HandlerTaskMode::CancelOnDisconnect, ); - make_server(0, &config, &self.log, tls, None).start() + make_server(0, &config, &self.log, tls, None) } } @@ -503,8 +504,7 @@ impl TestConfigBindServer let mut api = dropshot::ApiDescription::new(); api.register(track_cancel_endpoint).unwrap(); - let server = - make_server(context, &config, &self.log, None, Some(api)).start(); + let server = make_server(context, &config, &self.log, None, Some(api)); self.bound_port.store(server.local_addr().port(), Ordering::SeqCst); diff --git a/dropshot_endpoint/src/api_trait.rs b/dropshot_endpoint/src/api_trait.rs index 789aa4a3..2a87e4b7 100644 --- a/dropshot_endpoint/src/api_trait.rs +++ b/dropshot_endpoint/src/api_trait.rs @@ -955,17 +955,13 @@ async fn main() {{ let context = /* some value of type `{trait_ident}Impl::{context_ident}` */; // Create a Dropshot server from the description. - let config = dropshot::ConfigDropshot::default(); let log = /* ... */; - let server = dropshot::HttpServerStarter::new( - &config, - description, - context, - &log, - ).unwrap(); + let server = dropshot::ServerBuilder::new(description, context, log) + .start() + .unwrap(); // Run the server. - server.start().await + server.await }} ``` diff --git a/dropshot_endpoint/tests/output/api_trait_basic.rs b/dropshot_endpoint/tests/output/api_trait_basic.rs index 99eada81..3229ce06 100644 --- a/dropshot_endpoint/tests/output/api_trait_basic.rs +++ b/dropshot_endpoint/tests/output/api_trait_basic.rs @@ -128,17 +128,13 @@ mod my_trait_mod { /// let context = /* some value of type `MyTraitImpl::Context` */; /// /// // Create a Dropshot server from the description. - /// let config = dropshot::ConfigDropshot::default(); /// let log = /* ... */; - /// let server = dropshot::HttpServerStarter::new( - /// &config, - /// description, - /// context, - /// &log, - /// ).unwrap(); + /// let server = dropshot::ServerBuilder::new(description, context, log) + /// .start() + /// .unwrap(); /// /// // Run the server. - /// server.start().await + /// server.await /// } /// ``` /// diff --git a/dropshot_endpoint/tests/output/api_trait_no_endpoints.rs b/dropshot_endpoint/tests/output/api_trait_no_endpoints.rs index 61fd2103..31a007f2 100644 --- a/dropshot_endpoint/tests/output/api_trait_no_endpoints.rs +++ b/dropshot_endpoint/tests/output/api_trait_no_endpoints.rs @@ -78,17 +78,13 @@ pub(crate) mod my_trait_mod { /// let context = /* some value of type `MyTraitImpl::Context` */; /// /// // Create a Dropshot server from the description. - /// let config = dropshot::ConfigDropshot::default(); /// let log = /* ... */; - /// let server = dropshot::HttpServerStarter::new( - /// &config, - /// description, - /// context, - /// &log, - /// ).unwrap(); + /// let server = dropshot::ServerBuilder::new(description, context, log) + /// .start() + /// .unwrap(); /// /// // Run the server. - /// server.start().await + /// server.await /// } /// ``` /// diff --git a/dropshot_endpoint/tests/output/api_trait_with_custom_params.rs b/dropshot_endpoint/tests/output/api_trait_with_custom_params.rs index 1997af94..7781d64d 100644 --- a/dropshot_endpoint/tests/output/api_trait_with_custom_params.rs +++ b/dropshot_endpoint/tests/output/api_trait_with_custom_params.rs @@ -147,17 +147,13 @@ pub mod my_support_module { /// let context = /* some value of type `MyTraitImpl::Situation` */; /// /// // Create a Dropshot server from the description. - /// let config = dropshot::ConfigDropshot::default(); /// let log = /* ... */; - /// let server = dropshot::HttpServerStarter::new( - /// &config, - /// description, - /// context, - /// &log, - /// ).unwrap(); + /// let server = dropshot::ServerBuilder::new(description, context, log) + /// .start() + /// .unwrap(); /// /// // Run the server. - /// server.start().await + /// server.await /// } /// ``` /// From 986dc9addee3ca1b45a4658d64eceed36743676c Mon Sep 17 00:00:00 2001 From: David Pacheco Date: Mon, 30 Sep 2024 15:04:40 -0700 Subject: [PATCH 08/20] add a test for the old interface --- Cargo.lock | 463 ++++++++++++++++++++++++++------- dropshot/Cargo.toml | 1 + dropshot/tests/test_starter.rs | 99 +++++++ 3 files changed, 471 insertions(+), 92 deletions(-) create mode 100644 dropshot/tests/test_starter.rs diff --git a/Cargo.lock b/Cargo.lock index ba5cef1a..07fdfdae 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -69,7 +69,7 @@ checksum = "16e62a023e7c117e27523144c5d2459f4397fcc3cab0085af8e2224f643a0193" dependencies = [ "proc-macro2", "quote", - "syn 2.0.79", + "syn", ] [[package]] @@ -80,7 +80,7 @@ checksum = "721cae7de5c34fbb2acd27e21e6d2cf7b886dce0c27388d46c4e6c47ea4318dd" dependencies = [ "proc-macro2", "quote", - "syn 2.0.79", + "syn", ] [[package]] @@ -198,7 +198,7 @@ dependencies = [ "iana-time-zone", "num-traits", "serde", - "windows-targets 0.52.0", + "windows-targets 0.52.6", ] [[package]] @@ -365,7 +365,7 @@ dependencies = [ "http", "http-body-util", "hyper", - "hyper-rustls", + "hyper-rustls 0.26.0", "hyper-staticfile", "hyper-util", "indexmap", @@ -378,7 +378,8 @@ dependencies = [ "pem", "percent-encoding", "rcgen", - "rustls", + "reqwest", + "rustls 0.22.4", "rustls-pemfile", "rustls-pki-types", "schemars", @@ -398,7 +399,7 @@ dependencies = [ "tempfile", "thiserror", "tokio", - "tokio-rustls", + "tokio-rustls 0.25.0", "tokio-tungstenite", "toml", "trybuild", @@ -420,7 +421,7 @@ dependencies = [ "schema", "serde", "serde_tokenstream", - "syn 2.0.79", + "syn", ] [[package]] @@ -515,6 +516,21 @@ version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" +[[package]] +name = "foreign-types" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1" +dependencies = [ + "foreign-types-shared", +] + +[[package]] +name = "foreign-types-shared" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" + [[package]] name = "form_urlencoded" version = "1.2.1" @@ -580,7 +596,7 @@ checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac" dependencies = [ "proc-macro2", "quote", - "syn 2.0.79", + "syn", ] [[package]] @@ -809,11 +825,28 @@ dependencies = [ "hyper", "hyper-util", "log", - "rustls", + "rustls 0.22.4", "rustls-native-certs", "rustls-pki-types", "tokio", - "tokio-rustls", + "tokio-rustls 0.25.0", + "tower-service", +] + +[[package]] +name = "hyper-rustls" +version = "0.27.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08afdbb5c31130e3034af566421053ab03787c640246a446327f550d11bcb333" +dependencies = [ + "futures-util", + "http", + "hyper", + "hyper-util", + "rustls 0.23.13", + "rustls-pki-types", + "tokio", + "tokio-rustls 0.26.0", "tower-service", ] @@ -836,6 +869,22 @@ dependencies = [ "winapi", ] +[[package]] +name = "hyper-tls" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "70206fc6890eaca9fde8a0bf71caa2ddfc9fe045ac9e5c70df101a7dbde866e0" +dependencies = [ + "bytes", + "http-body-util", + "hyper", + "hyper-util", + "native-tls", + "tokio", + "tokio-native-tls", + "tower-service", +] + [[package]] name = "hyper-util" version = "0.1.9" @@ -871,11 +920,10 @@ dependencies = [ [[package]] name = "idna" -version = "0.2.3" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "418a0a6fab821475f634efe3ccc45c013f742efe03d853e8d3355d5cb850ecf8" +checksum = "634d9b1461af396cad843f47fdba5597a4f9e6ddd4bfb6ff5d85028c25cb12f6" dependencies = [ - "matches", "unicode-bidi", "unicode-normalization", ] @@ -891,6 +939,12 @@ dependencies = [ "serde", ] +[[package]] +name = "ipnet" +version = "2.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "187674a687eed5fe42285b40c6291f9a01517d415fad1c3cbc6a9f778af7fcd4" + [[package]] name = "is-terminal" version = "0.4.12" @@ -959,12 +1013,6 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ffbee8634e0d45d258acb448e7eaab3fce7a0a467395d4d9f228e3c1f01fb2e4" -[[package]] -name = "matches" -version = "0.1.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a3e378b66a060d48947b590737b30a1be76706c8dd7b8ba0f2fe3989c68a853f" - [[package]] name = "memchr" version = "2.6.0" @@ -1034,6 +1082,23 @@ dependencies = [ "version_check", ] +[[package]] +name = "native-tls" +version = "0.2.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a8614eb2c83d59d1c8cc974dd3f920198647674a0a035e1af1fa58707e317466" +dependencies = [ + "libc", + "log", + "openssl", + "openssl-probe", + "openssl-sys", + "schannel", + "security-framework", + "security-framework-sys", + "tempfile", +] + [[package]] name = "newline-converter" version = "0.3.0" @@ -1088,9 +1153,12 @@ dependencies = [ [[package]] name = "once_cell" -version = "1.13.1" +version = "1.20.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "074864da206b4973b84eb91683020dbefd6a8c3f0f38e054d93954e891935e4e" +checksum = "82881c4be219ab5faaf2ad5e5e5ecdff8c66bd7402ca3160975c93b24961afd1" +dependencies = [ + "portable-atomic", +] [[package]] name = "openapiv3" @@ -1103,12 +1171,50 @@ dependencies = [ "serde_json", ] +[[package]] +name = "openssl" +version = "0.10.66" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9529f4786b70a3e8c61e11179af17ab6188ad8d0ded78c5529441ed39d4bd9c1" +dependencies = [ + "bitflags 2.4.0", + "cfg-if", + "foreign-types", + "libc", + "once_cell", + "openssl-macros", + "openssl-sys", +] + +[[package]] +name = "openssl-macros" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "openssl-probe" version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "28988d872ab76095a6e6ac88d99b54fd267702734fd7ffe610ca27f533ddb95a" +[[package]] +name = "openssl-sys" +version = "0.9.103" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f9e8deee91df40a943c71b917e5874b951d32a802526c85721ce3b776c929d6" +dependencies = [ + "cc", + "libc", + "pkg-config", + "vcpkg", +] + [[package]] name = "parking" version = "2.2.0" @@ -1191,7 +1297,7 @@ dependencies = [ "pest_meta", "proc-macro2", "quote", - "syn 2.0.79", + "syn", ] [[package]] @@ -1217,12 +1323,24 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" +[[package]] +name = "pkg-config" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "953ec861398dccce10c670dfeaf3ec4911ca479e9c02154b3a215178c5f566f2" + [[package]] name = "plain" version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b4596b6d070b27117e987119b4dac604f3c58cfb0b191112e24771b2faeac1a6" +[[package]] +name = "portable-atomic" +version = "1.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cc9c68a3f6da06753e9335d63e27f6b9754dd1920d941135b7ea8224f141adb2" + [[package]] name = "powerfmt" version = "0.2.0" @@ -1248,7 +1366,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "479cf940fbbb3426c32c5d5176f62ad57549a0bb84773423ba8be9d089f5faba" dependencies = [ "proc-macro2", - "syn 2.0.79", + "syn", ] [[package]] @@ -1341,6 +1459,49 @@ dependencies = [ "redox_syscall", ] +[[package]] +name = "reqwest" +version = "0.12.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f713147fbe92361e52392c73b8c9e48c04c6625bce969ef54dc901e58e042a7b" +dependencies = [ + "base64", + "bytes", + "encoding_rs", + "futures-core", + "futures-util", + "h2", + "http", + "http-body", + "http-body-util", + "hyper", + "hyper-rustls 0.27.3", + "hyper-tls", + "hyper-util", + "ipnet", + "js-sys", + "log", + "mime", + "native-tls", + "once_cell", + "percent-encoding", + "pin-project-lite", + "rustls-pemfile", + "serde", + "serde_json", + "serde_urlencoded", + "sync_wrapper", + "system-configuration", + "tokio", + "tokio-native-tls", + "tower-service", + "url", + "wasm-bindgen", + "wasm-bindgen-futures", + "web-sys", + "windows-registry", +] + [[package]] name = "ring" version = "0.17.7" @@ -1388,6 +1549,19 @@ dependencies = [ "zeroize", ] +[[package]] +name = "rustls" +version = "0.23.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f2dabaac7466917e566adb06783a81ca48944c6898a1b08b9374106dd671f4c8" +dependencies = [ + "once_cell", + "rustls-pki-types", + "rustls-webpki", + "subtle", + "zeroize", +] + [[package]] name = "rustls-native-certs" version = "0.7.0" @@ -1419,9 +1593,9 @@ checksum = "fc0a2ce646f8655401bb81e7927b812614bd5d91dbc968696be50603510fcaf0" [[package]] name = "rustls-webpki" -version = "0.102.1" +version = "0.102.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ef4ca26037c909dedb327b48c3327d0ba91d3dd3c4e05dad328f210ffb68e95b" +checksum = "64ca1bc8749bd4cf37b5ce386cc146580777b4e8572c7b97baf22c83f444bee9" dependencies = [ "ring", "rustls-pki-types", @@ -1459,7 +1633,7 @@ dependencies = [ "proc-macro2", "quote", "schema-derive", - "syn 2.0.79", + "syn", ] [[package]] @@ -1471,7 +1645,7 @@ dependencies = [ "paste", "proc-macro2", "quote", - "syn 2.0.79", + "syn", ] [[package]] @@ -1497,7 +1671,7 @@ dependencies = [ "proc-macro2", "quote", "serde_derive_internals", - "syn 2.0.79", + "syn", ] [[package]] @@ -1523,7 +1697,7 @@ checksum = "7f81c2fde025af7e69b1d1420531c8a8811ca898919db177141a85313b1cb932" dependencies = [ "proc-macro2", "quote", - "syn 2.0.79", + "syn", ] [[package]] @@ -1566,7 +1740,7 @@ checksum = "243902eda00fad750862fc144cea25caca5e20d615af0a81bee94ca738f1df1f" dependencies = [ "proc-macro2", "quote", - "syn 2.0.79", + "syn", ] [[package]] @@ -1577,7 +1751,7 @@ checksum = "330f01ce65a3a5fe59a60c82f3c9a024b573b8a6e875bd233fe5f934e71d54e3" dependencies = [ "proc-macro2", "quote", - "syn 2.0.79", + "syn", ] [[package]] @@ -1620,7 +1794,7 @@ dependencies = [ "proc-macro2", "quote", "serde", - "syn 2.0.79", + "syn", ] [[package]] @@ -1779,9 +1953,9 @@ checksum = "81cdd64d312baedb58e21336b31bc043b77e01cc99033ce76ef539f78e965ebc" [[package]] name = "syn" -version = "1.0.109" +version = "2.0.79" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" +checksum = "89132cd0bf050864e1d38dc3bbc07a0eb8e7530af26344d3d2bbbef83499f590" dependencies = [ "proc-macro2", "quote", @@ -1789,14 +1963,33 @@ dependencies = [ ] [[package]] -name = "syn" -version = "2.0.79" +name = "sync_wrapper" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89132cd0bf050864e1d38dc3bbc07a0eb8e7530af26344d3d2bbbef83499f590" +checksum = "a7065abeca94b6a8a577f9bd45aa0867a2238b74e8eb67cf10d492bc39351394" dependencies = [ - "proc-macro2", - "quote", - "unicode-ident", + "futures-core", +] + +[[package]] +name = "system-configuration" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c879d448e9d986b661742763247d3693ed13609438cf3d006f51f5368a5ba6b" +dependencies = [ + "bitflags 2.4.0", + "core-foundation", + "system-configuration-sys", +] + +[[package]] +name = "system-configuration-sys" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e1d1b10ced5ca923a1fcb8d03e96b8d3268065d724548c0211415ff6ac6bac4" +dependencies = [ + "core-foundation-sys", + "libc", ] [[package]] @@ -1854,7 +2047,7 @@ checksum = "08904e7672f5eb876eaaf87e0ce17857500934f4981c4a0ab2b4aa98baac7fc3" dependencies = [ "proc-macro2", "quote", - "syn 2.0.79", + "syn", ] [[package]] @@ -1952,7 +2145,17 @@ checksum = "5f5ae998a069d4b5aba8ee9dad856af7d520c3699e6159b185c2acd48155d39a" dependencies = [ "proc-macro2", "quote", - "syn 2.0.79", + "syn", +] + +[[package]] +name = "tokio-native-tls" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbae76ab933c85776efabc971569dd6119c580d8f5d448769dec1764bf796ef2" +dependencies = [ + "native-tls", + "tokio", ] [[package]] @@ -1961,7 +2164,18 @@ version = "0.25.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "775e0c0f0adb3a2f22a00c4745d728b479985fc15ee7ca6a2608388c5569860f" dependencies = [ - "rustls", + "rustls 0.22.4", + "rustls-pki-types", + "tokio", +] + +[[package]] +name = "tokio-rustls" +version = "0.26.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c7bc40d0e5a97695bb96e27995cd3a08538541b0a846f65bba7a359f36700d4" +dependencies = [ + "rustls 0.23.13", "rustls-pki-types", "tokio", ] @@ -2112,9 +2326,9 @@ dependencies = [ [[package]] name = "unicode-bidi" -version = "0.3.7" +version = "0.3.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a01404663e3db436ed2746d9fefef640d868edae3cceb81c3b8d5732fda678f" +checksum = "08f95100a766bf4f8f28f90d77e0a5461bbdb219042e7679bebe79004fed8d75" [[package]] name = "unicode-ident" @@ -2124,9 +2338,9 @@ checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" [[package]] name = "unicode-normalization" -version = "0.1.19" +version = "0.1.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d54590932941a9e9266f0832deed84ebe1bf2e4c9e4a3554d393d18f5e854bf9" +checksum = "5033c97c4262335cded6d6fc3e5c18ab755e1a3dc96376350f3d8e9f009ad956" dependencies = [ "tinyvec", ] @@ -2151,13 +2365,12 @@ checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" [[package]] name = "url" -version = "2.2.2" +version = "2.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a507c383b2d33b5fc35d1861e77e6b383d158b2da5e14fe51b83dfedf6fd578c" +checksum = "22784dbdf76fdde8af1aeda5622b546b422b6fc585325248a2bf9f5e41e94d6c" dependencies = [ "form_urlencoded", "idna", - "matches", "percent-encoding", ] @@ -2187,7 +2400,7 @@ dependencies = [ "proc-macro2", "quote", "serde_tokenstream", - "syn 2.0.79", + "syn", "usdt-impl", ] @@ -2205,7 +2418,7 @@ dependencies = [ "quote", "serde", "serde_json", - "syn 2.0.79", + "syn", "thiserror", "thread-id", "version_check", @@ -2221,7 +2434,7 @@ dependencies = [ "proc-macro2", "quote", "serde_tokenstream", - "syn 2.0.79", + "syn", "usdt-impl", ] @@ -2241,6 +2454,12 @@ dependencies = [ "serde", ] +[[package]] +name = "vcpkg" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" + [[package]] name = "version_check" version = "0.9.5" @@ -2274,34 +2493,47 @@ checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" [[package]] name = "wasm-bindgen" -version = "0.2.82" +version = "0.2.93" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fc7652e3f6c4706c8d9cd54832c4a4ccb9b5336e2c3bd154d5cccfbf1c1f5f7d" +checksum = "a82edfc16a6c469f5f44dc7b571814045d60404b55a0ee849f9bcfa2e63dd9b5" dependencies = [ "cfg-if", + "once_cell", "wasm-bindgen-macro", ] [[package]] name = "wasm-bindgen-backend" -version = "0.2.82" +version = "0.2.93" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "662cd44805586bd52971b9586b1df85cdbbd9112e4ef4d8f41559c334dc6ac3f" +checksum = "9de396da306523044d3302746f1208fa71d7532227f15e347e2d93e4145dd77b" dependencies = [ "bumpalo", "log", "once_cell", "proc-macro2", "quote", - "syn 1.0.109", + "syn", "wasm-bindgen-shared", ] +[[package]] +name = "wasm-bindgen-futures" +version = "0.4.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fa76fb221a1f8acddf5b54ace85912606980ad661ac7a503b4570ffd3a624dad" +dependencies = [ + "cfg-if", + "js-sys", + "wasm-bindgen", + "web-sys", +] + [[package]] name = "wasm-bindgen-macro" -version = "0.2.82" +version = "0.2.93" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b260f13d3012071dfb1512849c033b1925038373aea48ced3012c09df952c602" +checksum = "585c4c91a46b072c92e908d99cb1dcdf95c5218eeb6f3bf1efa991ee7a68cccf" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -2309,22 +2541,32 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.82" +version = "0.2.93" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5be8e654bdd9b79216c2929ab90721aa82faf65c48cdf08bdc4e7f51357b80da" +checksum = "afc340c74d9005395cf9dd098506f7f44e38f2b4a21c6aaacf9a105ea5e1e836" dependencies = [ "proc-macro2", "quote", - "syn 1.0.109", + "syn", "wasm-bindgen-backend", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-shared" -version = "0.2.82" +version = "0.2.93" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c62a0a307cb4a311d3a07867860911ca130c3494e8c2719593806c08bc5d0484" + +[[package]] +name = "web-sys" +version = "0.3.59" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6598dd0bd3c7d51095ff6531a5b23e02acdc81804e30d8f07afb77b7215a140a" +checksum = "ed055ab27f941423197eb86b2035720b1a3ce40504df082cac2ecc6ed73335a1" +dependencies = [ + "js-sys", + "wasm-bindgen", +] [[package]] name = "winapi" @@ -2364,7 +2606,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e48a53791691ab099e5e2ad123536d0fff50652600abaf43bbf952894110d0be" dependencies = [ "windows-core", - "windows-targets 0.52.0", + "windows-targets 0.52.6", ] [[package]] @@ -2373,7 +2615,37 @@ version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9" dependencies = [ - "windows-targets 0.52.0", + "windows-targets 0.52.6", +] + +[[package]] +name = "windows-registry" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e400001bb720a623c1c69032f8e3e4cf09984deec740f007dd2b03ec864804b0" +dependencies = [ + "windows-result", + "windows-strings", + "windows-targets 0.52.6", +] + +[[package]] +name = "windows-result" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d1043d8214f791817bab27572aaa8af63732e11bf84aa21a45a78d6c317ae0e" +dependencies = [ + "windows-targets 0.52.6", +] + +[[package]] +name = "windows-strings" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4cd9b125c486025df0eabcb585e62173c6c9eddcec5d117d3b6e8c30e2ee4d10" +dependencies = [ + "windows-result", + "windows-targets 0.52.6", ] [[package]] @@ -2415,7 +2687,7 @@ version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" dependencies = [ - "windows-targets 0.52.0", + "windows-targets 0.52.6", ] [[package]] @@ -2450,17 +2722,18 @@ dependencies = [ [[package]] name = "windows-targets" -version = "0.52.0" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a18201040b24831fbb9e4eb208f8892e1f50a37feb53cc7ff887feb8f50e7cd" +checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" dependencies = [ - "windows_aarch64_gnullvm 0.52.0", - "windows_aarch64_msvc 0.52.0", - "windows_i686_gnu 0.52.0", - "windows_i686_msvc 0.52.0", - "windows_x86_64_gnu 0.52.0", - "windows_x86_64_gnullvm 0.52.0", - "windows_x86_64_msvc 0.52.0", + "windows_aarch64_gnullvm 0.52.6", + "windows_aarch64_msvc 0.52.6", + "windows_i686_gnu 0.52.6", + "windows_i686_gnullvm", + "windows_i686_msvc 0.52.6", + "windows_x86_64_gnu 0.52.6", + "windows_x86_64_gnullvm 0.52.6", + "windows_x86_64_msvc 0.52.6", ] [[package]] @@ -2477,9 +2750,9 @@ checksum = "91ae572e1b79dba883e0d315474df7305d12f569b400fcf90581b06062f7e1bc" [[package]] name = "windows_aarch64_gnullvm" -version = "0.52.0" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cb7764e35d4db8a7921e09562a0304bf2f93e0a51bfccee0bd0bb0b666b015ea" +checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" [[package]] name = "windows_aarch64_msvc" @@ -2495,9 +2768,9 @@ checksum = "b2ef27e0d7bdfcfc7b868b317c1d32c641a6fe4629c171b8928c7b08d98d7cf3" [[package]] name = "windows_aarch64_msvc" -version = "0.52.0" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bbaa0368d4f1d2aaefc55b6fcfee13f41544ddf36801e793edbbfd7d7df075ef" +checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" [[package]] name = "windows_i686_gnu" @@ -2513,9 +2786,15 @@ checksum = "622a1962a7db830d6fd0a69683c80a18fda201879f0f447f065a3b7467daa241" [[package]] name = "windows_i686_gnu" -version = "0.52.0" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a28637cb1fa3560a16915793afb20081aba2c92ee8af57b4d5f28e4b3e7df313" +checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" + +[[package]] +name = "windows_i686_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" [[package]] name = "windows_i686_msvc" @@ -2531,9 +2810,9 @@ checksum = "4542c6e364ce21bf45d69fdd2a8e455fa38d316158cfd43b3ac1c5b1b19f8e00" [[package]] name = "windows_i686_msvc" -version = "0.52.0" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ffe5e8e31046ce6230cc7215707b816e339ff4d4d67c65dffa206fd0f7aa7b9a" +checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" [[package]] name = "windows_x86_64_gnu" @@ -2549,9 +2828,9 @@ checksum = "ca2b8a661f7628cbd23440e50b05d705db3686f894fc9580820623656af974b1" [[package]] name = "windows_x86_64_gnu" -version = "0.52.0" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d6fa32db2bc4a2f5abeacf2b69f7992cd09dca97498da74a151a3132c26befd" +checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" [[package]] name = "windows_x86_64_gnullvm" @@ -2567,9 +2846,9 @@ checksum = "7896dbc1f41e08872e9d5e8f8baa8fdd2677f29468c4e156210174edc7f7b953" [[package]] name = "windows_x86_64_gnullvm" -version = "0.52.0" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a657e1e9d3f514745a572a6846d3c7aa7dbe1658c056ed9c3344c4109a6949e" +checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" [[package]] name = "windows_x86_64_msvc" @@ -2585,9 +2864,9 @@ checksum = "1a515f5799fe4961cb532f983ce2b23082366b898e52ffbce459c86f67c8378a" [[package]] name = "windows_x86_64_msvc" -version = "0.52.0" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dff9641d1cd4be8d1a070daf9e3773c5f67e78b4d9d42263020c057706765c04" +checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" [[package]] name = "winnow" @@ -2625,7 +2904,7 @@ checksum = "9ce1b18ccd8e73a9321186f97e46f9f04b778851177567b1975109d26a08d2a6" dependencies = [ "proc-macro2", "quote", - "syn 2.0.79", + "syn", ] [[package]] diff --git a/dropshot/Cargo.toml b/dropshot/Cargo.toml index f41d22a0..f9137682 100644 --- a/dropshot/Cargo.toml +++ b/dropshot/Cargo.toml @@ -105,6 +105,7 @@ trybuild = "1.0.99" # Used by the https examples and tests pem = "3.0" rcgen = "0.13.1" +reqwest = { version = "0.12.8", features = ["json"] } # Used in a doc-test demonstrating the WebsocketUpgrade extractor. tokio-tungstenite = "0.24.0" diff --git a/dropshot/tests/test_starter.rs b/dropshot/tests/test_starter.rs new file mode 100644 index 00000000..e4e875c8 --- /dev/null +++ b/dropshot/tests/test_starter.rs @@ -0,0 +1,99 @@ +// Copyright 2024 Oxide Computer Company + +//! Quick check that the "legacy" HttpServerStarter::new() and +//! HttpServerStarter::new_with_tls() interfaces work. + +pub mod common; + +use common::create_log_context; +use dropshot::endpoint; +use dropshot::test_util::read_json; +use dropshot::test_util::ClientTestContext; +use dropshot::ApiDescription; +use dropshot::ConfigDropshot; +use dropshot::ConfigTls; +use dropshot::HttpError; +use dropshot::HttpResponseOk; +use dropshot::HttpServerStarter; +use dropshot::RequestContext; + +extern crate slog; + +/// Test starting a server with `HttpServerStarter::new()`. +#[tokio::test] +async fn test_no_tls() { + let api = demo_api(); + let logctx = create_log_context("test_no_tls"); + let starter = + HttpServerStarter::new(&ConfigDropshot::default(), api, 0, &logctx.log) + .unwrap(); + let server = starter.start(); + let server_addr = server.local_addr(); + let client = ClientTestContext::new(server_addr, logctx.log.clone()); + let mut response = client + .make_request_no_body(http::Method::GET, "/demo", http::StatusCode::OK) + .await + .unwrap(); + let json: String = read_json(&mut response).await; + assert_eq!(json, "demo"); + + logctx.cleanup_successful(); +} + +/// Test starting a server with `HttpServerStarter::new_with_tls()`. +#[tokio::test] +async fn test_with_tls() { + let logctx = create_log_context("test_with_tls"); + + // Generate key for the server + let (certs, key) = common::generate_tls_key(); + let (serialized_certs, serialized_key) = + common::tls_key_to_buffer(&certs, &key); + let config_tls = Some(ConfigTls::AsBytes { + certs: serialized_certs.clone(), + key: serialized_key.clone(), + }); + + let client = reqwest::Client::builder() + .add_root_certificate( + reqwest::Certificate::from_der(&certs[0]).unwrap(), + ) + .build() + .unwrap(); + + let api = demo_api(); + let starter = HttpServerStarter::new_with_tls( + &ConfigDropshot::default(), + api, + 0, + &logctx.log, + config_tls, + ) + .unwrap(); + let server = starter.start(); + let server_addr = server.local_addr(); + // It would be nice to just write the whole sockaddr into the URL. But + // for TLS, we're required to use a server name and not an IP address here. + let url = format!("https://localhost:{}/demo", server_addr.port()); + let response = client.get(&url).send().await.unwrap(); + assert_eq!(response.status(), hyper::StatusCode::OK); + assert_eq!(response.json::().await.unwrap(), "demo"); + + logctx.cleanup_successful(); +} + +#[endpoint { + method = GET, + path = "/demo", +}] +async fn demo_handler( + _rqctx: RequestContext, +) -> Result, HttpError> { + Ok(HttpResponseOk(String::from("demo"))) +} + +fn demo_api() -> ApiDescription { + let mut api = ApiDescription::::new(); + api.register(demo_handler).unwrap(); + api +} From 8de0dcf40c2a83e139333a043411bd9a591e2102 Mon Sep 17 00:00:00 2001 From: David Pacheco Date: Mon, 30 Sep 2024 15:33:23 -0700 Subject: [PATCH 09/20] little help? --- .github/buildomat/jobs/build-and-test.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/buildomat/jobs/build-and-test.sh b/.github/buildomat/jobs/build-and-test.sh index e306bd66..b3d095a3 100644 --- a/.github/buildomat/jobs/build-and-test.sh +++ b/.github/buildomat/jobs/build-and-test.sh @@ -17,4 +17,4 @@ banner build ptime -m cargo build --all-features --locked --all-targets --verbose banner test -ptime -m cargo test --all-features --locked --verbose +RUST_BACKTRACE=1 ptime -m cargo test --all-features --locked --verbose From b22e9c1343faa44fbbfad532d318cdf9e0ae7692 Mon Sep 17 00:00:00 2001 From: David Pacheco Date: Mon, 30 Sep 2024 16:08:48 -0700 Subject: [PATCH 10/20] okay, but the right help --- .github/buildomat/jobs/build-and-test.sh | 2 +- .github/workflows/rust.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/buildomat/jobs/build-and-test.sh b/.github/buildomat/jobs/build-and-test.sh index b3d095a3..e306bd66 100644 --- a/.github/buildomat/jobs/build-and-test.sh +++ b/.github/buildomat/jobs/build-and-test.sh @@ -17,4 +17,4 @@ banner build ptime -m cargo build --all-features --locked --all-targets --verbose banner test -RUST_BACKTRACE=1 ptime -m cargo test --all-features --locked --verbose +ptime -m cargo test --all-features --locked --verbose diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml index 4fc852db..73fed7c5 100644 --- a/.github/workflows/rust.yml +++ b/.github/workflows/rust.yml @@ -59,4 +59,4 @@ jobs: - name: Build run: cargo build ${{ matrix.feature_flags }} --locked --all-targets --verbose - name: Run tests - run: cargo test ${{ matrix.feature_flags }} --locked --all-targets --verbose + run: RUST_BACKTRACE=1 cargo test ${{ matrix.feature_flags }} --locked --all-targets --verbose From 5aa71faaff8e7333f1cbd21a292dbc6eaaa741ba Mon Sep 17 00:00:00 2001 From: David Pacheco Date: Mon, 30 Sep 2024 16:19:14 -0700 Subject: [PATCH 11/20] fix changelog fmt --- CHANGELOG.adoc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.adoc b/CHANGELOG.adoc index 43f6ed64..1091346d 100644 --- a/CHANGELOG.adoc +++ b/CHANGELOG.adoc @@ -47,7 +47,7 @@ ServerBuilder::new(api, private, log).config(config).tls(tls).start().map_err(.. + If you were _not_ invoking `start()` immediately before, you can still construct an intermediate starter object with `build_starter()`. If you were doing this: + -```rust` +```rust let starter = HttpServerStarter::new(&config, api, private, &log).map_err(...)?; ... starter.start() From d9778c0a33bc3eeac9cd16c60360f0836d868a8a Mon Sep 17 00:00:00 2001 From: David Pacheco Date: Mon, 30 Sep 2024 16:19:47 -0700 Subject: [PATCH 12/20] attempt#3 to get some debugging info out of the windows job --- .github/workflows/rust.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml index 73fed7c5..937b7f49 100644 --- a/.github/workflows/rust.yml +++ b/.github/workflows/rust.yml @@ -11,6 +11,7 @@ on: env: CARGO_TERM_COLOR: always + RUST_BACKTRACE: 1 jobs: check-style: @@ -59,4 +60,4 @@ jobs: - name: Build run: cargo build ${{ matrix.feature_flags }} --locked --all-targets --verbose - name: Run tests - run: RUST_BACKTRACE=1 cargo test ${{ matrix.feature_flags }} --locked --all-targets --verbose + run: cargo test ${{ matrix.feature_flags }} --locked --all-targets --verbose From e763be5577d1475b7617d355be10b4584f8d1595 Mon Sep 17 00:00:00 2001 From: David Pacheco Date: Mon, 30 Sep 2024 19:24:59 -0700 Subject: [PATCH 13/20] maybe fix Windows job? --- dropshot/tests/test_starter.rs | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/dropshot/tests/test_starter.rs b/dropshot/tests/test_starter.rs index e4e875c8..f3599d1a 100644 --- a/dropshot/tests/test_starter.rs +++ b/dropshot/tests/test_starter.rs @@ -54,13 +54,13 @@ async fn test_with_tls() { key: serialized_key.clone(), }); - let client = reqwest::Client::builder() - .add_root_certificate( - reqwest::Certificate::from_der(&certs[0]).unwrap(), - ) - .build() - .unwrap(); - + let cert = reqwest::Certificate::from_pem_bundle(&serialized_certs) + .unwrap() + .into_iter() + .next() + .expect("one certificate in the bundle"); + let client = + reqwest::Client::builder().add_root_certificate(cert).build().unwrap(); let api = demo_api(); let starter = HttpServerStarter::new_with_tls( &ConfigDropshot::default(), From 9eba31a88fa476e0291f684ff18b3f10eb8ab643 Mon Sep 17 00:00:00 2001 From: David Pacheco Date: Mon, 30 Sep 2024 20:09:27 -0700 Subject: [PATCH 14/20] does older reqwest help? --- Cargo.lock | 266 +++++++++++++++++---------------- dropshot/Cargo.toml | 2 +- dropshot/tests/test_starter.rs | 2 +- 3 files changed, 140 insertions(+), 130 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 07fdfdae..a3d23720 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -110,6 +110,12 @@ dependencies = [ "rustc-demangle", ] +[[package]] +name = "base64" +version = "0.21.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d297deb1925b89f2ccc13d7635fa0714f12c87adce1c75356b39ca9b7178567" + [[package]] name = "base64" version = "0.22.1" @@ -351,7 +357,7 @@ dependencies = [ "async-channel", "async-stream", "async-trait", - "base64", + "base64 0.22.1", "buf-list", "bytes", "camino", @@ -362,10 +368,10 @@ dependencies = [ "form_urlencoded", "futures", "hostname 0.4.0", - "http", + "http 1.1.0", "http-body-util", - "hyper", - "hyper-rustls 0.26.0", + "hyper 1.4.1", + "hyper-rustls", "hyper-staticfile", "hyper-util", "indexmap", @@ -379,8 +385,8 @@ dependencies = [ "percent-encoding", "rcgen", "reqwest", - "rustls 0.22.4", - "rustls-pemfile", + "rustls", + "rustls-pemfile 2.1.3", "rustls-pki-types", "schemars", "scopeguard", @@ -399,7 +405,7 @@ dependencies = [ "tempfile", "thiserror", "tokio", - "tokio-rustls 0.25.0", + "tokio-rustls", "tokio-tungstenite", "toml", "trybuild", @@ -673,6 +679,25 @@ dependencies = [ "scroll", ] +[[package]] +name = "h2" +version = "0.3.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "81fe527a889e1532da5c525686d96d4c2e74cdd345badf8dfef9f6b39dd5f5e8" +dependencies = [ + "bytes", + "fnv", + "futures-core", + "futures-sink", + "futures-util", + "http 0.2.12", + "indexmap", + "slab", + "tokio", + "tokio-util", + "tracing", +] + [[package]] name = "h2" version = "0.4.6" @@ -684,7 +709,7 @@ dependencies = [ "fnv", "futures-core", "futures-sink", - "http", + "http 1.1.0", "indexmap", "slab", "tokio", @@ -741,6 +766,17 @@ dependencies = [ "windows", ] +[[package]] +name = "http" +version = "0.2.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "601cbb57e577e2f5ef5be8e7b83f0f63994f25aa94d673e54a92d5c516d101f1" +dependencies = [ + "bytes", + "fnv", + "itoa", +] + [[package]] name = "http" version = "1.1.0" @@ -752,6 +788,17 @@ dependencies = [ "itoa", ] +[[package]] +name = "http-body" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7ceab25649e9960c0311ea418d17bee82c0dcec1bd053b5f9a66e265a693bed2" +dependencies = [ + "bytes", + "http 0.2.12", + "pin-project-lite", +] + [[package]] name = "http-body" version = "1.0.1" @@ -759,7 +806,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1efedce1fb8e6913f23e0c92de8e62cd5b772a67e7b3946df930a62566c93184" dependencies = [ "bytes", - "http", + "http 1.1.0", ] [[package]] @@ -770,8 +817,8 @@ checksum = "793429d76616a256bcb62c2a2ec2bed781c8307e797e2598c50010f2bee2544f" dependencies = [ "bytes", "futures-util", - "http", - "http-body", + "http 1.1.0", + "http-body 1.0.1", "pin-project-lite", ] @@ -795,58 +842,65 @@ checksum = "6456b8a6c8f33fee7d958fcd1b60d55b11940a79e63ae87013e6d22e26034440" [[package]] name = "hyper" -version = "1.4.1" +version = "0.14.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "50dfd22e0e76d0f662d429a5f80fcaf3855009297eab6a0a9f8543834744ba05" +checksum = "a152ddd61dfaec7273fe8419ab357f33aee0d914c5f4efbf0d96fa749eea5ec9" dependencies = [ "bytes", "futures-channel", + "futures-core", "futures-util", - "h2", - "http", - "http-body", + "h2 0.3.26", + "http 0.2.12", + "http-body 0.4.6", "httparse", "httpdate", "itoa", "pin-project-lite", - "smallvec", + "socket2", "tokio", + "tower-service", + "tracing", "want", ] [[package]] -name = "hyper-rustls" -version = "0.26.0" +name = "hyper" +version = "1.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a0bea761b46ae2b24eb4aef630d8d1c398157b6fc29e6350ecf090a0b70c952c" +checksum = "50dfd22e0e76d0f662d429a5f80fcaf3855009297eab6a0a9f8543834744ba05" dependencies = [ + "bytes", + "futures-channel", "futures-util", - "http", - "hyper", - "hyper-util", - "log", - "rustls 0.22.4", - "rustls-native-certs", - "rustls-pki-types", + "h2 0.4.6", + "http 1.1.0", + "http-body 1.0.1", + "httparse", + "httpdate", + "itoa", + "pin-project-lite", + "smallvec", "tokio", - "tokio-rustls 0.25.0", - "tower-service", + "want", ] [[package]] name = "hyper-rustls" -version = "0.27.3" +version = "0.26.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08afdbb5c31130e3034af566421053ab03787c640246a446327f550d11bcb333" +checksum = "a0bea761b46ae2b24eb4aef630d8d1c398157b6fc29e6350ecf090a0b70c952c" dependencies = [ "futures-util", - "http", - "hyper", + "http 1.1.0", + "hyper 1.4.1", "hyper-util", - "rustls 0.23.13", + "log", + "rustls", + "rustls-native-certs", "rustls-pki-types", "tokio", - "tokio-rustls 0.26.0", + "tokio-rustls", "tower-service", ] @@ -857,10 +911,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bc4bce64c32578957926e75f832032f81ebb30bcee74f86c5848b13a69e547eb" dependencies = [ "futures-util", - "http", + "http 1.1.0", "http-range", "httpdate", - "hyper", + "hyper 1.4.1", "mime_guess", "percent-encoding", "rand", @@ -871,18 +925,15 @@ dependencies = [ [[package]] name = "hyper-tls" -version = "0.6.0" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70206fc6890eaca9fde8a0bf71caa2ddfc9fe045ac9e5c70df101a7dbde866e0" +checksum = "d6183ddfa99b85da61a140bea0efc93fdf56ceaa041b37d553518030827f9905" dependencies = [ "bytes", - "http-body-util", - "hyper", - "hyper-util", + "hyper 0.14.30", "native-tls", "tokio", "tokio-native-tls", - "tower-service", ] [[package]] @@ -894,9 +945,9 @@ dependencies = [ "bytes", "futures-channel", "futures-util", - "http", - "http-body", - "hyper", + "http 1.1.0", + "http-body 1.0.1", + "hyper 1.4.1", "pin-project-lite", "socket2", "tokio", @@ -1074,7 +1125,7 @@ dependencies = [ "bytes", "encoding_rs", "futures-util", - "http", + "http 1.1.0", "httparse", "memchr", "mime", @@ -1256,7 +1307,7 @@ version = "3.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8e459365e590736a54c3fa561947c84837534b8e9af6fc5bf781307e82658fae" dependencies = [ - "base64", + "base64 0.22.1", "serde", ] @@ -1461,23 +1512,20 @@ dependencies = [ [[package]] name = "reqwest" -version = "0.12.8" +version = "0.11.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f713147fbe92361e52392c73b8c9e48c04c6625bce969ef54dc901e58e042a7b" +checksum = "dd67538700a17451e7cba03ac727fb961abb7607553461627b97de0b89cf4a62" dependencies = [ - "base64", + "base64 0.21.7", "bytes", "encoding_rs", "futures-core", "futures-util", - "h2", - "http", - "http-body", - "http-body-util", - "hyper", - "hyper-rustls 0.27.3", + "h2 0.3.26", + "http 0.2.12", + "http-body 0.4.6", + "hyper 0.14.30", "hyper-tls", - "hyper-util", "ipnet", "js-sys", "log", @@ -1486,7 +1534,7 @@ dependencies = [ "once_cell", "percent-encoding", "pin-project-lite", - "rustls-pemfile", + "rustls-pemfile 1.0.4", "serde", "serde_json", "serde_urlencoded", @@ -1499,7 +1547,7 @@ dependencies = [ "wasm-bindgen", "wasm-bindgen-futures", "web-sys", - "windows-registry", + "winreg", ] [[package]] @@ -1549,19 +1597,6 @@ dependencies = [ "zeroize", ] -[[package]] -name = "rustls" -version = "0.23.13" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f2dabaac7466917e566adb06783a81ca48944c6898a1b08b9374106dd671f4c8" -dependencies = [ - "once_cell", - "rustls-pki-types", - "rustls-webpki", - "subtle", - "zeroize", -] - [[package]] name = "rustls-native-certs" version = "0.7.0" @@ -1569,19 +1604,28 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8f1fb85efa936c42c6d5fc28d2629bb51e4b2f4b8a5211e297d599cc5a093792" dependencies = [ "openssl-probe", - "rustls-pemfile", + "rustls-pemfile 2.1.3", "rustls-pki-types", "schannel", "security-framework", ] +[[package]] +name = "rustls-pemfile" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1c74cae0a4cf6ccbbf5f359f08efdf8ee7e1dc532573bf0db71968cb56b1448c" +dependencies = [ + "base64 0.21.7", +] + [[package]] name = "rustls-pemfile" version = "2.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "196fe16b00e106300d3e45ecfcb764fa292a535d7326a29a5875c579c7417425" dependencies = [ - "base64", + "base64 0.22.1", "rustls-pki-types", ] @@ -1964,29 +2008,26 @@ dependencies = [ [[package]] name = "sync_wrapper" -version = "1.0.1" +version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a7065abeca94b6a8a577f9bd45aa0867a2238b74e8eb67cf10d492bc39351394" -dependencies = [ - "futures-core", -] +checksum = "2047c6ded9c721764247e62cd3b03c09ffc529b2ba5b10ec482ae507a4a70160" [[package]] name = "system-configuration" -version = "0.6.1" +version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c879d448e9d986b661742763247d3693ed13609438cf3d006f51f5368a5ba6b" +checksum = "ba3a3adc5c275d719af8cb4272ea1c4a6d668a777f37e115f6d11ddbc1c8e0e7" dependencies = [ - "bitflags 2.4.0", + "bitflags 1.3.2", "core-foundation", "system-configuration-sys", ] [[package]] name = "system-configuration-sys" -version = "0.6.0" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e1d1b10ced5ca923a1fcb8d03e96b8d3268065d724548c0211415ff6ac6bac4" +checksum = "a75fb188eb626b924683e3b95e3a48e63551fcfb51949de2f06a9d91dbee93c9" dependencies = [ "core-foundation-sys", "libc", @@ -2164,18 +2205,7 @@ version = "0.25.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "775e0c0f0adb3a2f22a00c4745d728b479985fc15ee7ca6a2608388c5569860f" dependencies = [ - "rustls 0.22.4", - "rustls-pki-types", - "tokio", -] - -[[package]] -name = "tokio-rustls" -version = "0.26.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c7bc40d0e5a97695bb96e27995cd3a08538541b0a846f65bba7a359f36700d4" -dependencies = [ - "rustls 0.23.13", + "rustls", "rustls-pki-types", "tokio", ] @@ -2294,7 +2324,7 @@ dependencies = [ "byteorder", "bytes", "data-encoding", - "http", + "http 1.1.0", "httparse", "log", "rand", @@ -2618,36 +2648,6 @@ dependencies = [ "windows-targets 0.52.6", ] -[[package]] -name = "windows-registry" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e400001bb720a623c1c69032f8e3e4cf09984deec740f007dd2b03ec864804b0" -dependencies = [ - "windows-result", - "windows-strings", - "windows-targets 0.52.6", -] - -[[package]] -name = "windows-result" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d1043d8214f791817bab27572aaa8af63732e11bf84aa21a45a78d6c317ae0e" -dependencies = [ - "windows-targets 0.52.6", -] - -[[package]] -name = "windows-strings" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4cd9b125c486025df0eabcb585e62173c6c9eddcec5d117d3b6e8c30e2ee4d10" -dependencies = [ - "windows-result", - "windows-targets 0.52.6", -] - [[package]] name = "windows-sys" version = "0.42.0" @@ -2877,6 +2877,16 @@ dependencies = [ "memchr", ] +[[package]] +name = "winreg" +version = "0.50.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "524e57b2c537c0f9b1e69f1965311ec12182b4122e45035b1508cd24d2adadb1" +dependencies = [ + "cfg-if", + "windows-sys 0.48.0", +] + [[package]] name = "yasna" version = "0.5.2" diff --git a/dropshot/Cargo.toml b/dropshot/Cargo.toml index f9137682..947a7c37 100644 --- a/dropshot/Cargo.toml +++ b/dropshot/Cargo.toml @@ -105,7 +105,7 @@ trybuild = "1.0.99" # Used by the https examples and tests pem = "3.0" rcgen = "0.13.1" -reqwest = { version = "0.12.8", features = ["json"] } +reqwest = { version = "0.11.0", features = ["json"] } # Used in a doc-test demonstrating the WebsocketUpgrade extractor. tokio-tungstenite = "0.24.0" diff --git a/dropshot/tests/test_starter.rs b/dropshot/tests/test_starter.rs index f3599d1a..5c90d9c6 100644 --- a/dropshot/tests/test_starter.rs +++ b/dropshot/tests/test_starter.rs @@ -76,7 +76,7 @@ async fn test_with_tls() { // for TLS, we're required to use a server name and not an IP address here. let url = format!("https://localhost:{}/demo", server_addr.port()); let response = client.get(&url).send().await.unwrap(); - assert_eq!(response.status(), hyper::StatusCode::OK); + assert_eq!(response.status(), reqwest::StatusCode::OK); assert_eq!(response.json::().await.unwrap(), "demo"); logctx.cleanup_successful(); From 49ccd57443aa42beb3749423829fdaa3182d20c3 Mon Sep 17 00:00:00 2001 From: David Pacheco Date: Tue, 1 Oct 2024 11:27:04 -0700 Subject: [PATCH 15/20] update schannel? --- Cargo.lock | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index a3d23720..462924da 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1660,12 +1660,11 @@ checksum = "71d301d4193d031abdd79ff7e3dd721168a9572ef3fe51a1517aba235bd8f86e" [[package]] name = "schannel" -version = "0.1.19" +version = "0.1.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f05ba609c234e60bee0d547fe94a4c7e9da733d1c962cf6e59efa4cd9c8bc75" +checksum = "e9aaafd5a2b6e3d657ff009d82fbd630b6bd54dd4eb06f21693925cdf80f9b8b" dependencies = [ - "lazy_static", - "winapi", + "windows-sys 0.59.0", ] [[package]] @@ -2690,6 +2689,15 @@ dependencies = [ "windows-targets 0.52.6", ] +[[package]] +name = "windows-sys" +version = "0.59.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" +dependencies = [ + "windows-targets 0.52.6", +] + [[package]] name = "windows-targets" version = "0.42.2" From f390df0ced80c6a30fdbb30c2cee9e3c7426b9ab Mon Sep 17 00:00:00 2001 From: David Pacheco Date: Tue, 1 Oct 2024 11:31:16 -0700 Subject: [PATCH 16/20] may as well use newer reqwest --- Cargo.lock | 266 +++++++++++++++++++++----------------------- dropshot/Cargo.toml | 2 +- 2 files changed, 129 insertions(+), 139 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 462924da..5c83a11a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -110,12 +110,6 @@ dependencies = [ "rustc-demangle", ] -[[package]] -name = "base64" -version = "0.21.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9d297deb1925b89f2ccc13d7635fa0714f12c87adce1c75356b39ca9b7178567" - [[package]] name = "base64" version = "0.22.1" @@ -357,7 +351,7 @@ dependencies = [ "async-channel", "async-stream", "async-trait", - "base64 0.22.1", + "base64", "buf-list", "bytes", "camino", @@ -368,10 +362,10 @@ dependencies = [ "form_urlencoded", "futures", "hostname 0.4.0", - "http 1.1.0", + "http", "http-body-util", - "hyper 1.4.1", - "hyper-rustls", + "hyper", + "hyper-rustls 0.26.0", "hyper-staticfile", "hyper-util", "indexmap", @@ -385,8 +379,8 @@ dependencies = [ "percent-encoding", "rcgen", "reqwest", - "rustls", - "rustls-pemfile 2.1.3", + "rustls 0.22.4", + "rustls-pemfile", "rustls-pki-types", "schemars", "scopeguard", @@ -405,7 +399,7 @@ dependencies = [ "tempfile", "thiserror", "tokio", - "tokio-rustls", + "tokio-rustls 0.25.0", "tokio-tungstenite", "toml", "trybuild", @@ -679,25 +673,6 @@ dependencies = [ "scroll", ] -[[package]] -name = "h2" -version = "0.3.26" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "81fe527a889e1532da5c525686d96d4c2e74cdd345badf8dfef9f6b39dd5f5e8" -dependencies = [ - "bytes", - "fnv", - "futures-core", - "futures-sink", - "futures-util", - "http 0.2.12", - "indexmap", - "slab", - "tokio", - "tokio-util", - "tracing", -] - [[package]] name = "h2" version = "0.4.6" @@ -709,7 +684,7 @@ dependencies = [ "fnv", "futures-core", "futures-sink", - "http 1.1.0", + "http", "indexmap", "slab", "tokio", @@ -766,17 +741,6 @@ dependencies = [ "windows", ] -[[package]] -name = "http" -version = "0.2.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "601cbb57e577e2f5ef5be8e7b83f0f63994f25aa94d673e54a92d5c516d101f1" -dependencies = [ - "bytes", - "fnv", - "itoa", -] - [[package]] name = "http" version = "1.1.0" @@ -788,17 +752,6 @@ dependencies = [ "itoa", ] -[[package]] -name = "http-body" -version = "0.4.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ceab25649e9960c0311ea418d17bee82c0dcec1bd053b5f9a66e265a693bed2" -dependencies = [ - "bytes", - "http 0.2.12", - "pin-project-lite", -] - [[package]] name = "http-body" version = "1.0.1" @@ -806,7 +759,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1efedce1fb8e6913f23e0c92de8e62cd5b772a67e7b3946df930a62566c93184" dependencies = [ "bytes", - "http 1.1.0", + "http", ] [[package]] @@ -817,8 +770,8 @@ checksum = "793429d76616a256bcb62c2a2ec2bed781c8307e797e2598c50010f2bee2544f" dependencies = [ "bytes", "futures-util", - "http 1.1.0", - "http-body 1.0.1", + "http", + "http-body", "pin-project-lite", ] @@ -840,30 +793,6 @@ version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6456b8a6c8f33fee7d958fcd1b60d55b11940a79e63ae87013e6d22e26034440" -[[package]] -name = "hyper" -version = "0.14.30" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a152ddd61dfaec7273fe8419ab357f33aee0d914c5f4efbf0d96fa749eea5ec9" -dependencies = [ - "bytes", - "futures-channel", - "futures-core", - "futures-util", - "h2 0.3.26", - "http 0.2.12", - "http-body 0.4.6", - "httparse", - "httpdate", - "itoa", - "pin-project-lite", - "socket2", - "tokio", - "tower-service", - "tracing", - "want", -] - [[package]] name = "hyper" version = "1.4.1" @@ -873,9 +802,9 @@ dependencies = [ "bytes", "futures-channel", "futures-util", - "h2 0.4.6", - "http 1.1.0", - "http-body 1.0.1", + "h2", + "http", + "http-body", "httparse", "httpdate", "itoa", @@ -892,15 +821,32 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a0bea761b46ae2b24eb4aef630d8d1c398157b6fc29e6350ecf090a0b70c952c" dependencies = [ "futures-util", - "http 1.1.0", - "hyper 1.4.1", + "http", + "hyper", "hyper-util", "log", - "rustls", + "rustls 0.22.4", "rustls-native-certs", "rustls-pki-types", "tokio", - "tokio-rustls", + "tokio-rustls 0.25.0", + "tower-service", +] + +[[package]] +name = "hyper-rustls" +version = "0.27.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08afdbb5c31130e3034af566421053ab03787c640246a446327f550d11bcb333" +dependencies = [ + "futures-util", + "http", + "hyper", + "hyper-util", + "rustls 0.23.13", + "rustls-pki-types", + "tokio", + "tokio-rustls 0.26.0", "tower-service", ] @@ -911,10 +857,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bc4bce64c32578957926e75f832032f81ebb30bcee74f86c5848b13a69e547eb" dependencies = [ "futures-util", - "http 1.1.0", + "http", "http-range", "httpdate", - "hyper 1.4.1", + "hyper", "mime_guess", "percent-encoding", "rand", @@ -925,15 +871,18 @@ dependencies = [ [[package]] name = "hyper-tls" -version = "0.5.0" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d6183ddfa99b85da61a140bea0efc93fdf56ceaa041b37d553518030827f9905" +checksum = "70206fc6890eaca9fde8a0bf71caa2ddfc9fe045ac9e5c70df101a7dbde866e0" dependencies = [ "bytes", - "hyper 0.14.30", + "http-body-util", + "hyper", + "hyper-util", "native-tls", "tokio", "tokio-native-tls", + "tower-service", ] [[package]] @@ -945,9 +894,9 @@ dependencies = [ "bytes", "futures-channel", "futures-util", - "http 1.1.0", - "http-body 1.0.1", - "hyper 1.4.1", + "http", + "http-body", + "hyper", "pin-project-lite", "socket2", "tokio", @@ -1125,7 +1074,7 @@ dependencies = [ "bytes", "encoding_rs", "futures-util", - "http 1.1.0", + "http", "httparse", "memchr", "mime", @@ -1307,7 +1256,7 @@ version = "3.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8e459365e590736a54c3fa561947c84837534b8e9af6fc5bf781307e82658fae" dependencies = [ - "base64 0.22.1", + "base64", "serde", ] @@ -1512,20 +1461,23 @@ dependencies = [ [[package]] name = "reqwest" -version = "0.11.27" +version = "0.12.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd67538700a17451e7cba03ac727fb961abb7607553461627b97de0b89cf4a62" +checksum = "f713147fbe92361e52392c73b8c9e48c04c6625bce969ef54dc901e58e042a7b" dependencies = [ - "base64 0.21.7", + "base64", "bytes", "encoding_rs", "futures-core", "futures-util", - "h2 0.3.26", - "http 0.2.12", - "http-body 0.4.6", - "hyper 0.14.30", + "h2", + "http", + "http-body", + "http-body-util", + "hyper", + "hyper-rustls 0.27.3", "hyper-tls", + "hyper-util", "ipnet", "js-sys", "log", @@ -1534,7 +1486,7 @@ dependencies = [ "once_cell", "percent-encoding", "pin-project-lite", - "rustls-pemfile 1.0.4", + "rustls-pemfile", "serde", "serde_json", "serde_urlencoded", @@ -1547,7 +1499,7 @@ dependencies = [ "wasm-bindgen", "wasm-bindgen-futures", "web-sys", - "winreg", + "windows-registry", ] [[package]] @@ -1597,6 +1549,19 @@ dependencies = [ "zeroize", ] +[[package]] +name = "rustls" +version = "0.23.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f2dabaac7466917e566adb06783a81ca48944c6898a1b08b9374106dd671f4c8" +dependencies = [ + "once_cell", + "rustls-pki-types", + "rustls-webpki", + "subtle", + "zeroize", +] + [[package]] name = "rustls-native-certs" version = "0.7.0" @@ -1604,28 +1569,19 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8f1fb85efa936c42c6d5fc28d2629bb51e4b2f4b8a5211e297d599cc5a093792" dependencies = [ "openssl-probe", - "rustls-pemfile 2.1.3", + "rustls-pemfile", "rustls-pki-types", "schannel", "security-framework", ] -[[package]] -name = "rustls-pemfile" -version = "1.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1c74cae0a4cf6ccbbf5f359f08efdf8ee7e1dc532573bf0db71968cb56b1448c" -dependencies = [ - "base64 0.21.7", -] - [[package]] name = "rustls-pemfile" version = "2.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "196fe16b00e106300d3e45ecfcb764fa292a535d7326a29a5875c579c7417425" dependencies = [ - "base64 0.22.1", + "base64", "rustls-pki-types", ] @@ -2007,26 +1963,29 @@ dependencies = [ [[package]] name = "sync_wrapper" -version = "0.1.2" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2047c6ded9c721764247e62cd3b03c09ffc529b2ba5b10ec482ae507a4a70160" +checksum = "a7065abeca94b6a8a577f9bd45aa0867a2238b74e8eb67cf10d492bc39351394" +dependencies = [ + "futures-core", +] [[package]] name = "system-configuration" -version = "0.5.1" +version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba3a3adc5c275d719af8cb4272ea1c4a6d668a777f37e115f6d11ddbc1c8e0e7" +checksum = "3c879d448e9d986b661742763247d3693ed13609438cf3d006f51f5368a5ba6b" dependencies = [ - "bitflags 1.3.2", + "bitflags 2.4.0", "core-foundation", "system-configuration-sys", ] [[package]] name = "system-configuration-sys" -version = "0.5.0" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a75fb188eb626b924683e3b95e3a48e63551fcfb51949de2f06a9d91dbee93c9" +checksum = "8e1d1b10ced5ca923a1fcb8d03e96b8d3268065d724548c0211415ff6ac6bac4" dependencies = [ "core-foundation-sys", "libc", @@ -2204,7 +2163,18 @@ version = "0.25.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "775e0c0f0adb3a2f22a00c4745d728b479985fc15ee7ca6a2608388c5569860f" dependencies = [ - "rustls", + "rustls 0.22.4", + "rustls-pki-types", + "tokio", +] + +[[package]] +name = "tokio-rustls" +version = "0.26.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c7bc40d0e5a97695bb96e27995cd3a08538541b0a846f65bba7a359f36700d4" +dependencies = [ + "rustls 0.23.13", "rustls-pki-types", "tokio", ] @@ -2323,7 +2293,7 @@ dependencies = [ "byteorder", "bytes", "data-encoding", - "http 1.1.0", + "http", "httparse", "log", "rand", @@ -2647,6 +2617,36 @@ dependencies = [ "windows-targets 0.52.6", ] +[[package]] +name = "windows-registry" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e400001bb720a623c1c69032f8e3e4cf09984deec740f007dd2b03ec864804b0" +dependencies = [ + "windows-result", + "windows-strings", + "windows-targets 0.52.6", +] + +[[package]] +name = "windows-result" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d1043d8214f791817bab27572aaa8af63732e11bf84aa21a45a78d6c317ae0e" +dependencies = [ + "windows-targets 0.52.6", +] + +[[package]] +name = "windows-strings" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4cd9b125c486025df0eabcb585e62173c6c9eddcec5d117d3b6e8c30e2ee4d10" +dependencies = [ + "windows-result", + "windows-targets 0.52.6", +] + [[package]] name = "windows-sys" version = "0.42.0" @@ -2885,16 +2885,6 @@ dependencies = [ "memchr", ] -[[package]] -name = "winreg" -version = "0.50.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "524e57b2c537c0f9b1e69f1965311ec12182b4122e45035b1508cd24d2adadb1" -dependencies = [ - "cfg-if", - "windows-sys 0.48.0", -] - [[package]] name = "yasna" version = "0.5.2" diff --git a/dropshot/Cargo.toml b/dropshot/Cargo.toml index 947a7c37..f9137682 100644 --- a/dropshot/Cargo.toml +++ b/dropshot/Cargo.toml @@ -105,7 +105,7 @@ trybuild = "1.0.99" # Used by the https examples and tests pem = "3.0" rcgen = "0.13.1" -reqwest = { version = "0.11.0", features = ["json"] } +reqwest = { version = "0.12.8", features = ["json"] } # Used in a doc-test demonstrating the WebsocketUpgrade extractor. tokio-tungstenite = "0.24.0" From 8557e0578f09e2ac64aca3c534d594fa72d49c73 Mon Sep 17 00:00:00 2001 From: David Pacheco Date: Tue, 1 Oct 2024 11:45:18 -0700 Subject: [PATCH 17/20] add all the certs? --- dropshot/tests/test_starter.rs | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/dropshot/tests/test_starter.rs b/dropshot/tests/test_starter.rs index 5c90d9c6..7cc5fd86 100644 --- a/dropshot/tests/test_starter.rs +++ b/dropshot/tests/test_starter.rs @@ -54,13 +54,13 @@ async fn test_with_tls() { key: serialized_key.clone(), }); - let cert = reqwest::Certificate::from_pem_bundle(&serialized_certs) - .unwrap() - .into_iter() - .next() - .expect("one certificate in the bundle"); - let client = - reqwest::Client::builder().add_root_certificate(cert).build().unwrap(); + let mut builder = reqwest::Client::builder(); + let certs = + reqwest::Certificate::from_pem_bundle(&serialized_certs).unwrap(); + for c in certs { + builder = builder.add_root_certificate(c); + } + let client = builder.build().unwrap(); let api = demo_api(); let starter = HttpServerStarter::new_with_tls( &ConfigDropshot::default(), From b219b244ee7e09e033a0dad23e08d76f96be11a3 Mon Sep 17 00:00:00 2001 From: David Pacheco Date: Wed, 2 Oct 2024 08:47:54 -0700 Subject: [PATCH 18/20] try rustls-tls --- Cargo.lock | 70 +++++++++++++++++++++++++++++++++++++++++++++ dropshot/Cargo.toml | 4 ++- 2 files changed, 73 insertions(+), 1 deletion(-) diff --git a/Cargo.lock b/Cargo.lock index 5c83a11a..50fdf093 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -848,6 +848,7 @@ dependencies = [ "tokio", "tokio-rustls 0.26.0", "tower-service", + "webpki-roots", ] [[package]] @@ -1378,6 +1379,54 @@ dependencies = [ "unicode-ident", ] +[[package]] +name = "quinn" +version = "0.11.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a2d2fb862b7ba45e615c1429def928f2e15f815bdf933b27a2d3824e224c1f46" +dependencies = [ + "bytes", + "pin-project-lite", + "quinn-proto", + "quinn-udp", + "rustc-hash", + "rustls 0.23.13", + "socket2", + "thiserror", + "tokio", + "tracing", +] + +[[package]] +name = "quinn-proto" +version = "0.11.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba92fb39ec7ad06ca2582c0ca834dfeadcaf06ddfc8e635c80aa7e1c05315fdd" +dependencies = [ + "bytes", + "rand", + "ring", + "rustc-hash", + "rustls 0.23.13", + "slab", + "thiserror", + "tinyvec", + "tracing", +] + +[[package]] +name = "quinn-udp" +version = "0.5.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4fe68c2e9e1a1234e218683dbdf9f9dfcb094113c5ac2b938dfcb9bab4c4140b" +dependencies = [ + "libc", + "once_cell", + "socket2", + "tracing", + "windows-sys 0.59.0", +] + [[package]] name = "quote" version = "1.0.37" @@ -1486,7 +1535,10 @@ dependencies = [ "once_cell", "percent-encoding", "pin-project-lite", + "quinn", + "rustls 0.23.13", "rustls-pemfile", + "rustls-pki-types", "serde", "serde_json", "serde_urlencoded", @@ -1494,11 +1546,13 @@ dependencies = [ "system-configuration", "tokio", "tokio-native-tls", + "tokio-rustls 0.26.0", "tower-service", "url", "wasm-bindgen", "wasm-bindgen-futures", "web-sys", + "webpki-roots", "windows-registry", ] @@ -1522,6 +1576,12 @@ version = "0.1.23" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76" +[[package]] +name = "rustc-hash" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "583034fd73374156e66797ed8e5b0d5690409c9226b22d87cb7f19821c05d152" + [[package]] name = "rustix" version = "0.38.31" @@ -1556,6 +1616,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f2dabaac7466917e566adb06783a81ca48944c6898a1b08b9374106dd671f4c8" dependencies = [ "once_cell", + "ring", "rustls-pki-types", "rustls-webpki", "subtle", @@ -2567,6 +2628,15 @@ dependencies = [ "wasm-bindgen", ] +[[package]] +name = "webpki-roots" +version = "0.26.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0bd24728e5af82c6c4ec1b66ac4844bdf8156257fccda846ec58b42cd0cdbe6a" +dependencies = [ + "rustls-pki-types", +] + [[package]] name = "winapi" version = "0.3.9" diff --git a/dropshot/Cargo.toml b/dropshot/Cargo.toml index f9137682..238a5166 100644 --- a/dropshot/Cargo.toml +++ b/dropshot/Cargo.toml @@ -105,7 +105,9 @@ trybuild = "1.0.99" # Used by the https examples and tests pem = "3.0" rcgen = "0.13.1" -reqwest = { version = "0.12.8", features = ["json"] } +# Using rustls-tls because it appears the rcgen-generated certificates are not +# supported by the native Windows APIs. +reqwest = { version = "0.12.8", features = ["json", "rustls-tls"] } # Used in a doc-test demonstrating the WebsocketUpgrade extractor. tokio-tungstenite = "0.24.0" From cb597481362cfa6f3e26145fd85e6cc9e3c8e75e Mon Sep 17 00:00:00 2001 From: David Pacheco Date: Wed, 2 Oct 2024 09:09:02 -0700 Subject: [PATCH 19/20] tell reqwest to USE rustls --- dropshot/tests/test_starter.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dropshot/tests/test_starter.rs b/dropshot/tests/test_starter.rs index 7cc5fd86..a93329d3 100644 --- a/dropshot/tests/test_starter.rs +++ b/dropshot/tests/test_starter.rs @@ -54,7 +54,7 @@ async fn test_with_tls() { key: serialized_key.clone(), }); - let mut builder = reqwest::Client::builder(); + let mut builder = reqwest::Client::builder().use_rustls_tls(); let certs = reqwest::Certificate::from_pem_bundle(&serialized_certs).unwrap(); for c in certs { From 394410c0ec1a4524bbe68866622e19d991ccaec3 Mon Sep 17 00:00:00 2001 From: David Pacheco Date: Wed, 2 Oct 2024 11:03:02 -0700 Subject: [PATCH 20/20] better comment and clean up the new test --- dropshot/tests/test_starter.rs | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/dropshot/tests/test_starter.rs b/dropshot/tests/test_starter.rs index a93329d3..bb90ef52 100644 --- a/dropshot/tests/test_starter.rs +++ b/dropshot/tests/test_starter.rs @@ -54,13 +54,18 @@ async fn test_with_tls() { key: serialized_key.clone(), }); - let mut builder = reqwest::Client::builder().use_rustls_tls(); + // Use Rustls-based TLS because the native TLS on Windows does not support + // appear to support adding the rcgen-generated P-256 certificate in this + // way. let certs = reqwest::Certificate::from_pem_bundle(&serialized_certs).unwrap(); - for c in certs { - builder = builder.add_root_certificate(c); - } - let client = builder.build().unwrap(); + let my_ca_root = + certs.into_iter().last().expect("at least one certificate"); + let client = reqwest::Client::builder() + .use_rustls_tls() + .add_root_certificate(my_ca_root) + .build() + .unwrap(); let api = demo_api(); let starter = HttpServerStarter::new_with_tls( &ConfigDropshot::default(),