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

Exposing ServerConfig options #959

Open
wants to merge 12 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all 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
4 changes: 4 additions & 0 deletions CHANGELOG.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,10 @@

https://github.com/oxidecomputer/dropshot/compare/v0.11.0\...HEAD[Full list of commits]

=== Breaking Changes

* https://github.com/oxidecomputer/dropshot/pull/959[#959] expands the settings available via `ConfigDropshot`. This adds two new fields `page_max_nitems` and `page_default_nitems` that will need to be added wherever a `ConfigDropshot` struct is manually constructed. The defaults are likely appropriate for most use cases.

== 0.11.0 (released 2024-08-21)

https://github.com/oxidecomputer/dropshot/compare/v0.10.1\...v0.11.0[Full list of commits]
Expand Down
7 changes: 7 additions & 0 deletions dropshot/src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
use serde::Deserialize;
use serde::Serialize;
use std::net::SocketAddr;
use std::num::NonZeroU32;
use std::path::PathBuf;

/// Raw [`rustls::ServerConfig`] TLS configuration for use with
Expand Down Expand Up @@ -49,6 +50,10 @@ pub struct ConfigDropshot {
pub bind_address: SocketAddr,
/// maximum allowed size of a request body, defaults to 1024
pub request_body_max_bytes: usize,
/// maximum size of any page of results
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

do we want to add #[non_exhaustive] to the struct? Would that force consumers to use ..Default::default() when constructing this? i.e. such that adding more fields would not be a breaking change?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wondered the same thing. Consumers can already do that if they want. It's kind of nice that the way it is now you can have your code break if we add some new config option so that you get a chance to look yourself at whether our default works for you. I think I've used this in the past.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We don't have to fix this here but I think I disagree with past-me here. If you want to do that, just check the changelog. We shouldn't need to bump a major to add new things.

A builder interface would be nice, too.

(I don't propose that we do anything in this PR.)

pub page_max_nitems: NonZeroU32,
/// default size for a page of results
pub page_default_nitems: NonZeroU32,
/// Default behavior for HTTP handler functions with respect to clients
/// disconnecting early.
pub default_handler_task_mode: HandlerTaskMode,
Expand Down Expand Up @@ -114,6 +119,8 @@ impl Default for ConfigDropshot {
ConfigDropshot {
bind_address: "127.0.0.1:0".parse().unwrap(),
request_body_max_bytes: 1024,
page_max_nitems: NonZeroU32::new(10000).unwrap(),
page_default_nitems: NonZeroU32::new(100).unwrap(),
default_handler_task_mode: HandlerTaskMode::Detached,
log_headers: Default::default(),
}
Expand Down
4 changes: 3 additions & 1 deletion dropshot/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@
//! use dropshot::ConfigLoggingLevel;
//! use dropshot::HandlerTaskMode;
//! use dropshot::HttpServerStarter;
//! use std::sync::Arc;
//! use std::{num::NonZeroU32, sync::Arc};
//!
//! #[tokio::main]
//! async fn main() -> Result<(), String> {
Expand All @@ -72,6 +72,8 @@
//! &ConfigDropshot {
//! bind_address: "127.0.0.1:0".parse().unwrap(),
//! request_body_max_bytes: 1024,
//! page_max_nitems: NonZeroU32::new(10000).unwrap(),
//! page_default_nitems: NonZeroU32::new(100).unwrap(),
//! default_handler_task_mode: HandlerTaskMode::Detached,
//! log_headers: Default::default(),
//! },
Expand Down
51 changes: 7 additions & 44 deletions dropshot/src/server.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,6 @@ use std::convert::TryFrom;
use std::future::Future;
use std::mem;
use std::net::SocketAddr;
use std::num::NonZeroU32;
use std::panic;
use std::pin::Pin;
use std::sync::Arc;
Expand Down Expand Up @@ -64,7 +63,7 @@ pub struct DropshotState<C: ServerContext> {
/// caller-specific state
pub private: C,
/// static server configuration parameters
pub config: ServerConfig,
pub config: ConfigDropshot,
/// request router
pub router: HttpRouter<C>,
/// server-wide log handle
Expand All @@ -84,29 +83,6 @@ impl<C: ServerContext> DropshotState<C> {
}
}

/// Stores static configuration associated with the server
/// TODO-cleanup merge with ConfigDropshot
#[derive(Debug)]
pub struct ServerConfig {
/// maximum allowed size of a request body
pub request_body_max_bytes: usize,
/// maximum size of any page of results
pub page_max_nitems: NonZeroU32,
/// default size for a page of results
pub page_default_nitems: NonZeroU32,
/// Default behavior for HTTP handler functions with respect to clients
/// disconnecting early.
pub default_handler_task_mode: HandlerTaskMode,
/// A list of header names to include as extra properties in the log
/// messages emitted by the per-request logger. Each header will, if
/// present, be included in the output with a "hdr_"-prefixed property name
/// in lower case that has all hyphens replaced with underscores; e.g.,
/// "X-Forwarded-For" will be included as "hdr_x_forwarded_for". No attempt
/// is made to deal with headers that appear multiple times in a single
/// request.
pub log_headers: Vec<String>,
}

pub struct HttpServerStarter<C: ServerContext> {
app_state: Arc<DropshotState<C>>,
local_addr: SocketAddr,
Expand All @@ -131,22 +107,12 @@ impl<C: ServerContext> HttpServerStarter<C> {
log: &Logger,
tls: Option<ConfigTls>,
) -> Result<HttpServerStarter<C>, GenericError> {
let server_config = ServerConfig {
// We start aggressively to ensure test coverage.
request_body_max_bytes: config.request_body_max_bytes,
page_max_nitems: NonZeroU32::new(10000).unwrap(),
page_default_nitems: NonZeroU32::new(100).unwrap(),
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,
config.clone(),
api,
private,
log,
Expand All @@ -163,8 +129,7 @@ impl<C: ServerContext> HttpServerStarter<C> {
None => {
let (starter, app_state, local_addr) =
InnerHttpServerStarter::new(
config,
server_config,
config.clone(),
api,
private,
log,
Expand Down Expand Up @@ -284,8 +249,7 @@ impl<C: ServerContext> InnerHttpServerStarter<C> {
/// of `HttpServerStarter` (and await the result) to actually start the
/// server.
fn new(
config: &ConfigDropshot,
server_config: ServerConfig,
config: ConfigDropshot,
api: ApiDescription<C>,
private: C,
log: &Logger,
Expand All @@ -296,7 +260,7 @@ impl<C: ServerContext> InnerHttpServerStarter<C> {

let app_state = Arc::new(DropshotState {
private,
config: server_config,
config,
router: api.into_router(),
log: log.new(o!("local_addr" => local_addr)),
local_addr,
Expand Down Expand Up @@ -569,8 +533,7 @@ impl<C: ServerContext> InnerHttpsServerStarter<C> {
}

fn new(
config: &ConfigDropshot,
server_config: ServerConfig,
config: ConfigDropshot,
api: ApiDescription<C>,
private: C,
log: &Logger,
Expand All @@ -597,7 +560,7 @@ impl<C: ServerContext> InnerHttpsServerStarter<C> {

let app_state = Arc::new(DropshotState {
private,
config: server_config,
config,
router: api.into_router(),
log: logger,
local_addr,
Expand Down
9 changes: 5 additions & 4 deletions dropshot/src/websocket.rs
Original file line number Diff line number Diff line change
Expand Up @@ -296,10 +296,10 @@ impl JsonSchema for WebsocketUpgrade {
mod tests {
use crate::config::HandlerTaskMode;
use crate::router::HttpRouter;
use crate::server::{DropshotState, ServerConfig};
use crate::server::DropshotState;
use crate::{
ExclusiveExtractor, HttpError, RequestContext, RequestInfo,
WebsocketUpgrade,
ConfigDropshot, ExclusiveExtractor, HttpError, RequestContext,
RequestInfo, WebsocketUpgrade,
};
use debug_ignore::DebugIgnore;
use http::Request;
Expand All @@ -324,13 +324,14 @@ mod tests {
let rqctx = RequestContext {
server: Arc::new(DropshotState {
private: (),
config: ServerConfig {
config: ConfigDropshot {
request_body_max_bytes: 0,
page_max_nitems: NonZeroU32::new(1).unwrap(),
page_default_nitems: NonZeroU32::new(1).unwrap(),
default_handler_task_mode:
HandlerTaskMode::CancelOnDisconnect,
log_headers: Default::default(),
..Default::default()
},
router: HttpRouter::new(),
log: log.clone(),
Expand Down
1 change: 1 addition & 0 deletions dropshot/tests/test_config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,7 @@ fn make_config(
request_body_max_bytes: 1024,
default_handler_task_mode,
log_headers: Default::default(),
..Default::default()
}
}

Expand Down
2 changes: 2 additions & 0 deletions dropshot/tests/test_tls.rs
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,7 @@ fn make_server(
request_body_max_bytes: 1024,
default_handler_task_mode: HandlerTaskMode::CancelOnDisconnect,
log_headers: Default::default(),
..Default::default()
};
let config_tls = Some(ConfigTls::AsFile {
cert_file: cert_file.to_path_buf(),
Expand Down Expand Up @@ -428,6 +429,7 @@ async fn test_server_is_https() {
request_body_max_bytes: 1024,
default_handler_task_mode: HandlerTaskMode::CancelOnDisconnect,
log_headers: Default::default(),
..Default::default()
};
let config_tls = Some(ConfigTls::AsFile {
cert_file: cert_file.path().to_path_buf(),
Expand Down