From 6a1c3c9c7583e9e182ca3a906b7615af61a23b77 Mon Sep 17 00:00:00 2001 From: Rain Date: Sun, 28 Sep 2025 17:58:21 +0000 Subject: [PATCH] [spr] initial version Created using spr 1.3.6-beta.1 --- .github/workflows/rust.yml | 12 +- Cargo.toml | 4 + dropshot/Cargo.toml | 3 +- dropshot/examples/api-trait-websocket.rs | 2 +- dropshot/examples/basic.rs | 2 +- dropshot/examples/custom-error.rs | 2 +- dropshot/examples/file_server.rs | 2 +- dropshot/examples/https.rs | 2 +- dropshot/examples/index.rs | 2 +- dropshot/examples/module-basic.rs | 2 +- dropshot/examples/module-shared-context.rs | 4 +- dropshot/examples/multipart.rs | 2 +- dropshot/examples/multiple-servers.rs | 16 +- dropshot/examples/pagination-basic.rs | 2 +- .../examples/pagination-multiple-resources.rs | 2 +- .../examples/pagination-multiple-sorts.rs | 4 +- dropshot/examples/petstore.rs | 4 +- dropshot/examples/request-headers.rs | 2 +- dropshot/examples/schema-with-example.rs | 2 +- dropshot/examples/self-referential.rs | 4 +- dropshot/examples/versioning.rs | 2 +- dropshot/examples/websocket.rs | 4 +- dropshot/examples/well-tagged.rs | 6 +- dropshot/src/api_description.rs | 47 ++-- dropshot/src/body.rs | 2 +- dropshot/src/error.rs | 4 +- dropshot/src/extractor/body.rs | 10 +- dropshot/src/extractor/common.rs | 2 +- dropshot/src/extractor/header.rs | 9 +- dropshot/src/extractor/metadata.rs | 22 +- dropshot/src/extractor/path.rs | 6 +- dropshot/src/extractor/query.rs | 8 +- dropshot/src/from_map.rs | 6 +- dropshot/src/handler.rs | 32 +-- dropshot/src/lib.rs | 6 +- dropshot/src/logging.rs | 4 +- dropshot/src/pagination.rs | 37 +-- dropshot/src/router.rs | 250 ++++++++++-------- dropshot/src/schema_util.rs | 36 +-- dropshot/src/server.rs | 20 +- dropshot/src/test_util.rs | 8 +- dropshot/src/to_map.rs | 4 +- dropshot/src/type_util.rs | 6 +- dropshot/src/websocket.rs | 4 +- dropshot/tests/integration-tests/api_trait.rs | 5 +- dropshot/tests/integration-tests/common.rs | 4 +- dropshot/tests/integration-tests/config.rs | 4 +- .../tests/integration-tests/custom_errors.rs | 4 +- dropshot/tests/integration-tests/demo.rs | 30 +-- .../integration-tests/detached_shutdown.rs | 2 +- dropshot/tests/integration-tests/multipart.rs | 2 +- dropshot/tests/integration-tests/openapi.rs | 12 +- .../tests/integration-tests/pagination.rs | 14 +- .../integration-tests/pagination_schema.rs | 4 +- .../tests/integration-tests/path_names.rs | 2 +- dropshot/tests/integration-tests/starter.rs | 6 +- dropshot/tests/integration-tests/streaming.rs | 2 +- dropshot/tests/integration-tests/tls.rs | 6 +- dropshot/tests/integration-tests/versions.rs | 2 +- dropshot_endpoint/Cargo.toml | 3 +- dropshot_endpoint/src/api_trait.rs | 28 +- dropshot_endpoint/src/channel.rs | 41 +-- dropshot_endpoint/src/endpoint.rs | 27 +- dropshot_endpoint/src/metadata.rs | 6 +- dropshot_endpoint/src/params.rs | 6 +- dropshot_endpoint/src/syn_parsing.rs | 8 +- rustfmt.toml | 2 +- 67 files changed, 449 insertions(+), 381 deletions(-) diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml index c1ebe7315..723593c75 100644 --- a/.github/workflows/rust.yml +++ b/.github/workflows/rust.yml @@ -54,11 +54,18 @@ jobs: # macos-14 for M1 runners os: [ubuntu-22.04, windows-2022, macos-14] features: [all, default] + rust-version: + - stable + # 1.85 is the MSRV + - "1.85" include: - features: all feature_flags: --all-features steps: - uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 + - uses: dtolnay/rust-toolchain@v1 + with: + toolchain: ${{ matrix.rust-version }} - name: Report cargo version run: cargo --version - name: Report rustc version @@ -70,4 +77,7 @@ 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: cargo test ${{ matrix.feature_flags }} --locked --all-targets --verbose -- --exact --skip fail + - name: Run trybuild tests + run: cargo test ${{ matrix.feature_flags }} --locked --all-targets --verbose -- --exact fail + diff --git a/Cargo.toml b/Cargo.toml index 60eb568bb..8643fa5ec 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -9,6 +9,10 @@ default-members = ["dropshot", "dropshot_endpoint" ] resolver = "2" +[workspace.package] +edition = "2024" +rust-version = "1.85" + [workspace.lints.clippy] # Clippy's style nits are useful, but not worth keeping in CI. style = { level = "allow", priority = -1 } diff --git a/dropshot/Cargo.toml b/dropshot/Cargo.toml index 34ce22b35..3fdee1db0 100644 --- a/dropshot/Cargo.toml +++ b/dropshot/Cargo.toml @@ -3,7 +3,8 @@ name = "dropshot" description = "expose REST APIs from a Rust program" version = "0.16.4" authors = ["David Pacheco "] -edition = "2021" +edition.workspace = true +rust-version.workspace = true license = "Apache-2.0" repository = "https://github.com/oxidecomputer/dropshot/" readme = "README-crates.io.md" diff --git a/dropshot/examples/api-trait-websocket.rs b/dropshot/examples/api-trait-websocket.rs index 78c347258..b77ef30dd 100644 --- a/dropshot/examples/api-trait-websocket.rs +++ b/dropshot/examples/api-trait-websocket.rs @@ -67,7 +67,7 @@ mod imp { WebsocketConnection, }; use futures::SinkExt; - use tokio_tungstenite::tungstenite::{protocol::Role, Message}; + use tokio_tungstenite::tungstenite::{Message, protocol::Role}; use crate::api::{CounterApi, CounterValue}; diff --git a/dropshot/examples/basic.rs b/dropshot/examples/basic.rs index 6dc4a8193..21ca4cb5f 100644 --- a/dropshot/examples/basic.rs +++ b/dropshot/examples/basic.rs @@ -1,7 +1,6 @@ // Copyright 2020 Oxide Computer Company //! Example use of Dropshot. -use dropshot::endpoint; use dropshot::ApiDescription; use dropshot::ConfigLogging; use dropshot::ConfigLoggingLevel; @@ -11,6 +10,7 @@ use dropshot::HttpResponseUpdatedNoContent; use dropshot::RequestContext; use dropshot::ServerBuilder; use dropshot::TypedBody; +use dropshot::endpoint; use schemars::JsonSchema; use serde::Deserialize; use serde::Serialize; diff --git a/dropshot/examples/custom-error.rs b/dropshot/examples/custom-error.rs index a1f013393..d3e0321cc 100644 --- a/dropshot/examples/custom-error.rs +++ b/dropshot/examples/custom-error.rs @@ -3,7 +3,6 @@ //! An example demonstrating how to return user-defined error types from //! endpoint handlers. -use dropshot::endpoint; use dropshot::ApiDescription; use dropshot::ConfigLogging; use dropshot::ConfigLoggingLevel; @@ -14,6 +13,7 @@ use dropshot::HttpResponseOk; use dropshot::Path; use dropshot::RequestContext; use dropshot::ServerBuilder; +use dropshot::endpoint; use schemars::JsonSchema; use serde::Deserialize; use serde::Serialize; diff --git a/dropshot/examples/file_server.rs b/dropshot/examples/file_server.rs index 58ae830d6..330897bce 100644 --- a/dropshot/examples/file_server.rs +++ b/dropshot/examples/file_server.rs @@ -9,7 +9,7 @@ use dropshot::ConfigLoggingLevel; use dropshot::HttpError; use dropshot::RequestContext; use dropshot::ServerBuilder; -use dropshot::{endpoint, Path}; +use dropshot::{Path, endpoint}; use http::{Response, StatusCode}; use schemars::JsonSchema; use serde::Deserialize; diff --git a/dropshot/examples/https.rs b/dropshot/examples/https.rs index a744d08f7..a3ed85b26 100644 --- a/dropshot/examples/https.rs +++ b/dropshot/examples/https.rs @@ -2,7 +2,6 @@ //! Example use of Dropshot with TLS enabled -use dropshot::endpoint; use dropshot::ApiDescription; use dropshot::ConfigLogging; use dropshot::ConfigLoggingLevel; @@ -13,6 +12,7 @@ use dropshot::HttpResponseUpdatedNoContent; use dropshot::RequestContext; use dropshot::ServerBuilder; use dropshot::TypedBody; +use dropshot::endpoint; use schemars::JsonSchema; use serde::Deserialize; use serde::Serialize; diff --git a/dropshot/examples/index.rs b/dropshot/examples/index.rs index 54c9ef3c3..8b6411f64 100644 --- a/dropshot/examples/index.rs +++ b/dropshot/examples/index.rs @@ -8,7 +8,7 @@ use dropshot::ConfigLoggingLevel; use dropshot::HttpError; use dropshot::RequestContext; use dropshot::ServerBuilder; -use dropshot::{endpoint, Path}; +use dropshot::{Path, endpoint}; use http::{Response, StatusCode}; use schemars::JsonSchema; use serde::Deserialize; diff --git a/dropshot/examples/module-basic.rs b/dropshot/examples/module-basic.rs index 43373347f..ba7ac09b2 100644 --- a/dropshot/examples/module-basic.rs +++ b/dropshot/examples/module-basic.rs @@ -59,12 +59,12 @@ pub struct CounterValue { /// mountable routes pub mod routes { use crate::{CounterValue, ExampleContext}; - use dropshot::endpoint; use dropshot::HttpError; use dropshot::HttpResponseOk; use dropshot::HttpResponseUpdatedNoContent; use dropshot::RequestContext; use dropshot::TypedBody; + use dropshot::endpoint; use std::sync::atomic::Ordering; /// Fetch the current value of the counter. diff --git a/dropshot/examples/module-shared-context.rs b/dropshot/examples/module-shared-context.rs index b1becf339..b2800787f 100644 --- a/dropshot/examples/module-shared-context.rs +++ b/dropshot/examples/module-shared-context.rs @@ -2,7 +2,6 @@ //! Example use of Dropshot where a client wants to act on //! a custom context object that outlives endpoint functions. -use dropshot::endpoint; use dropshot::ApiDescription; use dropshot::ConfigLogging; use dropshot::ConfigLoggingLevel; @@ -10,13 +9,14 @@ use dropshot::HttpError; use dropshot::HttpResponseOk; use dropshot::RequestContext; use dropshot::ServerBuilder; +use dropshot::endpoint; use futures::FutureExt; use schemars::JsonSchema; use serde::Deserialize; use serde::Serialize; +use std::sync::Arc; use std::sync::atomic::AtomicU64; use std::sync::atomic::Ordering; -use std::sync::Arc; #[tokio::main] async fn main() -> Result<(), String> { diff --git a/dropshot/examples/multipart.rs b/dropshot/examples/multipart.rs index 211d400f2..6e3dc2b0d 100644 --- a/dropshot/examples/multipart.rs +++ b/dropshot/examples/multipart.rs @@ -1,7 +1,6 @@ // Copyright 2023 Oxide Computer Company //! Example use of Dropshot for multipart form-data. -use dropshot::endpoint; use dropshot::ApiDescription; use dropshot::Body; use dropshot::ConfigLogging; @@ -10,6 +9,7 @@ use dropshot::HttpError; use dropshot::MultipartBody; use dropshot::RequestContext; use dropshot::ServerBuilder; +use dropshot::endpoint; use http::{Response, StatusCode}; #[tokio::main] diff --git a/dropshot/examples/multiple-servers.rs b/dropshot/examples/multiple-servers.rs index b3810fec2..9292cee72 100644 --- a/dropshot/examples/multiple-servers.rs +++ b/dropshot/examples/multiple-servers.rs @@ -67,7 +67,6 @@ //! querying server "A" to show that "B" is gone. The logfiles of the running //! process will also note the shutdown of server B. -use dropshot::endpoint; use dropshot::ApiDescription; use dropshot::ConfigDropshot; use dropshot::ConfigLogging; @@ -81,22 +80,23 @@ use dropshot::Path; use dropshot::RequestContext; use dropshot::ServerBuilder; use dropshot::TypedBody; -use futures::future::BoxFuture; -use futures::stream::FuturesUnordered; +use dropshot::endpoint; use futures::FutureExt; use futures::StreamExt; +use futures::future::BoxFuture; +use futures::stream::FuturesUnordered; use schemars::JsonSchema; use serde::Deserialize; use serde::Serialize; -use slog::info; use slog::Logger; -use std::collections::hash_map::Entry; +use slog::info; use std::collections::HashMap; +use std::collections::hash_map::Entry; use std::mem; use std::net::SocketAddr; use std::sync::Arc; -use tokio::sync::mpsc; use tokio::sync::Mutex; +use tokio::sync::mpsc; #[tokio::main] async fn main() -> Result<(), String> { @@ -186,7 +186,9 @@ impl SharedMultiServerContext { let mut servers = self.servers.lock().await; let slot = match servers.entry(name.to_string()) { Entry::Occupied(_) => { - return Err(format!("already running a server named {name:?}",)) + return Err( + format!("already running a server named {name:?}",), + ); } Entry::Vacant(slot) => slot, }; diff --git a/dropshot/examples/pagination-basic.rs b/dropshot/examples/pagination-basic.rs index 395cca310..fefbdb0df 100644 --- a/dropshot/examples/pagination-basic.rs +++ b/dropshot/examples/pagination-basic.rs @@ -60,7 +60,6 @@ //! Now we have the next three projects and a new token. We can continue this //! way until we've listed all the projects. -use dropshot::endpoint; use dropshot::ApiDescription; use dropshot::ConfigDropshot; use dropshot::ConfigLogging; @@ -74,6 +73,7 @@ use dropshot::RequestContext; use dropshot::ResultsPage; use dropshot::ServerBuilder; use dropshot::WhichPage; +use dropshot::endpoint; use schemars::JsonSchema; use serde::Deserialize; use serde::Serialize; diff --git a/dropshot/examples/pagination-multiple-resources.rs b/dropshot/examples/pagination-multiple-resources.rs index 63775551c..56c706c28 100644 --- a/dropshot/examples/pagination-multiple-resources.rs +++ b/dropshot/examples/pagination-multiple-resources.rs @@ -3,7 +3,6 @@ //! multiple resources. See the other pagination examples for more information //! about how to run this. -use dropshot::endpoint; use dropshot::ApiDescription; use dropshot::ConfigDropshot; use dropshot::ConfigLogging; @@ -19,6 +18,7 @@ use dropshot::RequestContext; use dropshot::ResultsPage; use dropshot::ServerBuilder; use dropshot::WhichPage; +use dropshot::endpoint; use schemars::JsonSchema; use serde::Deserialize; use serde::Serialize; diff --git a/dropshot/examples/pagination-multiple-sorts.rs b/dropshot/examples/pagination-multiple-sorts.rs index 335294b6b..08903e63e 100644 --- a/dropshot/examples/pagination-multiple-sorts.rs +++ b/dropshot/examples/pagination-multiple-sorts.rs @@ -88,10 +88,9 @@ //! be relied upon. We mention it here just to help explain how the pagination //! mechanism works. -use chrono::offset::TimeZone; use chrono::DateTime; use chrono::Utc; -use dropshot::endpoint; +use chrono::offset::TimeZone; use dropshot::ApiDescription; use dropshot::ConfigDropshot; use dropshot::ConfigLogging; @@ -107,6 +106,7 @@ use dropshot::RequestContext; use dropshot::ResultsPage; use dropshot::ServerBuilder; use dropshot::WhichPage; +use dropshot::endpoint; use hyper::Uri; use schemars::JsonSchema; use serde::Deserialize; diff --git a/dropshot/examples/petstore.rs b/dropshot/examples/petstore.rs index aa350761c..0ca69f776 100644 --- a/dropshot/examples/petstore.rs +++ b/dropshot/examples/petstore.rs @@ -1,6 +1,6 @@ use dropshot::{ - endpoint, ApiDescription, HttpError, HttpResponseOk, PaginationParams, - Path, Query, RequestContext, ResultsPage, TypedBody, + ApiDescription, HttpError, HttpResponseOk, PaginationParams, Path, Query, + RequestContext, ResultsPage, TypedBody, endpoint, }; use schemars::JsonSchema; use serde::{Deserialize, Serialize}; diff --git a/dropshot/examples/request-headers.rs b/dropshot/examples/request-headers.rs index 0c09f9d26..bb0c02f12 100644 --- a/dropshot/examples/request-headers.rs +++ b/dropshot/examples/request-headers.rs @@ -10,7 +10,6 @@ //! This example is based on the "basic.rs" one. See that one for more detailed //! comments on the common code. -use dropshot::endpoint; use dropshot::ApiDescription; use dropshot::ConfigLogging; use dropshot::ConfigLoggingLevel; @@ -18,6 +17,7 @@ use dropshot::HttpError; use dropshot::HttpResponseOk; use dropshot::RequestContext; use dropshot::ServerBuilder; +use dropshot::endpoint; #[tokio::main] async fn main() -> Result<(), String> { diff --git a/dropshot/examples/schema-with-example.rs b/dropshot/examples/schema-with-example.rs index cd44fca0a..b413d2623 100644 --- a/dropshot/examples/schema-with-example.rs +++ b/dropshot/examples/schema-with-example.rs @@ -3,7 +3,7 @@ //! and how that will be reflected in the resultant JSON generated when ran. use dropshot::{ - endpoint, ApiDescription, HttpError, HttpResponseOk, RequestContext, + ApiDescription, HttpError, HttpResponseOk, RequestContext, endpoint, }; use schemars::JsonSchema; use serde::{Deserialize, Serialize}; diff --git a/dropshot/examples/self-referential.rs b/dropshot/examples/self-referential.rs index 9334f3a22..36afaf82b 100644 --- a/dropshot/examples/self-referential.rs +++ b/dropshot/examples/self-referential.rs @@ -2,7 +2,6 @@ //! An example that demonstrates server shutdown (and waiting for shutdown). -use dropshot::endpoint; use dropshot::ApiDescription; use dropshot::ConfigLogging; use dropshot::ConfigLoggingLevel; @@ -10,12 +9,13 @@ use dropshot::HttpError; use dropshot::HttpResponseOk; use dropshot::RequestContext; use dropshot::ServerBuilder; +use dropshot::endpoint; use schemars::JsonSchema; use serde::Deserialize; use serde::Serialize; +use std::sync::Arc; use std::sync::atomic::AtomicU64; use std::sync::atomic::Ordering; -use std::sync::Arc; #[tokio::main] async fn main() -> Result<(), String> { diff --git a/dropshot/examples/versioning.rs b/dropshot/examples/versioning.rs index fca2bddb0..4527c526d 100644 --- a/dropshot/examples/versioning.rs +++ b/dropshot/examples/versioning.rs @@ -95,7 +95,6 @@ //! {"thing1_late":"hello from a LATE v1"} //! ``` -use dropshot::endpoint; use dropshot::ApiDescription; use dropshot::ClientSpecifiesVersionInHeader; use dropshot::ConfigDropshot; @@ -106,6 +105,7 @@ use dropshot::HttpResponseOk; use dropshot::RequestContext; use dropshot::ServerBuilder; use dropshot::VersionPolicy; +use dropshot::endpoint; use http::HeaderName; use schemars::JsonSchema; use serde::Serialize; diff --git a/dropshot/examples/websocket.rs b/dropshot/examples/websocket.rs index 1bcec4de3..87b302fb1 100644 --- a/dropshot/examples/websocket.rs +++ b/dropshot/examples/websocket.rs @@ -1,7 +1,6 @@ // Copyright 2022 Oxide Computer Company //! Example use of Dropshot with a websocket endpoint. -use dropshot::channel; use dropshot::ApiDescription; use dropshot::ConfigLogging; use dropshot::ConfigLoggingLevel; @@ -9,11 +8,12 @@ use dropshot::Query; use dropshot::RequestContext; use dropshot::ServerBuilder; use dropshot::WebsocketConnection; +use dropshot::channel; use futures::SinkExt; use schemars::JsonSchema; use serde::Deserialize; -use tokio_tungstenite::tungstenite::protocol::Role; use tokio_tungstenite::tungstenite::Message; +use tokio_tungstenite::tungstenite::protocol::Role; #[tokio::main] async fn main() -> Result<(), String> { diff --git a/dropshot/examples/well-tagged.rs b/dropshot/examples/well-tagged.rs index 354aaa691..96bcf9547 100644 --- a/dropshot/examples/well-tagged.rs +++ b/dropshot/examples/well-tagged.rs @@ -6,9 +6,9 @@ //! proper tagging innate. use dropshot::{ - endpoint, ApiDescription, ConfigLogging, ConfigLoggingLevel, - EndpointTagPolicy, HttpError, HttpResponseOk, RequestContext, - ServerBuilder, TagConfig, TagDetails, TagExternalDocs, + ApiDescription, ConfigLogging, ConfigLoggingLevel, EndpointTagPolicy, + HttpError, HttpResponseOk, RequestContext, ServerBuilder, TagConfig, + TagDetails, TagExternalDocs, endpoint, }; #[endpoint { diff --git a/dropshot/src/api_description.rs b/dropshot/src/api_description.rs index 0a6334597..937b8d65a 100644 --- a/dropshot/src/api_description.rs +++ b/dropshot/src/api_description.rs @@ -2,6 +2,10 @@ //! Describes the endpoints and handler functions in your API +use crate::CONTENT_TYPE_JSON; +use crate::CONTENT_TYPE_MULTIPART_FORM_DATA; +use crate::CONTENT_TYPE_OCTET_STREAM; +use crate::CONTENT_TYPE_URL_ENCODED; use crate::extractor::RequestExtractor; use crate::handler::HttpHandlerFunc; use crate::handler::HttpResponse; @@ -9,23 +13,19 @@ use crate::handler::HttpResponseError; use crate::handler::HttpRouteHandler; use crate::handler::RouteHandler; use crate::handler::StubRouteHandler; -use crate::router::route_path_to_segments; use crate::router::HttpRouter; use crate::router::PathSegment; +use crate::router::route_path_to_segments; use crate::schema_util::j2oas_schema; use crate::server::ServerContext; use crate::type_util::type_is_scalar; use crate::type_util::type_is_string_enum; -use crate::CONTENT_TYPE_JSON; -use crate::CONTENT_TYPE_MULTIPART_FORM_DATA; -use crate::CONTENT_TYPE_OCTET_STREAM; -use crate::CONTENT_TYPE_URL_ENCODED; use http::Method; use http::StatusCode; -use serde::de::Error; use serde::Deserialize; use serde::Serialize; +use serde::de::Error; use std::collections::BTreeMap; use std::collections::HashMap; use std::collections::HashSet; @@ -395,8 +395,9 @@ impl ApiEndpointErrorResponse { pub enum ApiSchemaGenerator { Gen { name: fn() -> String, - schema: - fn(&mut schemars::gen::SchemaGenerator) -> schemars::schema::Schema, + schema: fn( + &mut schemars::r#gen::SchemaGenerator, + ) -> schemars::schema::Schema, }, Static { schema: Box, @@ -487,10 +488,10 @@ impl ApiDescription { match (&self.tag_config.policy, e.tags.len()) { (EndpointTagPolicy::AtLeastOne, 0) => { - return Err("At least one tag is required".to_string()) + return Err("At least one tag is required".to_string()); } (EndpointTagPolicy::ExactlyOne, n) if n != 1 => { - return Err("Exactly one tag is required".to_string()) + return Err("Exactly one tag is required".to_string()); } _ => (), } @@ -607,7 +608,7 @@ impl ApiDescription { }; match ¶m.metadata { - ApiEndpointParameterMetadata::Path(ref name) => { + ApiEndpointParameterMetadata::Path(name) => { match path_segments.get(name) { Some(SegmentOrWildcard::Segment) => { type_is_scalar( @@ -630,7 +631,7 @@ impl ApiDescription { } } } - ApiEndpointParameterMetadata::Query(ref name) => { + ApiEndpointParameterMetadata::Query(name) => { if path_segments.contains_key(name) { return Err(format!( "the parameter '{}' is specified for both query \ @@ -720,8 +721,8 @@ impl ApiDescription { // Sort the tags for stability openapi.tags.sort_by(|a, b| a.name.cmp(&b.name)); - let settings = schemars::gen::SchemaSettings::openapi3(); - let mut generator = schemars::gen::SchemaGenerator::new(settings); + let settings = schemars::r#gen::SchemaSettings::openapi3(); + let mut generator = schemars::r#gen::SchemaGenerator::new(settings); let mut definitions = indexmap::IndexMap::::new(); @@ -756,7 +757,7 @@ impl ApiDescription { ); let pathitem = match path { - openapiv3::ReferenceOr::Item(ref mut item) => item, + openapiv3::ReferenceOr::Item(item) => item, _ => panic!("reference not expected"), }; @@ -1031,8 +1032,8 @@ impl ApiDescription { error_responses.entry(type_name).or_insert_with(|| { let (error_schema, name) = match schema { ApiSchemaGenerator::Gen { - ref name, - ref schema, + name, + schema, } => { let schema = j2oas_schema( Some(&name()), @@ -1043,8 +1044,8 @@ impl ApiDescription { (schema, name()) } ApiSchemaGenerator::Static { - ref schema, - ref dependencies, + schema, + dependencies, } => { definitions.extend(dependencies.clone()); let schema = j2oas_schema(None, &schema); @@ -1664,18 +1665,18 @@ pub enum ExtensionMode { #[cfg(test)] mod test { - use crate::endpoint; - use crate::error::HttpError; - use crate::handler::RequestContext; use crate::ApiDescription; use crate::ApiEndpoint; use crate::Body; + use crate::CONTENT_TYPE_JSON; use crate::EndpointTagPolicy; use crate::Path; use crate::Query; use crate::TagConfig; use crate::TagDetails; - use crate::CONTENT_TYPE_JSON; + use crate::endpoint; + use crate::error::HttpError; + use crate::handler::RequestContext; use http::Method; use hyper::Response; use openapiv3::OpenAPI; diff --git a/dropshot/src/body.rs b/dropshot/src/body.rs index bf3585e85..41051b4fd 100644 --- a/dropshot/src/body.rs +++ b/dropshot/src/body.rs @@ -3,8 +3,8 @@ use std::pin::Pin; use std::task::{Context, Poll}; -use http_body_util::combinators::BoxBody; use http_body_util::BodyExt; +use http_body_util::combinators::BoxBody; use hyper::body::{Body as HttpBody, Bytes, Frame}; type BoxError = Box; diff --git a/dropshot/src/error.rs b/dropshot/src/error.rs index 374da95b1..cde9c75b3 100644 --- a/dropshot/src/error.rs +++ b/dropshot/src/error.rs @@ -146,9 +146,9 @@ impl JsonSchema for HttpErrorResponseBody { } fn json_schema( - gen: &mut schemars::gen::SchemaGenerator, + r#gen: &mut schemars::r#gen::SchemaGenerator, ) -> schemars::schema::Schema { - let str_schema = String::json_schema(gen); + let str_schema = String::json_schema(r#gen); schemars::schema::SchemaObject { metadata: Some( diff --git a/dropshot/src/extractor/body.rs b/dropshot/src/extractor/body.rs index 0c239baa9..7755da603 100644 --- a/dropshot/src/extractor/body.rs +++ b/dropshot/src/extractor/body.rs @@ -2,17 +2,17 @@ //! Body-related extractor(s) +use crate::ExclusiveExtractor; +use crate::ExtractorMetadata; +use crate::RequestContext; use crate::api_description::ApiEndpointParameter; use crate::api_description::ApiSchemaGenerator; use crate::api_description::{ApiEndpointBodyContentType, ExtensionMode}; use crate::error::HttpError; -use crate::http_util::http_dump_body; use crate::http_util::CONTENT_TYPE_JSON; +use crate::http_util::http_dump_body; use crate::schema_util::make_subschema_for; use crate::server::ServerContext; -use crate::ExclusiveExtractor; -use crate::ExtractorMetadata; -use crate::RequestContext; use async_trait::async_trait; use bytes::BufMut; use bytes::Bytes; @@ -20,9 +20,9 @@ use bytes::BytesMut; use futures::Stream; use futures::TryStreamExt; use http_body_util::BodyExt; +use schemars::JsonSchema; use schemars::schema::InstanceType; use schemars::schema::SchemaObject; -use schemars::JsonSchema; use serde::de::DeserializeOwned; use std::fmt::Debug; diff --git a/dropshot/src/extractor/common.rs b/dropshot/src/extractor/common.rs index 4fe10f11b..99dd29f08 100644 --- a/dropshot/src/extractor/common.rs +++ b/dropshot/src/extractor/common.rs @@ -1,10 +1,10 @@ // Copyright 2023 Oxide Computer Company +use crate::RequestContext; use crate::api_description::ApiEndpointParameter; use crate::api_description::{ApiEndpointBodyContentType, ExtensionMode}; use crate::error::HttpError; use crate::server::ServerContext; -use crate::RequestContext; use async_trait::async_trait; diff --git a/dropshot/src/extractor/header.rs b/dropshot/src/extractor/header.rs index 644db0132..77c788a5a 100644 --- a/dropshot/src/extractor/header.rs +++ b/dropshot/src/extractor/header.rs @@ -9,12 +9,11 @@ use schemars::JsonSchema; use serde::de::DeserializeOwned; use crate::{ - from_map::from_map_insensitive, ApiEndpointBodyContentType, - ApiEndpointParameterLocation, HttpError, RequestContext, RequestInfo, - ServerContext, + ApiEndpointBodyContentType, ApiEndpointParameterLocation, HttpError, + RequestContext, RequestInfo, ServerContext, from_map::from_map_insensitive, }; -use super::{metadata::get_metadata, ExtractorMetadata, SharedExtractor}; +use super::{ExtractorMetadata, SharedExtractor, metadata::get_metadata}; /// `Header` is an extractor used to deserialize an instance of /// `HeaderType` from an HTTP request's header values. `HeaderType` may be any @@ -93,7 +92,7 @@ mod tests { use schemars::JsonSchema; use serde::Deserialize; - use crate::{extractor::header::http_request_load_header, RequestInfo}; + use crate::{RequestInfo, extractor::header::http_request_load_header}; #[test] fn test_header_parsing() { diff --git a/dropshot/src/extractor/metadata.rs b/dropshot/src/extractor/metadata.rs index 0e2ec857c..6ad246eaf 100644 --- a/dropshot/src/extractor/metadata.rs +++ b/dropshot/src/extractor/metadata.rs @@ -1,15 +1,15 @@ // Copyright 2023 Oxide Computer Company -use crate::api_description::ApiSchemaGenerator; -use crate::pagination::PAGINATION_PARAM_SENTINEL; -use crate::schema_util::schema2struct; -use crate::schema_util::schema_extensions; -use crate::schema_util::StructMember; -use crate::websocket::WEBSOCKET_PARAM_SENTINEL; use crate::ApiEndpointParameter; use crate::ApiEndpointParameterLocation; use crate::ExtensionMode; use crate::ExtractorMetadata; +use crate::api_description::ApiSchemaGenerator; +use crate::pagination::PAGINATION_PARAM_SENTINEL; +use crate::schema_util::StructMember; +use crate::schema_util::schema_extensions; +use crate::schema_util::schema2struct; +use crate::websocket::WEBSOCKET_PARAM_SENTINEL; use schemars::JsonSchema; /// Convenience function to generate parameter metadata from types implementing @@ -20,7 +20,7 @@ pub(crate) fn get_metadata( where ParamType: JsonSchema, { - let mut settings = schemars::gen::SchemaSettings::openapi3(); + let mut settings = schemars::r#gen::SchemaSettings::openapi3(); // Headers can't be null. if let ApiEndpointParameterLocation::Header = loc { @@ -29,7 +29,7 @@ where // Generate the type for `ParamType` then pluck out each member of // the structure to encode as an individual parameter. - let mut generator = schemars::gen::SchemaGenerator::new(settings); + let mut generator = schemars::r#gen::SchemaGenerator::new(settings); let schema = generator.root_schema_for::().schema.into(); let extension_mode = match schema_extensions(&schema) { @@ -87,14 +87,14 @@ where mod test { use crate::api_description::ExtensionMode; use crate::{ - api_description::ApiEndpointParameterMetadata, ApiEndpointParameter, - ApiEndpointParameterLocation, PaginationParams, + ApiEndpointParameter, ApiEndpointParameterLocation, PaginationParams, + api_description::ApiEndpointParameterMetadata, }; use schemars::JsonSchema; use serde::{Deserialize, Serialize}; - use super::get_metadata; use super::ExtractorMetadata; + use super::get_metadata; #[derive(Deserialize, Serialize, JsonSchema)] #[allow(dead_code)] diff --git a/dropshot/src/extractor/path.rs b/dropshot/src/extractor/path.rs index 362eb7ae6..0b5b6417a 100644 --- a/dropshot/src/extractor/path.rs +++ b/dropshot/src/extractor/path.rs @@ -3,14 +3,14 @@ //! URL-related extractor(s) use super::metadata::get_metadata; +use crate::ExtractorMetadata; +use crate::RequestContext; +use crate::SharedExtractor; use crate::api_description::ApiEndpointBodyContentType; use crate::api_description::ApiEndpointParameterLocation; use crate::error::HttpError; use crate::http_util::http_extract_path_params; use crate::server::ServerContext; -use crate::ExtractorMetadata; -use crate::RequestContext; -use crate::SharedExtractor; use async_trait::async_trait; use schemars::JsonSchema; use serde::de::DeserializeOwned; diff --git a/dropshot/src/extractor/query.rs b/dropshot/src/extractor/query.rs index 8209a139a..57ec94cb0 100644 --- a/dropshot/src/extractor/query.rs +++ b/dropshot/src/extractor/query.rs @@ -3,14 +3,14 @@ //! Querystring-related extractor(s) use super::metadata::get_metadata; -use crate::api_description::ApiEndpointBodyContentType; -use crate::api_description::ApiEndpointParameterLocation; -use crate::error::HttpError; -use crate::server::ServerContext; use crate::ExtractorMetadata; use crate::RequestContext; use crate::RequestInfo; use crate::SharedExtractor; +use crate::api_description::ApiEndpointBodyContentType; +use crate::api_description::ApiEndpointParameterLocation; +use crate::error::HttpError; +use crate::server::ServerContext; use async_trait::async_trait; use schemars::JsonSchema; use serde::de::DeserializeOwned; diff --git a/dropshot/src/from_map.rs b/dropshot/src/from_map.rs index bf8638eae..64868419f 100644 --- a/dropshot/src/from_map.rs +++ b/dropshot/src/from_map.rs @@ -1,14 +1,14 @@ // Copyright 2025 Oxide Computer Company use paste::paste; +use serde::Deserialize; +use serde::Deserializer; use serde::de::DeserializeSeed; use serde::de::EnumAccess; use serde::de::MapAccess; use serde::de::SeqAccess; use serde::de::VariantAccess; use serde::de::Visitor; -use serde::Deserialize; -use serde::Deserializer; use std::any::type_name; use std::collections::BTreeMap; use std::fmt::Debug; @@ -134,7 +134,7 @@ where F: FnOnce(&Z) -> Result, { match self { - MapDeserializer::Value(ref raw_value) => deserialize(raw_value), + MapDeserializer::Value(raw_value) => deserialize(raw_value), MapDeserializer::Map(..) => Err(MapError( "must be applied to a flattened struct rather than a raw type" .to_string(), diff --git a/dropshot/src/handler.rs b/dropshot/src/handler.rs index c978a4fdb..541332f44 100644 --- a/dropshot/src/handler.rs +++ b/dropshot/src/handler.rs @@ -46,9 +46,9 @@ use crate::api_description::StubContext; use crate::body::Body; use crate::pagination::PaginationParams; use crate::router::VariableSet; +use crate::schema_util::StructMember; use crate::schema_util::make_subschema_for; use crate::schema_util::schema2struct; -use crate::schema_util::StructMember; use crate::to_map::to_map; use async_trait::async_trait; @@ -56,8 +56,8 @@ use http::HeaderMap; use http::StatusCode; use hyper::Response; use schemars::JsonSchema; -use serde::de::DeserializeOwned; use serde::Serialize; +use serde::de::DeserializeOwned; use slog::Logger; use std::cmp::min; use std::convert::TryFrom; @@ -311,22 +311,22 @@ pub enum HandlerError { impl HandlerError { pub(crate) fn status_code(&self) -> StatusCode { match self { - Self::Handler { ref rsp, .. } => rsp.status(), - Self::Dropshot(ref e) => e.status_code.as_status(), + Self::Handler { rsp, .. } => rsp.status(), + Self::Dropshot(e) => e.status_code.as_status(), } } pub(crate) fn internal_message(&self) -> &String { match self { - Self::Handler { ref message, .. } => message, - Self::Dropshot(ref e) => &e.internal_message, + Self::Handler { message, .. } => message, + Self::Dropshot(e) => &e.internal_message, } } pub(crate) fn external_message(&self) -> Option<&String> { match self { Self::Handler { .. } => None, - Self::Dropshot(ref e) => Some(&e.external_message), + Self::Dropshot(e) => Some(&e.external_message), } } @@ -924,7 +924,7 @@ pub struct Empty; /// object. pub trait HttpResponseContent { fn to_response(self, builder: http::response::Builder) - -> HttpHandlerResult; + -> HttpHandlerResult; // TODO the return type here could be something more elegant that is able // to produce the map of mime type -> openapiv3::MediaType that's needed in @@ -1346,10 +1346,8 @@ impl HttpResponseHeaders { } } } -impl< - T: HttpCodedResponse, - H: JsonSchema + Serialize + Send + Sync + 'static, - > HttpResponseHeaders +impl + HttpResponseHeaders { pub fn new(body: T, headers: H) -> Self { Self { @@ -1363,10 +1361,8 @@ impl< &mut self.other_headers } } -impl< - T: HttpCodedResponse, - H: JsonSchema + Serialize + Send + Sync + 'static, - > HttpResponse for HttpResponseHeaders +impl + HttpResponse for HttpResponseHeaders { fn to_result(self) -> HttpHandlerResult { let HttpResponseHeaders { body, structured_headers, other_headers } = @@ -1398,8 +1394,8 @@ impl< fn response_metadata() -> ApiEndpointResponse { let mut metadata = T::response_metadata(); - let mut generator = schemars::gen::SchemaGenerator::new( - schemars::gen::SchemaSettings::openapi3(), + let mut generator = schemars::r#gen::SchemaGenerator::new( + schemars::r#gen::SchemaSettings::openapi3(), ); let schema = generator.root_schema_for::().schema.into(); diff --git a/dropshot/src/lib.rs b/dropshot/src/lib.rs index 24d006fbe..3c0ea89fb 100644 --- a/dropshot/src/lib.rs +++ b/dropshot/src/lib.rs @@ -917,9 +917,6 @@ pub use extractor::SharedExtractor; pub use extractor::StreamingBody; pub use extractor::TypedBody; pub use extractor::UntypedBody; -pub use handler::http_response_found; -pub use handler::http_response_see_other; -pub use handler::http_response_temporary_redirect; pub use handler::FreeformBody; pub use handler::HttpCodedResponse; pub use handler::HttpResponse; @@ -937,6 +934,9 @@ pub use handler::NoHeaders; pub use handler::RequestContext; pub use handler::RequestEndpointMetadata; pub use handler::RequestInfo; +pub use handler::http_response_found; +pub use handler::http_response_see_other; +pub use handler::http_response_temporary_redirect; pub use http_util::CONTENT_TYPE_JSON; pub use http_util::CONTENT_TYPE_MULTIPART_FORM_DATA; pub use http_util::CONTENT_TYPE_NDJSON; diff --git a/dropshot/src/logging.rs b/dropshot/src/logging.rs index 961c57b85..ffcc6fbb9 100644 --- a/dropshot/src/logging.rs +++ b/dropshot/src/logging.rs @@ -179,12 +179,12 @@ fn log_drain_for_file( #[cfg(test)] mod test { + use crate::ConfigLogging; + use crate::test_util::BunyanLogRecordSpec; use crate::test_util::read_bunyan_log; use crate::test_util::read_config; use crate::test_util::verify_bunyan_records; use crate::test_util::verify_bunyan_records_sequential; - use crate::test_util::BunyanLogRecordSpec; - use crate::ConfigLogging; use libc; use slog::Logger; use std::fs; diff --git a/dropshot/src/pagination.rs b/dropshot/src/pagination.rs index a8a236485..a3cf89d96 100644 --- a/dropshot/src/pagination.rs +++ b/dropshot/src/pagination.rs @@ -99,13 +99,13 @@ use crate::error::HttpError; use crate::from_map::from_map; -use base64::engine::general_purpose::URL_SAFE; use base64::Engine; +use base64::engine::general_purpose::URL_SAFE; use schemars::JsonSchema; -use serde::de::DeserializeOwned; use serde::Deserialize; use serde::Deserializer; use serde::Serialize; +use serde::de::DeserializeOwned; use std::collections::BTreeMap; use std::fmt::Debug; use std::num::NonZeroU32; @@ -131,9 +131,9 @@ where } fn json_schema( - gen: &mut schemars::gen::SchemaGenerator, + r#gen: &mut schemars::r#gen::SchemaGenerator, ) -> schemars::schema::Schema { - ResultsPageSchema::::json_schema(gen) + ResultsPageSchema::::json_schema(r#gen) } } @@ -260,7 +260,7 @@ where } fn json_schema( - gen: &mut schemars::gen::SchemaGenerator, + r#gen: &mut schemars::r#gen::SchemaGenerator, ) -> schemars::schema::Schema { // We use `SchemaPaginationParams` to generate an intuitive schema and // we use the JSON schema extensions mechanism to communicate the fact @@ -273,9 +273,10 @@ where // // TODO we would ideally like to verify that both parameters *and* // response structure are properly configured for pagination. - let mut schema = SchemaPaginationParams::::json_schema(gen) - .into_object(); - let first_page_schema = ScanParams::json_schema(gen); + let mut schema = + SchemaPaginationParams::::json_schema(r#gen) + .into_object(); + let first_page_schema = ScanParams::json_schema(r#gen); let Some(first_page_object) = first_page_schema.into_object().object else { panic!("ScanParams must be an object"); @@ -500,18 +501,18 @@ fn deserialize_page_token( #[cfg(test)] mod test { - use super::deserialize_page_token; - use super::serialize_page_token; + use super::PAGINATION_PARAM_SENTINEL; use super::PaginationParams; use super::ResultsPage; use super::WhichPage; - use super::PAGINATION_PARAM_SENTINEL; - use base64::engine::general_purpose::URL_SAFE; + use super::deserialize_page_token; + use super::serialize_page_token; use base64::Engine; + use base64::engine::general_purpose::URL_SAFE; use schemars::JsonSchema; - use serde::de::DeserializeOwned; use serde::Deserialize; use serde::Serialize; + use serde::de::DeserializeOwned; use serde_json::json; use std::{fmt::Debug, num::NonZeroU32}; @@ -562,9 +563,9 @@ mod test { let error = serialize_page_token(&input).unwrap_err(); assert_eq!(error.status_code, http::StatusCode::INTERNAL_SERVER_ERROR); assert_eq!(error.external_message, "Internal Server Error"); - assert!(error - .internal_message - .contains("serialized token is too large")); + assert!( + error.internal_message.contains("serialized token is too large") + ); // Non-base64 let error = @@ -816,8 +817,8 @@ mod test { #[test] fn test_pagination_schema() { - let settings = schemars::gen::SchemaSettings::openapi3(); - let mut generator = schemars::gen::SchemaGenerator::new(settings); + let settings = schemars::r#gen::SchemaSettings::openapi3(); + let mut generator = schemars::r#gen::SchemaGenerator::new(settings); let schema = PaginationParams::::json_schema(&mut generator) .into_object(); diff --git a/dropshot/src/router.rs b/dropshot/src/router.rs index e624a2219..8335330cf 100644 --- a/dropshot/src/router.rs +++ b/dropshot/src/router.rs @@ -5,12 +5,12 @@ use super::error::HttpError; use super::error_status_code::ClientErrorStatusCode; use super::handler::RouteHandler; +use crate::ApiEndpoint; +use crate::RequestEndpointMetadata; use crate::api_description::ApiEndpointVersions; use crate::from_map::MapError; use crate::from_map::MapValue; use crate::server::ServerContext; -use crate::ApiEndpoint; -use crate::RequestEndpointMetadata; use http::Method; use percent_encoding::percent_decode_str; use semver::Version; @@ -268,7 +268,7 @@ impl HttpRouter { path, lit, varname ); } - HttpRouterEdges::Literals(ref mut literals) => literals + HttpRouterEdges::Literals(literals) => literals .entry(lit) .or_insert_with(|| Box::new(HttpRouterNode::new())), } @@ -302,10 +302,7 @@ impl HttpRouter { path, new_varname, varname, ), - HttpRouterEdges::VariableSingle( - varname, - ref mut node, - ) => { + HttpRouterEdges::VariableSingle(varname, node) => { if *new_varname != *varname { // Don't allow people to use different names for // the same part of the path. Again, this could @@ -363,10 +360,7 @@ impl HttpRouter { path, new_varname, varname, ), - HttpRouterEdges::VariableRest( - varname, - ref mut node, - ) => { + HttpRouterEdges::VariableRest(varname, node) => { if *new_varname != *varname { /* * Don't allow people to use different names for @@ -466,7 +460,7 @@ impl HttpRouter { Some(HttpRouterEdges::Literals(edges)) => { edges.get(&segment_string) } - Some(HttpRouterEdges::VariableSingle(varname, ref node)) => { + Some(HttpRouterEdges::VariableSingle(varname, node)) => { variables.insert( varname.clone(), VariableValue::String(segment_string), @@ -634,11 +628,7 @@ where { Box::new(node.methods.iter().flat_map(move |(m, handlers)| { handlers.iter().filter_map(move |h| { - if h.versions.matches(version) { - Some((m, h)) - } else { - None - } + if h.versions.matches(version) { Some((m, h)) } else { None } }) })) } @@ -722,7 +712,7 @@ impl<'a, Context: ServerContext> Iterator for HttpRouterIter<'a, Context> { // it's time to find the next node. match self.path.last_mut() { None => break None, - Some((_, ref mut last)) => match last.next() { + Some((_, last)) => match last.next() { None => { self.path.pop(); assert!(self.method.next().is_none()); @@ -842,16 +832,16 @@ mod test { use super::super::handler::HttpRouteHandler; use super::super::handler::RequestContext; use super::super::handler::RouteHandler; - use super::input_path_to_segments; use super::HttpRouter; use super::PathSegment; + use super::input_path_to_segments; + use crate::ApiEndpoint; + use crate::ApiEndpointResponse; + use crate::Body; use crate::api_description::ApiEndpointBodyContentType; use crate::api_description::ApiEndpointVersions; use crate::from_map::from_map; use crate::router::VariableValue; - use crate::ApiEndpoint; - use crate::ApiEndpointResponse; - use crate::Body; use http::Method; use http::StatusCode; use hyper::Response; @@ -1158,24 +1148,39 @@ mod test { // Insert a route into the middle of the tree. This will let us look at // parent nodes, sibling nodes, and child nodes. router.insert(new_endpoint(new_handler(), Method::GET, "/foo/bar")); - assert!(router - .lookup_route_unversioned(&Method::GET, "/foo/bar".into()) - .is_ok()); - assert!(router - .lookup_route_unversioned(&Method::GET, "/foo/bar/".into()) - .is_ok()); - assert!(router - .lookup_route_unversioned(&Method::GET, "//foo/bar".into()) - .is_ok()); - assert!(router - .lookup_route_unversioned(&Method::GET, "//foo//bar".into()) - .is_ok()); - assert!(router - .lookup_route_unversioned(&Method::GET, "//foo//bar//".into()) - .is_ok()); - assert!(router - .lookup_route_unversioned(&Method::GET, "///foo///bar///".into()) - .is_ok()); + assert!( + router + .lookup_route_unversioned(&Method::GET, "/foo/bar".into()) + .is_ok() + ); + assert!( + router + .lookup_route_unversioned(&Method::GET, "/foo/bar/".into()) + .is_ok() + ); + assert!( + router + .lookup_route_unversioned(&Method::GET, "//foo/bar".into()) + .is_ok() + ); + assert!( + router + .lookup_route_unversioned(&Method::GET, "//foo//bar".into()) + .is_ok() + ); + assert!( + router + .lookup_route_unversioned(&Method::GET, "//foo//bar//".into()) + .is_ok() + ); + assert!( + router + .lookup_route_unversioned( + &Method::GET, + "///foo///bar///".into() + ) + .is_ok() + ); // TODO-cleanup: consider having a "build" step that constructs a // read-only router and does validation like making sure that there's a @@ -1241,9 +1246,9 @@ mod test { // back, even if we use different names that normalize to "/". // Before we start, sanity-check that there's nothing at the root // already. Other test cases examine the errors in more detail. - assert!(router - .lookup_route_unversioned(&Method::GET, "/".into()) - .is_err()); + assert!( + router.lookup_route_unversioned(&Method::GET, "/".into()).is_err() + ); router.insert(new_endpoint(new_handler_named("h1"), Method::GET, "/")); let result = router.lookup_route_unversioned(&Method::GET, "/".into()).unwrap(); @@ -1263,9 +1268,9 @@ mod test { // we get both this handler and the previous one if we ask for the // corresponding method and that we get no handler for a different, // third method. - assert!(router - .lookup_route_unversioned(&Method::PUT, "/".into()) - .is_err()); + assert!( + router.lookup_route_unversioned(&Method::PUT, "/".into()).is_err() + ); router.insert(new_endpoint(new_handler_named("h2"), Method::PUT, "/")); let result = router.lookup_route_unversioned(&Method::PUT, "/".into()).unwrap(); @@ -1275,16 +1280,20 @@ mod test { router.lookup_route_unversioned(&Method::GET, "/".into()).unwrap(); assert_eq!(result.handler.label(), "h1"); assert!(result.endpoint.variables.is_empty()); - assert!(router - .lookup_route_unversioned(&Method::DELETE, "/".into()) - .is_err()); + assert!( + router + .lookup_route_unversioned(&Method::DELETE, "/".into()) + .is_err() + ); // Now insert a handler one level deeper. Verify that all the previous // handlers behave as we expect, and that we have one handler at the new // path, whichever name we use for it. - assert!(router - .lookup_route_unversioned(&Method::GET, "/foo".into()) - .is_err()); + assert!( + router + .lookup_route_unversioned(&Method::GET, "/foo".into()) + .is_err() + ); router.insert(new_endpoint( new_handler_named("h3"), Method::GET, @@ -1318,18 +1327,26 @@ mod test { .unwrap(); assert_eq!(result.handler.label(), "h3"); assert!(result.endpoint.variables.is_empty()); - assert!(router - .lookup_route_unversioned(&Method::PUT, "/foo".into()) - .is_err()); - assert!(router - .lookup_route_unversioned(&Method::PUT, "/foo/".into()) - .is_err()); - assert!(router - .lookup_route_unversioned(&Method::PUT, "//foo//".into()) - .is_err()); - assert!(router - .lookup_route_unversioned(&Method::PUT, "/foo//".into()) - .is_err()); + assert!( + router + .lookup_route_unversioned(&Method::PUT, "/foo".into()) + .is_err() + ); + assert!( + router + .lookup_route_unversioned(&Method::PUT, "/foo/".into()) + .is_err() + ); + assert!( + router + .lookup_route_unversioned(&Method::PUT, "//foo//".into()) + .is_err() + ); + assert!( + router + .lookup_route_unversioned(&Method::PUT, "/foo//".into()) + .is_err() + ); } #[test] @@ -1413,9 +1430,14 @@ mod test { // This isn't an important use case today, but we'd like to know if we // change the behavior, intentionally or otherwise. let mut router = HttpRouter::new(); - assert!(router - .lookup_route_unversioned(&Method::GET, "/not{a}variable".into()) - .is_err()); + assert!( + router + .lookup_route_unversioned( + &Method::GET, + "/not{a}variable".into() + ) + .is_err() + ); router.insert(new_endpoint( new_handler_named("h4"), Method::GET, @@ -1426,12 +1448,22 @@ mod test { .unwrap(); assert_eq!(result.handler.label(), "h4"); assert!(result.endpoint.variables.is_empty()); - assert!(router - .lookup_route_unversioned(&Method::GET, "/not{b}variable".into()) - .is_err()); - assert!(router - .lookup_route_unversioned(&Method::GET, "/notnotavariable".into()) - .is_err()); + assert!( + router + .lookup_route_unversioned( + &Method::GET, + "/not{b}variable".into() + ) + .is_err() + ); + assert!( + router + .lookup_route_unversioned( + &Method::GET, + "/notnotavariable".into() + ) + .is_err() + ); } #[test] @@ -1443,12 +1475,16 @@ mod test { Method::GET, "/projects/{project_id}", )); - assert!(router - .lookup_route_unversioned(&Method::GET, "/projects".into()) - .is_err()); - assert!(router - .lookup_route_unversioned(&Method::GET, "/projects/".into()) - .is_err()); + assert!( + router + .lookup_route_unversioned(&Method::GET, "/projects".into()) + .is_err() + ); + assert!( + router + .lookup_route_unversioned(&Method::GET, "/projects/".into()) + .is_err() + ); let result = router .lookup_route_unversioned(&Method::GET, "/projects/p12345".into()) .unwrap(); @@ -1461,12 +1497,14 @@ mod test { *result.endpoint.variables.get("project_id").unwrap(), VariableValue::String("p12345".to_string()) ); - assert!(router - .lookup_route_unversioned( - &Method::GET, - "/projects/p12345/child".into() - ) - .is_err()); + assert!( + router + .lookup_route_unversioned( + &Method::GET, + "/projects/p12345/child".into() + ) + .is_err() + ); let result = router .lookup_route_unversioned(&Method::GET, "/projects/p12345/".into()) .unwrap(); @@ -1545,24 +1583,30 @@ mod test { Method::GET, "/projects/{project_id}/instances", )); - assert!(router - .lookup_route_unversioned( - &Method::GET, - "/projects/instances".into() - ) - .is_err()); - assert!(router - .lookup_route_unversioned( - &Method::GET, - "/projects//instances".into() - ) - .is_err()); - assert!(router - .lookup_route_unversioned( - &Method::GET, - "/projects///instances".into() - ) - .is_err()); + assert!( + router + .lookup_route_unversioned( + &Method::GET, + "/projects/instances".into() + ) + .is_err() + ); + assert!( + router + .lookup_route_unversioned( + &Method::GET, + "/projects//instances".into() + ) + .is_err() + ); + assert!( + router + .lookup_route_unversioned( + &Method::GET, + "/projects///instances".into() + ) + .is_err() + ); let result = router .lookup_route_unversioned( &Method::GET, diff --git a/dropshot/src/schema_util.rs b/dropshot/src/schema_util.rs index dbae46322..a3f4008f2 100644 --- a/dropshot/src/schema_util.rs +++ b/dropshot/src/schema_util.rs @@ -2,8 +2,8 @@ //! schemars helper functions -use schemars::schema::SchemaObject; use schemars::JsonSchema; +use schemars::schema::SchemaObject; use std::fmt; @@ -26,7 +26,7 @@ pub(crate) fn schema2struct( schema_name: &str, kind: &str, schema: &schemars::schema::Schema, - generator: &schemars::gen::SchemaGenerator, + generator: &schemars::r#gen::SchemaGenerator, required: bool, ) -> Vec { match schema2struct_impl(schema, generator, required) { @@ -43,7 +43,7 @@ pub(crate) fn schema2struct( /// This function is invoked recursively on subschemas. fn schema2struct_impl( schema: &schemars::schema::Schema, - generator: &schemars::gen::SchemaGenerator, + generator: &schemars::r#gen::SchemaGenerator, required: bool, ) -> Result, Box> { // We ignore schema.metadata, which includes things like doc comments, and @@ -152,7 +152,7 @@ fn schema2struct_impl( Schema2StructError::InvalidSubschema( invalid.clone(), ), - )) + )); } } } @@ -241,9 +241,9 @@ impl fmt::Display for Schema2StructError { impl std::error::Error for Schema2StructError {} pub(crate) fn make_subschema_for( - gen: &mut schemars::gen::SchemaGenerator, + r#gen: &mut schemars::r#gen::SchemaGenerator, ) -> schemars::schema::Schema { - gen.subschema_for::() + r#gen.subschema_for::() } pub(crate) fn schema_extensions( @@ -936,8 +936,8 @@ mod test { #[derive(JsonSchema)] struct Empty {} - let settings = schemars::gen::SchemaSettings::openapi3(); - let mut generator = schemars::gen::SchemaGenerator::new(settings); + let settings = schemars::r#gen::SchemaSettings::openapi3(); + let mut generator = schemars::r#gen::SchemaGenerator::new(settings); let schema = Empty::json_schema(&mut generator); let _ = j2oas_schema(None, &schema); @@ -974,8 +974,8 @@ mod test { B { b: f32 }, } - let settings = schemars::gen::SchemaSettings::openapi3(); - let mut generator = schemars::gen::SchemaGenerator::new(settings); + let settings = schemars::r#gen::SchemaSettings::openapi3(); + let mut generator = schemars::r#gen::SchemaGenerator::new(settings); let schema = SuperGarbage::json_schema(&mut generator); let _ = j2oas_schema(None, &schema); @@ -991,8 +991,8 @@ mod test { enum Union { A { a: u32 }, } - let settings = schemars::gen::SchemaSettings::openapi3(); - let mut generator = schemars::gen::SchemaGenerator::new(settings); + let settings = schemars::r#gen::SchemaSettings::openapi3(); + let mut generator = schemars::r#gen::SchemaGenerator::new(settings); let schema = Union::json_schema(&mut generator); let _ = j2oas_schema(None, &schema); for (key, schema) in generator.definitions().iter() { @@ -1007,8 +1007,8 @@ mod test { struct Foo { bar: String, } - let settings = schemars::gen::SchemaSettings::openapi3(); - let generator = schemars::gen::SchemaGenerator::new(settings); + let settings = schemars::r#gen::SchemaSettings::openapi3(); + let generator = schemars::r#gen::SchemaGenerator::new(settings); let root_schema = generator.into_root_schema_for::>(); let schema = root_schema.schema; let os = j2oas_schema_object(None, &schema); @@ -1110,8 +1110,8 @@ mod test { } fn assert_enum_error() { - let mut generator = schemars::gen::SchemaGenerator::new( - schemars::gen::SchemaSettings::openapi3(), + let mut generator = schemars::r#gen::SchemaGenerator::new( + schemars::r#gen::SchemaSettings::openapi3(), ); let schema: schemars::schema::Schema = generator.root_schema_for::().schema.into(); @@ -1155,8 +1155,8 @@ mod test { front: Option, } - let schema = schemars::gen::SchemaGenerator::new( - schemars::gen::SchemaSettings::openapi3(), + let schema = schemars::r#gen::SchemaGenerator::new( + schemars::r#gen::SchemaSettings::openapi3(), ) .into_root_schema_for::() .schema; diff --git a/dropshot/src/server.rs b/dropshot/src/server.rs index 40f49c77e..1627096dc 100644 --- a/dropshot/src/server.rs +++ b/dropshot/src/server.rs @@ -1,6 +1,7 @@ // Copyright 2024 Oxide Computer Company //! Generic server-wide state and facilities +use super::ProbeRegistration; use super::api_description::ApiDescription; use super::body::Body; use super::config::{ConfigDropshot, ConfigTls}; @@ -11,7 +12,6 @@ use super::handler::RequestContext; use super::http_util::HEADER_REQUEST_ID; use super::router::HttpRouter; use super::versioning::VersionPolicy; -use super::ProbeRegistration; use async_stream::stream; use debug_ignore::DebugIgnore; @@ -20,11 +20,11 @@ use futures::future::{ }; use futures::lock::Mutex; use futures::stream::{Stream, StreamExt}; -use hyper::service::Service; use hyper::Request; use hyper::Response; +use hyper::service::Service; use rustls; -use scopeguard::{guard, ScopeGuard}; +use scopeguard::{ScopeGuard, guard}; use std::convert::TryFrom; use std::future::Future; use std::mem; @@ -37,12 +37,12 @@ use std::task::{Context, Poll}; use tokio::io::ReadBuf; use tokio::net::{TcpListener, TcpStream}; use tokio::sync::oneshot; -use tokio_rustls::{server::TlsStream, TlsAcceptor}; +use tokio_rustls::{TlsAcceptor, server::TlsStream}; use uuid::Uuid; use waitgroup::WaitGroup; -use crate::config::HandlerTaskMode; use crate::RequestInfo; +use crate::config::HandlerTaskMode; use slog::Logger; use thiserror::Error; @@ -1079,9 +1079,7 @@ pub enum BuildError { #[source] error: std::io::Error, }, - #[error( - "unversioned servers cannot have endpoints with specific versions" - )] + #[error("unversioned servers cannot have endpoints with specific versions")] UnversionedServerHasVersionedRoutes, } @@ -1206,14 +1204,14 @@ mod test { // Referring to the current crate as "dropshot::" instead of "crate::" // helps the endpoint macro with module lookup. use crate as dropshot; - use dropshot::endpoint; - use dropshot::test_util::ClientTestContext; - use dropshot::test_util::LogContext; use dropshot::ConfigLogging; use dropshot::ConfigLoggingLevel; use dropshot::HttpError; use dropshot::HttpResponseOk; use dropshot::RequestContext; + use dropshot::endpoint; + use dropshot::test_util::ClientTestContext; + use dropshot::test_util::LogContext; use http::StatusCode; use hyper::Method; diff --git a/dropshot/src/test_util.rs b/dropshot/src/test_util.rs index 8690c094e..f192ac7ad 100644 --- a/dropshot/src/test_util.rs +++ b/dropshot/src/test_util.rs @@ -11,10 +11,10 @@ use hyper::Request; use hyper::Response; use hyper::StatusCode; use hyper::Uri; -use hyper_util::client::legacy::{connect::HttpConnector, Client}; -use serde::de::DeserializeOwned; +use hyper_util::client::legacy::{Client, connect::HttpConnector}; use serde::Deserialize; use serde::Serialize; +use serde::de::DeserializeOwned; use slog::Logger; use std::convert::TryFrom; use std::fmt::Debug; @@ -959,10 +959,10 @@ mod test { const T1_STR: &str = "2020-03-24T00:00:00Z"; const T2_STR: &str = "2020-03-25T00:00:00Z"; - use super::verify_bunyan_records; - use super::verify_bunyan_records_sequential; use super::BunyanLogRecord; use super::BunyanLogRecordSpec; + use super::verify_bunyan_records; + use super::verify_bunyan_records_sequential; use chrono::DateTime; use chrono::Utc; diff --git a/dropshot/src/to_map.rs b/dropshot/src/to_map.rs index afc4f6429..3649fb049 100644 --- a/dropshot/src/to_map.rs +++ b/dropshot/src/to_map.rs @@ -3,8 +3,8 @@ use std::{collections::BTreeMap, fmt::Display}; use serde::{ - ser::{Impossible, SerializeStruct}, Serialize, Serializer, + ser::{Impossible, SerializeStruct}, }; /// Serialize an instance of T into a `BTreeMap`. @@ -325,7 +325,7 @@ impl Serializer for &mut ValueSerializer<'_> { mod test { use serde::Serialize; - use crate::to_map::{to_map, MapError}; + use crate::to_map::{MapError, to_map}; #[test] fn test_to_map_valid() { diff --git a/dropshot/src/type_util.rs b/dropshot/src/type_util.rs index b76b864d7..8ef47d058 100644 --- a/dropshot/src/type_util.rs +++ b/dropshot/src/type_util.rs @@ -261,8 +261,8 @@ fn type_resolve<'a>( mod tests { use indexmap::IndexMap; use schemars::{ - schema::{Schema, SchemaObject}, JsonSchema, + schema::{Schema, SchemaObject}, }; use crate::schema_util::schema2struct; @@ -322,8 +322,8 @@ mod tests { thing: Things, } - let mut generator = schemars::gen::SchemaGenerator::new( - schemars::gen::SchemaSettings::openapi3(), + let mut generator = schemars::r#gen::SchemaGenerator::new( + schemars::r#gen::SchemaSettings::openapi3(), ); let schema: schemars::schema::Schema = generator.root_schema_for::().schema.into(); diff --git a/dropshot/src/websocket.rs b/dropshot/src/websocket.rs index a2fee96ec..0ef939f19 100644 --- a/dropshot/src/websocket.rs +++ b/dropshot/src/websocket.rs @@ -14,9 +14,9 @@ use crate::{ }; use async_trait::async_trait; use base64::Engine; -use http::header; use http::Response; use http::StatusCode; +use http::header; use hyper::upgrade::OnUpgrade; use schemars::JsonSchema; use serde_json::json; @@ -290,7 +290,7 @@ impl JsonSchema for WebsocketUpgrade { } fn json_schema( - _gen: &mut schemars::gen::SchemaGenerator, + _gen: &mut schemars::r#gen::SchemaGenerator, ) -> schemars::schema::Schema { let mut schema = schemars::schema::SchemaObject::default(); schema diff --git a/dropshot/tests/integration-tests/api_trait.rs b/dropshot/tests/integration-tests/api_trait.rs index fe95438ae..bcb20ac4d 100644 --- a/dropshot/tests/integration-tests/api_trait.rs +++ b/dropshot/tests/integration-tests/api_trait.rs @@ -1,8 +1,9 @@ // Copyright 2024 Oxide Computer Company use dropshot::{ - test_util::read_json, EndpointTagPolicy, HandlerTaskMode, HttpError, - HttpResponseOk, HttpResponseUpdatedNoContent, RequestContext, UntypedBody, + EndpointTagPolicy, HandlerTaskMode, HttpError, HttpResponseOk, + HttpResponseUpdatedNoContent, RequestContext, UntypedBody, + test_util::read_json, }; use http::{Method, StatusCode}; use schemars::JsonSchema; diff --git a/dropshot/tests/integration-tests/common.rs b/dropshot/tests/integration-tests/common.rs index 8d2518f37..d1f9f31a1 100644 --- a/dropshot/tests/integration-tests/common.rs +++ b/dropshot/tests/integration-tests/common.rs @@ -2,8 +2,6 @@ //! Common facilities for automated testing. -use dropshot::test_util::LogContext; -use dropshot::test_util::TestContext; use dropshot::ApiDescription; use dropshot::ConfigDropshot; use dropshot::ConfigLogging; @@ -11,6 +9,8 @@ use dropshot::ConfigLoggingIfExists; use dropshot::ConfigLoggingLevel; use dropshot::HandlerTaskMode; use dropshot::ServerContext; +use dropshot::test_util::LogContext; +use dropshot::test_util::TestContext; use slog::o; use std::io::Write; use tempfile::NamedTempFile; diff --git a/dropshot/tests/integration-tests/config.rs b/dropshot/tests/integration-tests/config.rs index 2456cfb9f..0455376dc 100644 --- a/dropshot/tests/integration-tests/config.rs +++ b/dropshot/tests/integration-tests/config.rs @@ -2,15 +2,15 @@ //! Tests for configuration file. -use dropshot::test_util::read_config; use dropshot::Body; +use dropshot::test_util::read_config; use dropshot::{ ConfigDropshot, ConfigTls, HandlerTaskMode, HttpError, HttpResponseOk, RequestContext, }; use dropshot::{HttpServer, ServerBuilder}; -use slog::o; use slog::Logger; +use slog::o; use std::str::FromStr; use std::sync::atomic::{AtomicU16, Ordering}; use tempfile::NamedTempFile; diff --git a/dropshot/tests/integration-tests/custom_errors.rs b/dropshot/tests/integration-tests/custom_errors.rs index 827b4ee12..0242cb5c9 100644 --- a/dropshot/tests/integration-tests/custom_errors.rs +++ b/dropshot/tests/integration-tests/custom_errors.rs @@ -2,8 +2,6 @@ //! Test cases for user-defined error types. -use dropshot::endpoint; -use dropshot::test_util::TestContext; use dropshot::ApiDescription; use dropshot::ErrorStatusCode; use dropshot::HttpError; @@ -11,6 +9,8 @@ use dropshot::HttpResponseError; use dropshot::HttpResponseOk; use dropshot::Path; use dropshot::RequestContext; +use dropshot::endpoint; +use dropshot::test_util::TestContext; use http::Method; use http::StatusCode; use schemars::JsonSchema; diff --git a/dropshot/tests/integration-tests/demo.rs b/dropshot/tests/integration-tests/demo.rs index 4e3bebd58..67f0990df 100644 --- a/dropshot/tests/integration-tests/demo.rs +++ b/dropshot/tests/integration-tests/demo.rs @@ -13,19 +13,9 @@ //! TODO-hardening: add test cases that exceed limits (e.g., query string length, //! JSON body length) -use dropshot::channel; -use dropshot::endpoint; -use dropshot::http_response_found; -use dropshot::http_response_see_other; -use dropshot::http_response_temporary_redirect; -use dropshot::test_util::object_delete; -use dropshot::test_util::read_content_length; -use dropshot::test_util::read_json; -use dropshot::test_util::read_string; -use dropshot::test_util::TEST_HEADER_1; -use dropshot::test_util::TEST_HEADER_2; use dropshot::ApiDescription; use dropshot::Body; +use dropshot::CONTENT_TYPE_JSON; use dropshot::HttpError; use dropshot::HttpResponseDeleted; use dropshot::HttpResponseFound; @@ -43,19 +33,29 @@ use dropshot::TypedBody; use dropshot::UntypedBody; use dropshot::WebsocketChannelResult; use dropshot::WebsocketConnection; -use dropshot::CONTENT_TYPE_JSON; -use futures::stream::StreamExt; +use dropshot::channel; +use dropshot::endpoint; +use dropshot::http_response_found; +use dropshot::http_response_see_other; +use dropshot::http_response_temporary_redirect; +use dropshot::test_util::TEST_HEADER_1; +use dropshot::test_util::TEST_HEADER_2; +use dropshot::test_util::object_delete; +use dropshot::test_util::read_content_length; +use dropshot::test_util::read_json; +use dropshot::test_util::read_string; use futures::SinkExt; use futures::TryStreamExt; +use futures::stream::StreamExt; use http::StatusCode; use hyper::Method; use hyper::Response; use schemars::JsonSchema; use serde::Deserialize; use serde::Serialize; -use tokio_tungstenite::tungstenite::protocol::Role; -use tokio_tungstenite::tungstenite::Message; use tokio_tungstenite::WebSocketStream; +use tokio_tungstenite::tungstenite::Message; +use tokio_tungstenite::tungstenite::protocol::Role; use uuid::Uuid; use crate::common; diff --git a/dropshot/tests/integration-tests/detached_shutdown.rs b/dropshot/tests/integration-tests/detached_shutdown.rs index edfa66825..7d34322e5 100644 --- a/dropshot/tests/integration-tests/detached_shutdown.rs +++ b/dropshot/tests/integration-tests/detached_shutdown.rs @@ -5,7 +5,7 @@ use dropshot::Body; use dropshot::{ - endpoint, ApiDescription, HandlerTaskMode, HttpError, RequestContext, + ApiDescription, HandlerTaskMode, HttpError, RequestContext, endpoint, }; use http::{Method, Response, StatusCode}; use std::time::Duration; diff --git a/dropshot/tests/integration-tests/multipart.rs b/dropshot/tests/integration-tests/multipart.rs index 2ec40734e..36cfc7449 100644 --- a/dropshot/tests/integration-tests/multipart.rs +++ b/dropshot/tests/integration-tests/multipart.rs @@ -4,7 +4,7 @@ use dropshot::test_util::read_string; use dropshot::{ - endpoint, ApiDescription, Body, HttpError, MultipartBody, RequestContext, + ApiDescription, Body, HttpError, MultipartBody, RequestContext, endpoint, }; use http::{Method, Response, StatusCode}; diff --git a/dropshot/tests/integration-tests/openapi.rs b/dropshot/tests/integration-tests/openapi.rs index 399b2cb1c..170297f5f 100644 --- a/dropshot/tests/integration-tests/openapi.rs +++ b/dropshot/tests/integration-tests/openapi.rs @@ -1,14 +1,14 @@ // Copyright 2025 Oxide Computer Company use dropshot::{ - channel, endpoint, http_response_found, http_response_see_other, - http_response_temporary_redirect, ApiDescription, - ApiDescriptionRegisterError, FreeformBody, Header, HttpError, - HttpResponseAccepted, HttpResponseCreated, HttpResponseDeleted, + ApiDescription, ApiDescriptionRegisterError, FreeformBody, Header, + HttpError, HttpResponseAccepted, HttpResponseCreated, HttpResponseDeleted, HttpResponseFound, HttpResponseHeaders, HttpResponseOk, HttpResponseSeeOther, HttpResponseTemporaryRedirect, HttpResponseUpdatedNoContent, MultipartBody, PaginationParams, Path, Query, RequestContext, ResultsPage, TagConfig, TagDetails, TypedBody, UntypedBody, + channel, endpoint, http_response_found, http_response_see_other, + http_response_temporary_redirect, }; use dropshot::{Body, WebsocketConnection}; use schemars::JsonSchema; @@ -567,7 +567,7 @@ impl JsonSchema for WithXRustType { } fn json_schema( - gen: &mut schemars::gen::SchemaGenerator, + r#gen: &mut schemars::r#gen::SchemaGenerator, ) -> schemars::schema::Schema { use schemars::schema::*; @@ -585,7 +585,7 @@ impl JsonSchema for WithXRustType { "version": "*", "path": "foo", "parameters": [ - gen.subschema_for::(), + r#gen.subschema_for::(), ], }); extensions.insert("x-rust-type".to_string(), rust_type); diff --git a/dropshot/tests/integration-tests/pagination.rs b/dropshot/tests/integration-tests/pagination.rs index 3e443fa70..7e14c4d1d 100644 --- a/dropshot/tests/integration-tests/pagination.rs +++ b/dropshot/tests/integration-tests/pagination.rs @@ -4,12 +4,6 @@ use chrono::DateTime; use chrono::Utc; -use dropshot::endpoint; -use dropshot::test_util::iter_collection; -use dropshot::test_util::object_get; -use dropshot::test_util::objects_list_page; -use dropshot::test_util::ClientTestContext; -use dropshot::test_util::LogContext; use dropshot::ApiDescription; use dropshot::Body; use dropshot::ConfigLogging; @@ -24,13 +18,19 @@ use dropshot::Query; use dropshot::RequestContext; use dropshot::ResultsPage; use dropshot::WhichPage; +use dropshot::endpoint; +use dropshot::test_util::ClientTestContext; +use dropshot::test_util::LogContext; +use dropshot::test_util::iter_collection; +use dropshot::test_util::object_get; +use dropshot::test_util::objects_list_page; use http::Method; use http::StatusCode; use hyper::Request; use schemars::JsonSchema; -use serde::de::DeserializeOwned; use serde::Deserialize; use serde::Serialize; +use serde::de::DeserializeOwned; use std::collections::BTreeSet; use std::env::current_exe; use std::fmt::Debug; diff --git a/dropshot/tests/integration-tests/pagination_schema.rs b/dropshot/tests/integration-tests/pagination_schema.rs index 70f5386c0..e18910801 100644 --- a/dropshot/tests/integration-tests/pagination_schema.rs +++ b/dropshot/tests/integration-tests/pagination_schema.rs @@ -1,8 +1,8 @@ // Copyright 2020 Oxide Computer Company use dropshot::{ - endpoint, ApiDescription, HttpError, HttpResponseOk, PaginationParams, - Query, RequestContext, ResultsPage, + ApiDescription, HttpError, HttpResponseOk, PaginationParams, Query, + RequestContext, ResultsPage, endpoint, }; use schemars::JsonSchema; use serde::{Deserialize, Serialize}; diff --git a/dropshot/tests/integration-tests/path_names.rs b/dropshot/tests/integration-tests/path_names.rs index 863a2e371..82d4db2f8 100644 --- a/dropshot/tests/integration-tests/path_names.rs +++ b/dropshot/tests/integration-tests/path_names.rs @@ -1,7 +1,7 @@ // Copyright 2022 Oxide Computer Company use dropshot::{ - endpoint, ApiDescription, HttpError, HttpResponseOk, Path, RequestContext, + ApiDescription, HttpError, HttpResponseOk, Path, RequestContext, endpoint, }; use schemars::JsonSchema; use serde::Deserialize; diff --git a/dropshot/tests/integration-tests/starter.rs b/dropshot/tests/integration-tests/starter.rs index 930c8a3f1..197e4b0a4 100644 --- a/dropshot/tests/integration-tests/starter.rs +++ b/dropshot/tests/integration-tests/starter.rs @@ -3,9 +3,6 @@ //! Quick check that the "legacy" HttpServerStarter::new() and //! HttpServerStarter::new_with_tls() interfaces work. -use dropshot::endpoint; -use dropshot::test_util::read_json; -use dropshot::test_util::ClientTestContext; use dropshot::ApiDescription; use dropshot::ConfigDropshot; use dropshot::ConfigTls; @@ -13,6 +10,9 @@ use dropshot::HttpError; use dropshot::HttpResponseOk; use dropshot::HttpServerStarter; use dropshot::RequestContext; +use dropshot::endpoint; +use dropshot::test_util::ClientTestContext; +use dropshot::test_util::read_json; use crate::common; use crate::common::create_log_context; diff --git a/dropshot/tests/integration-tests/streaming.rs b/dropshot/tests/integration-tests/streaming.rs index 718fd8f2e..dd7dd1f2a 100644 --- a/dropshot/tests/integration-tests/streaming.rs +++ b/dropshot/tests/integration-tests/streaming.rs @@ -3,7 +3,7 @@ //! Test cases for streaming requests. use dropshot::Body; -use dropshot::{endpoint, ApiDescription, HttpError, RequestContext}; +use dropshot::{ApiDescription, HttpError, RequestContext, endpoint}; use http::{Method, Response, StatusCode}; use http_body_util::BodyExt; use tokio::io::{AsyncSeekExt, AsyncWriteExt}; diff --git a/dropshot/tests/integration-tests/tls.rs b/dropshot/tests/integration-tests/tls.rs index 1b061a647..66b4b9342 100644 --- a/dropshot/tests/integration-tests/tls.rs +++ b/dropshot/tests/integration-tests/tls.rs @@ -7,11 +7,11 @@ use dropshot::{ ConfigDropshot, ConfigTls, HandlerTaskMode, HttpResponseOk, HttpServer, ServerBuilder, }; -use slog::{o, Logger}; +use slog::{Logger, o}; use std::convert::TryFrom; use std::path::Path; -use std::sync::atomic::{AtomicUsize, Ordering}; use std::sync::Arc; +use std::sync::atomic::{AtomicUsize, Ordering}; use crate::common::{self, create_log_context, generate_tls_key}; @@ -130,7 +130,7 @@ fn make_server( fn make_pki_verifier( certs: &Vec, -) -> Arc { +) -> Arc> { let mut root_store = rustls::RootCertStore { roots: vec![] }; root_store.add(certs[certs.len() - 1].clone()).expect("adding root cert"); rustls::client::WebPkiServerVerifier::builder(Arc::new(root_store)) diff --git a/dropshot/tests/integration-tests/versions.rs b/dropshot/tests/integration-tests/versions.rs index 42e8d694f..918a7bf88 100644 --- a/dropshot/tests/integration-tests/versions.rs +++ b/dropshot/tests/integration-tests/versions.rs @@ -2,7 +2,6 @@ //! Exercise the API versioning behavior -use dropshot::endpoint; use dropshot::ApiDescription; use dropshot::ClientSpecifiesVersionInHeader; use dropshot::HttpError; @@ -11,6 +10,7 @@ use dropshot::HttpResponseOk; use dropshot::RequestContext; use dropshot::ServerBuilder; use dropshot::VersionPolicy; +use dropshot::endpoint; use reqwest::Method; use reqwest::StatusCode; use schemars::JsonSchema; diff --git a/dropshot_endpoint/Cargo.toml b/dropshot_endpoint/Cargo.toml index d245b5b06..4e0032473 100644 --- a/dropshot_endpoint/Cargo.toml +++ b/dropshot_endpoint/Cargo.toml @@ -3,7 +3,8 @@ name = "dropshot_endpoint" description = "macro used by dropshot consumers for registering handlers" version = "0.16.4" authors = ["Adam H. Leventhal "] -edition = "2021" +edition.workspace = true +rust-version.workspace = true license = "Apache-2.0" repository = "https://github.com/oxidecomputer/dropshot/" diff --git a/dropshot_endpoint/src/api_trait.rs b/dropshot_endpoint/src/api_trait.rs index 918b55748..e1273d929 100644 --- a/dropshot_endpoint/src/api_trait.rs +++ b/dropshot_endpoint/src/api_trait.rs @@ -25,16 +25,16 @@ use std::collections::HashMap; use heck::ToSnakeCase; use proc_macro2::TokenStream; -use quote::{format_ident, quote, quote_spanned, ToTokens}; +use quote::{ToTokens, format_ident, quote, quote_spanned}; use serde::Deserialize; use serde_tokenstream::{ - from_tokenstream, from_tokenstream_spanned, ParseWrapper, + ParseWrapper, from_tokenstream, from_tokenstream_spanned, }; -use syn::{parse_quote, parse_quote_spanned, spanned::Spanned, Error}; +use syn::{Error, parse_quote, parse_quote_spanned, spanned::Spanned}; use crate::{ channel::ChannelParams, - doc::{string_to_doc_attrs, ExtractedDoc}, + doc::{ExtractedDoc, string_to_doc_attrs}, endpoint::EndpointParams, error_store::{ErrorSink, ErrorStore}, metadata::{ @@ -46,7 +46,7 @@ use crate::{ ItemTraitPartParsed, TraitItemFnForSignature, TraitItemPartParsed, UnparsedBlock, }, - util::{get_crate, MacroKind}, + util::{MacroKind, get_crate}, }; pub(crate) fn do_trait( @@ -592,11 +592,7 @@ impl<'ast> ContextItem<'ast> { } // Don't return the type if there were errors. - if errors.has_errors() { - Self::Invalid(ty) - } else { - Self::Valid(ty) - } + if errors.has_errors() { Self::Invalid(ty) } else { Self::Valid(ty) } } fn new_missing( @@ -1191,13 +1187,19 @@ impl<'ast> ApiFnItem<'ast> { for attr in rest { let msg = match (first, attr) { (ApiAttr::Endpoint(_), ApiAttr::Endpoint(_)) => { - format!("method `{name}` marked as endpoint multiple times") + format!( + "method `{name}` marked as endpoint multiple times" + ) } (ApiAttr::Channel(_), ApiAttr::Channel(_)) => { - format!("method `{name}` marked as channel multiple times") + format!( + "method `{name}` marked as channel multiple times" + ) } _ => { - format!("method `{name}` marked as both endpoint and channel") + format!( + "method `{name}` marked as both endpoint and channel" + ) } }; diff --git a/dropshot_endpoint/src/channel.rs b/dropshot_endpoint/src/channel.rs index 5543cbc10..dee2d2cca 100644 --- a/dropshot_endpoint/src/channel.rs +++ b/dropshot_endpoint/src/channel.rs @@ -7,10 +7,10 @@ use crate::error_store::ErrorSink; use crate::error_store::ErrorStore; use crate::metadata::ApiEndpointKind; use crate::metadata::ChannelMetadata; -use crate::params::validate_fn_ast; use crate::params::ParamValidator; use crate::params::RqctxKind; use crate::params::RqctxTy; +use crate::params::validate_fn_ast; use crate::syn_parsing::ItemFnForSignature; use crate::syn_parsing::TraitItemFnForSignature; use crate::util::MacroKind; @@ -18,8 +18,8 @@ use proc_macro2::TokenStream; use quote::format_ident; use quote::quote; use quote::quote_spanned; -use serde_tokenstream::from_tokenstream; use serde_tokenstream::Error; +use serde_tokenstream::from_tokenstream; use syn::parse_quote; use syn::spanned::Spanned; @@ -305,25 +305,28 @@ impl<'ast> ChannelParams<'ast> { // errored out. if errors.has_errors() { None - } else if let (Some(rqctx_ty), Some(websocket_conn), Some(ret_ty)) = - (rqctx_ty, websocket_conn, ret_ty) - { - Some(Self { - dropshot: dropshot.clone(), - sig, - rqctx_ty, - ret_ty, - shared_extractors, - websocket_conn, - adapter_name, - websocket_upgrade_ty, - endpoint_result_ty, - }) } else { - unreachable!( - "no param errors, but rqctx_ty, \ + match (rqctx_ty, websocket_conn, ret_ty) { + (Some(rqctx_ty), Some(websocket_conn), Some(ret_ty)) => { + Some(Self { + dropshot: dropshot.clone(), + sig, + rqctx_ty, + ret_ty, + shared_extractors, + websocket_conn, + adapter_name, + websocket_upgrade_ty, + endpoint_result_ty, + }) + } + _ => { + unreachable!( + "no param errors, but rqctx_ty, \ websocket_upgrade or ret_ty is None" - ); + ); + } + } } } diff --git a/dropshot_endpoint/src/endpoint.rs b/dropshot_endpoint/src/endpoint.rs index 6245dd99a..c70441340 100644 --- a/dropshot_endpoint/src/endpoint.rs +++ b/dropshot_endpoint/src/endpoint.rs @@ -6,8 +6,8 @@ use proc_macro2::TokenStream; use quote::format_ident; use quote::quote; use quote::quote_spanned; -use serde_tokenstream::from_tokenstream; use serde_tokenstream::Error; +use serde_tokenstream::from_tokenstream; use syn::spanned::Spanned; use crate::doc::ExtractedDoc; @@ -15,10 +15,10 @@ use crate::error_store::ErrorSink; use crate::error_store::ErrorStore; use crate::metadata::ApiEndpointKind; use crate::metadata::EndpointMetadata; -use crate::params::validate_fn_ast; use crate::params::ParamValidator; use crate::params::RqctxKind; use crate::params::RqctxTy; +use crate::params::validate_fn_ast; use crate::syn_parsing::ItemFnForSignature; use crate::syn_parsing::TraitItemFnForSignature; use crate::util::MacroKind; @@ -296,16 +296,21 @@ impl<'ast> EndpointParams<'ast> { // have errored out. if errors.has_errors() { None - } else if let (Some(rqctx_ty), Some(ret_ty)) = (rqctx_ty, ret_ty) { - Some(Self { - dropshot: dropshot.clone(), - rqctx_ty, - shared_extractors, - exclusive_extractor, - ret_ty, - }) } else { - unreachable!("no param errors, but rqctx_ty or ret_ty is None"); + match (rqctx_ty, ret_ty) { + (Some(rqctx_ty), Some(ret_ty)) => Some(Self { + dropshot: dropshot.clone(), + rqctx_ty, + shared_extractors, + exclusive_extractor, + ret_ty, + }), + _ => { + unreachable!( + "no param errors, but rqctx_ty or ret_ty is None" + ); + } + } } } diff --git a/dropshot_endpoint/src/metadata.rs b/dropshot_endpoint/src/metadata.rs index 2f63d22f5..3dccfc217 100644 --- a/dropshot_endpoint/src/metadata.rs +++ b/dropshot_endpoint/src/metadata.rs @@ -3,15 +3,15 @@ //! Code to handle metadata associated with an endpoint. use proc_macro2::TokenStream; -use quote::{format_ident, quote_spanned, ToTokens}; +use quote::{ToTokens, format_ident, quote_spanned}; use serde::Deserialize; use serde_tokenstream::ParseWrapper; -use syn::{spanned::Spanned, Error}; +use syn::{Error, spanned::Spanned}; use crate::{ doc::ExtractedDoc, error_store::ErrorSink, - util::{get_crate, is_wildcard_path, MacroKind, ValidContentType}, + util::{MacroKind, ValidContentType, get_crate, is_wildcard_path}, }; #[allow(non_snake_case)] diff --git a/dropshot_endpoint/src/params.rs b/dropshot_endpoint/src/params.rs index aeb3abd92..5eb83fab8 100644 --- a/dropshot_endpoint/src/params.rs +++ b/dropshot_endpoint/src/params.rs @@ -4,9 +4,9 @@ use std::{fmt, iter::Peekable}; -use proc_macro2::{extra::DelimSpan, TokenStream}; -use quote::{quote_spanned, ToTokens}; -use syn::{parse_quote, spanned::Spanned, visit::Visit, Error}; +use proc_macro2::{TokenStream, extra::DelimSpan}; +use quote::{ToTokens, quote_spanned}; +use syn::{Error, parse_quote, spanned::Spanned, visit::Visit}; use crate::error_store::ErrorSink; diff --git a/dropshot_endpoint/src/syn_parsing.rs b/dropshot_endpoint/src/syn_parsing.rs index 108d90e63..3c54741ba 100644 --- a/dropshot_endpoint/src/syn_parsing.rs +++ b/dropshot_endpoint/src/syn_parsing.rs @@ -5,11 +5,11 @@ use quote::{ToTokens, TokenStreamExt}; use syn::{ - braced, bracketed, - parse::{discouraged::Speculative, Parse, ParseStream}, + Abi, AttrStyle, Attribute, Generics, Ident, ImplRestriction, Result, + Signature, Token, TraitItem, TypeParamBound, Visibility, braced, bracketed, + parse::{Parse, ParseStream, discouraged::Speculative}, punctuated::Punctuated, - token, Abi, AttrStyle, Attribute, Generics, Ident, ImplRestriction, Result, - Signature, Token, TraitItem, TypeParamBound, Visibility, + token, }; /// Represent an item without concern for its body which may (or may not) diff --git a/rustfmt.toml b/rustfmt.toml index 11297fdbe..59816574a 100644 --- a/rustfmt.toml +++ b/rustfmt.toml @@ -3,4 +3,4 @@ # --------------------------------------------------------------------------- max_width = 80 use_small_heuristics = "max" -edition = "2018" +edition = "2024"