Skip to content

December 12th, 2022

Pre-release
Pre-release
Compare
Choose a tag to compare
@aws-sdk-rust-ci aws-sdk-rust-ci released this 12 Dec 15:39
· 1396 commits to main since this release

Breaking Changes:

  • ⚠🎉 (all, smithy-rs#1938, @jjantdev) Upgrade Rust MSRV to 1.62.1

  • ⚠🎉 (server, smithy-rs#1199, smithy-rs#1342, smithy-rs#1401, smithy-rs#1998, smithy-rs#2005, smithy-rs#2028, smithy-rs#2034, smithy-rs#2036) Constraint traits in server SDKs are beginning to be supported. The following are now supported:

    • The length trait on string shapes.
    • The length trait on map shapes.
    • The length trait on list shapes.
    • The range trait on byte shapes.
    • The range trait on short shapes.
    • The range trait on integer shapes.
    • The range trait on long shapes.
    • The pattern trait on string shapes.

    Upon receiving a request that violates the modeled constraints, the server SDK will reject it with a message indicating why.

    Unsupported (constraint trait, target shape) combinations will now fail at code generation time, whereas previously they were just ignored. This is a breaking change to raise awareness in service owners of their server SDKs behaving differently than what was modeled. To continue generating a server SDK with unsupported constraint traits, set codegen.ignoreUnsupportedConstraints to true in your smithy-build.json.

    {
        ...
        "rust-server-codegen": {
            ...
            "codegen": {
                "ignoreUnsupportedConstraints": true
            }
        }
    }
  • ⚠🎉 (server, smithy-rs#1342, smithy-rs#1119) Server SDKs now generate "constrained types" for constrained shapes. Constrained types are newtypes that encapsulate the modeled constraints. They constitute a widespread pattern to guarantee domain invariants and promote correctness in your business logic. So, for example, the model:

    @length(min: 1, max: 69)
    string NiceString

    will now render a struct NiceString(String). Instantiating a NiceString is a fallible operation:

    let data: String = ... ;
    let nice_string = NiceString::try_from(data).expect("data is not nice");

    A failed attempt to instantiate a constrained type will yield a ConstraintViolation error type you may want to handle. This type's API is subject to change.

    Constrained types guarantee, by virtue of the type system, that your service's operation outputs adhere to the modeled constraints. To learn more about the motivation for constrained types and how they work, see the RFC.

    If you'd like to opt-out of generating constrained types, you can set codegen.publicConstrainedTypes to false. Note that if you do, the generated server SDK will still honor your operation input's modeled constraints upon receiving a request, but will not help you in writing business logic code that adheres to the constraints, and will not prevent you from returning responses containing operation outputs that violate said constraints.

    {
        ...
        "rust-server-codegen": {
            ...
            "codegen": {
                "publicConstrainedTypes": false
            }
        }
    }
  • 🐛⚠🎉 (server, smithy-rs#1714, smithy-rs#1342) Structure builders in server SDKs have undergone significant changes.

    The API surface has been reduced. It is now simpler and closely follows what you would get when using the derive_builder crate:

    1. Builders no longer have set_* methods taking in Option<T>. You must use the unprefixed method, named exactly after the structure's field name, and taking in a value whose type matches exactly that of the structure's field.
    2. Builders no longer have convenience methods to pass in an element for a field whose type is a vector or a map. You must pass in the entire contents of the collection up front.
    3. Builders no longer implement PartialEq.

    Bug fixes:

    1. Builders now always fail to build if a value for a required member is not provided. Previously, builders were falling back to a default value (e.g. "" for Strings) for some shapes. This was a bug.

    Additions:

    1. A structure Structure with builder Builder now implements TryFrom<Builder> for Structure or From<Builder> for Structure, depending on whether the structure is constrained or not, respectively.

    To illustrate how to migrate to the new API, consider the example model below.

    structure Pokemon {
        @required
        name: String,
        @required
        description: String,
        @required
        evolvesTo: PokemonList
    }
    
    list PokemonList {
        member: Pokemon
    }

    In the Rust code below, note the references calling out the changes described in the numbered list above.

    Before:

    let eevee_builder = Pokemon::builder()
        // (1) `set_description` takes in `Some<String>`.
        .set_description(Some("Su código genético es muy inestable. Puede evolucionar en diversas razas de Pokémon.".to_owned()))
        // (2) Convenience method to add one element to the `evolvesTo` list.
        .evolves_to(vaporeon)
        .evolves_to(jolteon)
        .evolves_to(flareon);
    
    // (3) Builder types can be compared.
    assert_ne!(eevee_builder, Pokemon::builder());
    
    // (4) Builds fine even though we didn't provide a value for `name`, which is `required`!
    let _eevee = eevee_builder.build();

    After:

    let eevee_builder = Pokemon::builder()
        // (1) `set_description` no longer exists. Use `description`, which directly takes in `String`.
        .description("Su código genético es muy inestable. Puede evolucionar en diversas razas de Pokémon.".to_owned())
        // (2) Convenience methods removed; provide the entire collection up front.
        .evolves_to(vec![vaporeon, jolteon, flareon]);
    
    // (3) Binary operation `==` cannot be applied to `pokemon::Builder`.
    // assert_ne!(eevee_builder, Pokemon::builder());
    
    // (4) `required` member `name` was not set.
    // (5) Builder type can be fallibly converted to the structure using `TryFrom` or `TryInto`.
    let _error = Pokemon::try_from(eevee_builder).expect_err("name was not provided");
  • ⚠🎉 (server, smithy-rs#1620, smithy-rs#1666, smithy-rs#1731, smithy-rs#1736, smithy-rs#1753, smithy-rs#1738, smithy-rs#1782, smithy-rs#1829, smithy-rs#1837, smithy-rs#1891, smithy-rs#1840, smithy-rs#1844, smithy-rs#1858, smithy-rs#1930, smithy-rs#1999, smithy-rs#2003, smithy-rs#2008, smithy-rs#2010, smithy-rs#2019, smithy-rs#2020, smithy-rs#2021, smithy-rs#2038, smithy-rs#2039, smithy-rs#2041)

    Plugins/New Service Builder API

    The Router struct has been replaced by a new Service located at the root of the generated crate. Its name coincides with the same name as the Smithy service you are generating.

    use pokemon_service_server_sdk::PokemonService;

    The new service builder infrastructure comes with a Plugin system which supports middleware on smithy-rs. See the mididleware documentation and the API documentation for more details.

    Usage of the new service builder API:

    // Apply a sequence of plugins using `PluginPipeline`.
    let plugins = PluginPipeline::new()
        // Apply the `PrintPlugin`.
        // This is a dummy plugin found in `rust-runtime/aws-smithy-http-server/examples/pokemon-service/src/plugin.rs`
        .print()
        // Apply the `InstrumentPlugin` plugin, which applies `tracing` instrumentation.
        .instrument();
    
    // Construct the service builder using the `plugins` defined above.
    let app = PokemonService::builder_with_plugins(plugins)
        // Assign all the handlers.
        .get_pokemon_species(get_pokemon_species)
        .get_storage(get_storage)
        .get_server_statistics(get_server_statistics)
        .capture_pokemon(capture_pokemon)
        .do_nothing(do_nothing)
        .check_health(check_health)
        // Construct the `PokemonService`.
        .build()
        // If handlers are missing a descriptive error will be provided.
        .expect("failed to build an instance of `PokemonService`");

    See the rust-runtime/aws-smithy-http-server/examples/pokemon-service/src/bin folder for various working examples.

    Public FromParts trait

    Previously, we only supported one Extension as an additional argument provided to the handler. This number has been increased to 8 and the argument type has been broadened to any struct which implements the FromParts trait. The trait is publicly exported and therefore provides customers with the ability to extend the domain of the handlers.

    As noted, a ubiqutious example of a struct that implements FromParts is the Extension struct, which extracts state from the Extensions typemap of a http::Request. A new example is the ConnectInfo struct which allows handlers to access the connection data. See the rust-runtime/aws-smithy-http-server/examples/pokemon-service/src/bin/pokemon-service-connect-info.rs example.

    fn get_pokemon_species(
        input: GetPokemonSpeciesInput,
        state: Extension<State>,
        address: ConnectInfo<SocketAddr>
    ) -> Result<GetPokemonSpeciesOutput, GetPokemonSpeciesError> {
        todo!()
    }

    In addition to the ConnectInfo extractor, we also have added lambda extractors which are feature gated with aws-lambda.

    FromParts documentation has been added.

    New Documentation

    New sections to have been added to the server side of the book.

    These include:

    This release also introduces extensive documentation at the root of the generated crate. For best results compile documentation with cargo +nightly doc --open.

    Deprecations

    The existing service builder infrastructure, OperationRegistryBuilder/OperationRegistry/Router, is now deprecated. Customers should migrate to the newer scheme described above. The deprecated types will be removed in a future release.

  • ⚠ (client, smithy-rs#1875) Replace bool with enum for a function parameter of label::fmt_string.

  • ⚠ (all, smithy-rs#1980) aws_smithy_types_convert::date_time::DateTimeExt::to_chrono_utc returns a Result<>

  • ⚠ (client, smithy-rs#1926, smithy-rs#1819) Several breaking changes have been made to errors. See the upgrade guide for more information.

  • 🐛⚠ (server, smithy-rs#1714, smithy-rs#1342, smithy-rs#1860) Server SDKs now correctly reject operation inputs that don't set values for required structure members. Previously, in some scenarios, server SDKs would accept the request and set a default value for the member (e.g. "" for a String), even when the member shape did not have Smithy IDL v2's default trait attached. The default trait is still unsupported.

  • ⚠ (client, smithy-rs#1945) Generate enums that guide the users to write match expressions in a forward-compatible way.
    Before this change, users could write a match expression against an enum in a non-forward-compatible way:

    match some_enum {
        SomeEnum::Variant1 => { /* ... */ },
        SomeEnum::Variant2 => { /* ... */ },
        Unknown(value) if value == "NewVariant" => { /* ... */ },
        _ => { /* ... */ },
    }

    This code can handle a case for "NewVariant" with a version of SDK where the enum does not yet include SomeEnum::NewVariant, but breaks with another version of SDK where the enum defines SomeEnum::NewVariant because the execution will hit a different match arm, i.e. the last one.
    After this change, users are guided to write the above match expression as follows:

    match some_enum {
        SomeEnum::Variant1 => { /* ... */ },
        SomeEnum::Variant2 => { /* ... */ },
        other @ _ if other.as_str() == "NewVariant" => { /* ... */ },
        _ => { /* ... */ },
    }

    This is forward-compatible because the execution will hit the second last match arm regardless of whether the enum defines SomeEnum::NewVariant or not.

  • ⚠ (client, smithy-rs#1984, smithy-rs#1496) Functions on aws_smithy_http::endpoint::Endpoint now return a Result instead of panicking.

  • ⚠ (client, smithy-rs#1984, smithy-rs#1496) Endpoint::mutable now takes impl AsRef<str> instead of Uri. For the old functionality, use Endpoint::mutable_uri.

  • ⚠ (client, smithy-rs#1984, smithy-rs#1496) Endpoint::immutable now takes impl AsRef<str> instead of Uri. For the old functionality, use Endpoint::immutable_uri.

  • ⚠ (server, smithy-rs#1982) RestJson1 server SDKs now serialize the full shape ID (including namespace) in operation error responses.

    Example server error response before:

    HTTP/1.1 400 Bad Request
    content-type: application/json
    x-amzn-errortype: InvalidRequestException
    ...
    

    Example server error response now:

    HTTP/1.1 400 Bad Request
    content-type: application/json
    x-amzn-errortype: com.example.service#InvalidRequestException
    ...
    
  • ⚠ (server, smithy-rs#2035) All types that are exclusively relevant within the context of an AWS Lambda function are now gated behind the
    aws-lambda feature flag.

    This will reduce the number of dependencies (and improve build times) for users that are running their Smithy services
    in non-serverless environments (e.g. via hyper).

  • ⚠ (all, smithy-rs#1983, smithy-rs#2029) Implementation of the Debug trait for container shapes now redacts what is printed per the sensitive trait.

  • ⚠ (client, smithy-rs#2065) SdkBody callbacks have been removed. If you were using these, please file an issue so that we can better understand your use-case and provide the support you need.

  • ⚠ (client, smithy-rs#2063) Added SmithyEndpointStage which can be used to set an endpoint for smithy-native clients

  • ⚠ (all, smithy-rs#1989) The Unit type for a Union member is no longer rendered. The serializers and parsers generated now function accordingly in the absence of the inner data associated with the Unit type.

New this release:

  • 🎉 (all, smithy-rs#1929) Upgrade Smithy to v1.26
  • 🎉 (client, smithy-rs#2044, smithy-rs#371) Fixed and improved the request tracing span hierarchy to improve log messages, profiling, and debuggability.
  • 🐛 (all, smithy-rs#1847) Support Sigv4 signature generation on PowerPC 32 and 64 bit. This architecture cannot compile ring, so the implementation has been updated to rely on hamc + sha2 to achive the same result with broader platform compatibility and higher performance. We also updated the CI which is now running as many tests as possible against i686 and PowerPC 32 and 64 bit.
  • 🐛 (server, smithy-rs#1910) aws_smithy_http_server::routing::Router is exported from the crate root again. This reverts unintentional breakage that was introduced in aws-smithy-http-server v0.51.0 only.
  • 🐛 (client, smithy-rs#1903, smithy-rs#1902) Fix bug that can cause panics in paginators
  • (client, smithy-rs#1919) Operation metadata is now added to the property bag before sending requests allowing middlewares to behave
    differently depending on the operation being sent.
  • (all, smithy-rs#1907) Fix cargo audit issue on chrono.
  • 🐛 (client, smithy-rs#1957) It was previously possible to send requests without setting query parameters modeled as required. Doing this may cause a
    service to interpret a request incorrectly instead of just sending back a 400 error. Now, when an operation has query
    parameters that are marked as required, the omission of those query parameters will cause a BuildError, preventing the
    invalid operation from being sent.
  • (all, smithy-rs#1972) Upgrade to Smithy 1.26.2
  • (all, smithy-rs#2011, @lsr0) Make generated enum values() functions callable in const contexts.
  • (client, smithy-rs#2064, aws-sdk-rust#632) Clients now default max idle connections to 70 (previously unlimited) to reduce the likelihood of hitting max file handles in AWS Lambda.
  • (client, smithy-rs#2057, smithy-rs#371) Add more tracing events to signing and event streams

Contributors
Thank you for your contributions! ❤