Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add builder interface for making servers #1122

Merged
merged 22 commits into from
Oct 2, 2024
Merged
Show file tree
Hide file tree
Changes from 7 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 31 additions & 0 deletions CHANGELOG.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -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, 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.
+
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]
Expand Down
9 changes: 5 additions & 4 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions dropshot/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down
14 changes: 4 additions & 10 deletions dropshot/examples/api-trait-alternate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down Expand Up @@ -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 =
Expand All @@ -218,14 +217,9 @@ async fn main() -> Result<(), String> {

let my_api =
api::counter_api_mod::api_description::<imp::CounterImpl>().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
}
14 changes: 4 additions & 10 deletions dropshot/examples/api-trait-websocket.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down Expand Up @@ -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 =
Expand All @@ -148,14 +147,9 @@ async fn main() -> Result<(), String> {

let my_server =
api::counter_api_mod::api_description::<imp::CounterImpl>().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
}
14 changes: 4 additions & 10 deletions dropshot/examples/api-trait.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down Expand Up @@ -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 =
Expand All @@ -151,14 +150,9 @@ async fn main() -> Result<(), String> {
// type parameter.
let my_api =
api::counter_api_mod::api_description::<imp::CounterImpl>().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
}
21 changes: 9 additions & 12 deletions dropshot/examples/basic.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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 =
Expand All @@ -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.
Expand Down
28 changes: 7 additions & 21 deletions dropshot/examples/https.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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(),
Expand All @@ -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.
Expand Down
4 changes: 2 additions & 2 deletions dropshot/src/handler.rs
Original file line number Diff line number Diff line change
Expand Up @@ -567,8 +567,8 @@ impl HttpResponse for Response<Body> {
}
}

/// 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<Body> for FreeformBody {
Expand Down
21 changes: 6 additions & 15 deletions dropshot/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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]
Expand All @@ -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
//! }
Expand Down Expand Up @@ -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};
Expand Down
Loading