-
#959 expands the settings available via
ConfigDropshot. This adds two new fieldspage_max_nitemsandpage_default_nitemsthat will need to be added wherever aConfigDropshotstruct is manually constructed.
-
#676 changed how TLS configuration is provided to Dropshot.
ConfigDropshotTlsis now no longer part ofConfigDropshot. If you’re using TLS, you need to provide this as a separate argument toHttpServerStarter::new_tls(). See #676 for details. -
#651 The address of the remote peer is now available to request handlers via the
RequestInfostruct. With this change we’ve removed the relatedFrom<hyper::Request<B>>implementation; instead useRequestInfo::new<B>(&hyper::Request<B>, std::net::SocketAddr). -
#701 changes how Dropshot manages the tasks that are used to handle requests. There are two modes, now configurable server-wide using
HandlerTaskMode. Prior to this change, the behavior matched what’s now calledHandlerTaskMode::CancelOnDisconnect: the Future associated with a request handler could be cancelled if, for example, the client disconnected early. After this change, the default behavior is what’s now calledHandlerTaskMode::Detached, which causes Dropshot to usetokio::spawnto run the request handler. That task will never be cancelled. This is useful for consumers whose request handlers may not be cancellation-safe. -
#849 updates rustls to 0.22 which is a breaking change due to the dependency on
rustls::ServerConfig. If your server supplies aServerConfigyou will need to apply the appropriate changes.
-
#660 The
x-dropshot-paginationextension used to be simply the valuetrue. Now it is an object with a field,required, that is an array of parameters that are mandatory on the first invocation.
There are a number of breaking changes in this release but we expect they will be easy to manage. If you have any trouble updating to this release or want help with it, please do start a discussion or file an issue!
-
#558 Remove
ArcaroundRequestContext. Previously, endpoint functions and extractors acceptedArc<RequestContext<T>>. They now accept justRequestContext<T>. This better reflects the intent that theRequestContextis provided for the duration of your endpoint function.We expect this to be an annoying (sorry) but otherwise easy change for consumers to make. If it’s tricky for some reason, please file an issue.
What you need to do:
-
For every endpoint function, change the type of the first argument from
Arc<RequestContext<T>>toRequestContext<T>. In case it’s useful, the following vim command worked to convert most of the cases we’ve seen:%s/Arc<RequestContext<\([^>]*\)>>/RequestContext<\1>/gc. -
For any type you’ve defined that impls
Extractor, you will need to adjust the arguments similarly. See the next bullet item to fix these for both this change and #556.
-
-
#556 Better type-safety around the use of extractors. It is now a compile-time error to define an endpoint that accepts two extractors that use the HTTP request body (e.g., to accept both a
TypedBodyand anUntypedBody, or twoTypedBodyarguments). Previously, this would have resulted in a runtime error. The main change is that theExtractortrait has been split into two separate traits:SharedExtractorandExclusiveExtractor. Endpoint functions can still accept 0-3 extractors, but only one can be anExclusiveExtractorand it must be the last one. The function signatures for*Extractor::from_requesthave also changed.What you need to do:
-
For any endpoint functions that use a
TypedBody,UntypedBody, orWebsocketConnectionextractor, this extractor must be the last argument to the function. Otherwise, you will get a compile error about the extractor not impl’ingSharedExtractor. -
If you have your own type that impls
Extractor, you will need to change that to eitherExclusiveExtractor(if the impl needs amutreference to the underlyinghyper::Request, which is usually because it needs to read the request body) orSharedExtractor. If your extractor only needs to look at the URL or request headers and not the body, it can probably be aSharedExtractor. If it’s an exclusive extractor, any function that accepts it must accept it as the last argument to the function. -
Again if you have your own type that impls
Extractor, having now updated it to eitherSharedExtractororExclusiveExtractor, you will also need to change the type signature of thefrom_requestmethod to accept a&RequestContext<T>instead ofArc<RequestContext<T>>. (This should not be a problem unless your extractor was hanging on to a reference via the Arc. We don’t know a reason this would be useful. If you were doing this, please start a discussion or file an issue. In the meantime, you likely can copy whatever information you need out of theRequestContextrather than cloning the Arc.)
-
-
#557 Simpler, safer access to raw request. Prior to this change, the raw
hyper::Request(http::Request) was accessible to endpoint functions via theRequestContext, but behind anArc<Mutex<…>>. This was a little strange because your endpoint function was usually the only one with a reference to this object. (You could get into trouble if you defined your own Extractor that cloned one of theArcobjects — your extractor could deadlock with the handler.) After this change, the raw request is available only through a separateRawRequestextractor. This is an exclusive extractor, which means you cannot use it withTypedBodyorUntypedBody. As a result, there is no way to wind up with multiple references to the request. There’s no lock and no way to get into this sort of trouble.After this change, the
hyper::Requestis passed as a separate argument toExclusiveExtractor::from_request().What you need to do:
-
If you have a request handler that accesses
rqctx.request, it’s typically doinglet request = rqctx.request.lock().await.-
If that code is only accessing the HTTP method, URI, headers, or version, then you can skip this step. However, it’s recommended that you replace that with
let request = &rqctx.request. (That object has methods compatible withhttp::Requestfor accessing the method, URI, headers, and version.) -
If that code is accessing other parts of the request (e.g., reading the body or doing a protocol upgrade), then you must instead add a
raw_request: RawRequestargument to your endpoint function. Then you can uselet request = raw_request.into_inner().
-
-
If you have an extractor that access
rqctx.request, then it too is typically doing something likelet request = rqctx.request.lock().await.-
If that code is only accessing the HTTP method, URI, headers, or version, then just like above you can skip this step, but it’s recommended that you replace that with
let request = &rqctx.request. This can be done from aSharedExtractoror anExclusiveExtractor. -
If that code is accessing other parts of the request (e.g., reading the body or doing a protocol upgrade), then this extractor must impl
ExclusiveExtractor(notSharedExtractor). WithExclusiveExtractor, thehyper::Requestis available as an argument tofrom_request().
-
-
-
#504 Dropshot now allows TLS configuration to be supplied either by path or as bytes. For compatibility, the
AsFilevariant ofConfigTlscontains thecert_fileandkey_filefields, and may be used similarly to the old variant. -
#502 Dropshot exposes a
refresh_tlsmethod to update the TLS certificates being used by a running server.What you need to do: If you previously tried to access
DropshotState.tls, you can access theDropshotState.using_tls()method instead. -
#540
ConfigDropshotnow uses acamino::Utf8PathBuffor its file path. There is no change to the configuration format itself, just its representation in Rust.
We realize this was a lot of breaking changes. We expect that most of these will affect few people (there don’t seem to be a lot of custom extractor impls out there). The rest are pretty mechanical. We hope the result will be a safer, easier to use API.
-
#522 Dropshot’s DTrace probes can now be used with a stable compiler on all platforms. This requires Rust >= 1.59 for most platforms, or >= 1.66 for macOS.
-
#452 Dropshot no longer enables the
slogcargo featuresmax_level_traceandrelease_max_level_debug. Previously, clients were unable to set a release log level oftrace; now they can. However, clients that did not select their own max log levels will see behavior change from the levels Dropshot was choosing to the default levels ofslogitself (debugfor debug builds andinfofor release builds). -
#451 There are now response types to support 302 ("Found"), 303 ("See Other"), and 307 ("Temporary Redirect") HTTP response codes. See
HttpResponseFound,HttpResponseSeeOther, andHttpResponseTemporaryRedirect. -
503 Add an optional
deprecatedfield to the[endpoint]macro.
-
#403 Dropshot now supports WebSockets. See the docs for details.
As part of this, the
ExtractorMetadatatype has been changed to represent our nonstandard extensions to OpenAPI in a fieldextension_mode: ExtensionMode, rather thanpaginated: bool, which was previously our only nonstandard extension, but is now joined by WebSockets.In any existing code that checked
extractor_metadata.paginated, you can instead check thatextractor_metadata.extension_modeisExtensionMode::Paginated. -
#351 The
uuidcrate has been updated to version 1.0.0 from 0.8.0. Consumers will need to update to a compatible version ofuuid. In addition consumers that were using theuuidfeature flag of theschemarscrate (so thatuuid::Uuidimplementsschemars::JsonSchema) will need to use theuuid1feature flag instead to force the use ofuuidversion 1.0.0.
-
#363 You can now decode
application/x-www-form-urlencodedbodies by specifying thecontent_typeproperty when you invoke theendpointmacro. See docs for details. -
#370 You can now define handlers for the
OPTIONSHTTP method. -
#420 Handlers can now determine whether the request came in over HTTP or HTTPS using
rqctx.server.tls.
-
#197 Endpoints using wildcard path params (i.e. those using the
/foo/{bar:.*}syntax) previously could be included in OpenAPI output albeit in a form that was invalid. Specifying a wildcard path without also specifyingunpublished = trueis now a compile-time error. -
#204 Rust 1.58.0-nightly introduced a new feature
asm_symwhich theusdtcrate requires on macOS. As of this change 1.58.0-nightly or later is required to build with theusdt-probesfeature on macOS. -
#310 changed the name of
HttpResponse::metadata()toHttpResponse::response_metadata().
-
#198 Responses that used
()(the unit type) as theirBodytype parameter previously (and inaccurately) were represented in OpenAPI as an emptyresponseBody. They are now more accurately represented as a body whose value isnull(4 bytes). We encourage those use cases to instead use eitherHttpResponseUpdatedNoContentorHttpResponseDeletedboth of which have empty response bodies. If there are other situations where you would like a response type with no body, please file an issue. -
252 Endpoints specified with the
#[endpoint ..]attribute macro now use the first line of a doc comment as the OpenAPIsummaryand subsequent lines as thedescription. Previously all lines were used as thedescription. -
#260 Pulls in a newer serde that changes error messages around parsing NonZeroU32.
-
#283 Add support for response headers with the
HttpResponseHeaderstype. Headers may either be defined by a struct type parameter (in which case they appear in the OpenAPI output) or ad-hoc added viaHttpResponseHeaders::headers_mut(). -
#286 OpenAPI output includes descriptions of 4xx and 5xx error responses.
-
#296
ApiDescriptionincludes atag_configmethod to specify both predefined tags with descriptions and links as well as a tag policy to ensure that endpoints, for example, only use predefined tags or have at least one tag. -
#317 Allow use of usdt probes with stable Rust. Dropshot consumers can build with USDT probes enabled on stable compilers >= 1.59 (except on MacOS).
-
#310 Freeform (and streaming) response bodies may be specified with specific HTTP response codes e.g. by having an endpoint return
Result<HttpResponseOk<FreeformBody>, HttpError>.-
#325 The example field (if present) for
JsonSchemaobjects in the API will be present in the OpenAPI output (and note that no validation of the example is performed)
-
-
#100 The type used for the "limit" argument for paginated resources has changed. This limit refers to the number of items that an HTTP client can ask for in a single request to a paginated endpoint. The limit is now 4294967295, where it may have previously been larger. This is not expected to affect consumers because this limit is far larger than practical. For details, see #100.
-
#116 Unused, non-
pubendpoints from the#[endpoint { … }]macro now produce a lint warning. This is technically a breaking change for those who may have had unused endpoints and compiled with#[deny(warning)]or#[deny(dead_code)]thus implicitly relying on the absence of a warning about the endpoint being unused. -
#118 Path handling has changed. Escape sequences are decoded so that path parameters will no longer include those escape sequences. In addition, paths for endpoints added via
ApiDescription::register()may not contain consecutive "/" characters. -
#161 The
ApiDescription::print_openapi()interface (previously deprecated) has been removed. Now useApiDescription::openapi()followed by a call toOpenApiDefinition::write()for equivalent functionality. -
#103 When the Dropshot server is dropped before having been shut down, Dropshot now attempts to gracefully shut down rather than panic.
-
#105 When generating an OpenAPI spec, Dropshot now uses references rather than inline schemas to represent request and response bodies.
-
#110 Wildcard paths are now supported. Consumers may take over routing (e.g. for file serving) by annotating a path component:
/static/{path:.*}. Thepathmember should then be of typeVec<String>and it will be filled in with all path components following/static/. -
#148 Adds local/remote addresses to loggers, including those passed in the context to actual endpoint handlers. This fixes #46, allowing logs for a client to be correlated from connection to completion.
-
#164 Add
make_request_with_requestto test utils alongside existingmake_request_with_body. The caller can specify things like headers by passing in a request. -
#160 Adds DTrace USDT probes for a request start and finish, with details about the request and response. For more information, see the crate-level documentation.
-
#108 The use of permissive schemas (e.g. serde_json::Value) in API types is allowed.
-
#123 and #133 add several checks on endpoint function signatures.
-
#128 The use of newtype structs in path and query parameters is now supported.
-
Fixes the dependency on the
openapiv3crate. Because of this problem, builds against Dropshot 0.5.0 will not work.
|
Warning
|
This release does not build due to downstream dependencies. See 0.5.1. |
-
#86 Dropshot now uses generics to store client context, rather than relying on an internal
Anyobject withinRequestContext. Endpoints signatures are expected to begin with the argumentrqctx: Arc<RequestContext<CallerContext>>, for someCallerContextobject, and they may callrqtcx.context()to access the inner type. -
To provide this generic context, many Dropshot types are now generic, acting on a specialized context object (this includes
ApiDescription,ApiEndpoint,OpenApiDefinition,HttpServer,HttpServerStarter, andRequestContext). For the most part, the specialization is made implicit by passing the context argument to anHttpServerStarter(formerlyHttpServer).
struct ExampleContext { ... }
// Old Version:
#[endpoint { method = GET, path = "/endpoint" }]
pub async fn example_endpoint(
rqctx: Arc<RequestContext>,
) -> Result<HttpResponseOk<...>, HttpError> {
let ctx: Arc<dyn Any + Send + Sync + 'static> = Arc::clone(&rqctx.server.private);
let example_context = ctx.downcast::<ExampleContext>().expect("Wrong type");
...
}
// New Version
#[endpoint { method = GET, path = "/endpoint" }]
pub async fn example_endpoint(
rqctx: Arc<RequestContext<ExampleContext>>,
) -> Result<HttpResponseOk<...>, HttpError> {
let example_context = rqctx.context();
...
}See #81 for details
-
In the old implementation,
HttpServerrepresented both a pending and running server. Callers were expected to invokerun()to begin execution of the old server. -
In the new implementation,
HttpServerStartermay be used to construct a server, andHttpServerrepresents the running server. InvokingHttpServerStarter::start()creates andHttpServerobject, which represents the new server.
-
In the old implementation,
HttpServerreturned atokio::JoinHandle, and callers were expected to invokewait_for_shutdownto await the completion of a server. -
In the new implementation,
HttpServerimplementsFuture, and may beawait-ed directly.
// Old Version:
let mut server = HttpServer::new( /* Arguments are the same between versions */ )
.map_err(|error| format!("failed to start server: {}", error))?;
let server_task = server.run();
server.wait_for_shutdown(server_task).await;
// New Version
let server = HttpServerStarter::new( /* Arguments are the same between versions */ )
.map_err(|error| format!("failed to start server: {}", error))?
.start();
server.await;-
Dropshot now uses tokio 1.0 and hyper 0.14. tokio 1.0 is incompatible at runtime with previous versions (0.2 and earlier). Consumers must update to tokio 1.0 when updating to Dropshot {{version}}. tokio does not expect to introduce new breaking changes in the foreseeable future, so we do not expect to have to do this again.
-
ApiDescription::print_openapi()is now deprecated. It’s been replaced withApiDescription::openapi(). See #68 below.
-
#68 Improve ergonomics of OpenAPI definition generation. This change deprecates
ApiDescription::print_openapi(), replacing it with the easier-to-useApiDescription::openapi(), which provides a builder interface. -
#64 The maximum request size is now configurable. It defaults to the previously hardcoded value of 1024 bytes. (The default is aggressive just to ensure test coverage.)
-
#61 The schemars dependency is updated to 0.8. Consumers must be using the same version of schemars. (See #67.)