Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

Better distinguish model and HTTP plugins #2827

Merged
merged 6 commits into from
Jul 4, 2023

Commits on Jul 3, 2023

  1. Better distinguish model and HTTP plugins

    So far, servers have tacitly worked with the notion that plugins come in
    two flavors: "HTTP plugins" and "model plugins":
    
    - A HTTP plugin acts on the HTTP request before it is deserialized, and
      acts on the HTTP response after it is serialized.
    - A model plugin acts on the modeled operation input after it is
      deserialized, and acts on the modeled operation output or the modeled
      operation error before it is serialized.
    
    However, this notion was never reified in the type system. Thus, users
    who pass in a model plugin where a HTTP plugin is expected or
    viceversa in several APIs:
    
    ```rust
    let pipeline = PluginPipeline::new().push(http_plugin).push(model_plugin);
    
    let app = SimpleService::builder_with_plugins(http_plugins, IdentityPlugin)
        .post_operation(handler)
        /* ... */
        .build()
        .unwrap();
    ```
    
    would get the typical Tower service compilation errors, which can get
    very confusing:
    
    ```
    error[E0631]: type mismatch in function arguments
      --> simple/rust-server-codegen/src/main.rs:47:6
       |
    15 | fn new_svc<S, Ext>(inner: S) -> model_plugin::PostOperationService<S, Ext> {
       | -------------------------------------------------------------------------- found signature defined here
    ...
    47 |     .post_operation(post_operation)
       |      ^^^^^^^^^^^^^^ expected due to this
       |
       = note: expected function signature `fn(Upgrade<RestJson1, (PostOperationInput, _), PostOperationService<aws_smithy_http_server::operation::IntoService<simple::operation_shape::PostOperation, _>, _>>) -> _`
                  found function signature `fn(aws_smithy_http_server::operation::IntoService<simple::operation_shape::PostOperation, _>) -> _`
       = note: required for `LayerFn<fn(aws_smithy_http_server::operation::IntoService<..., ...>) -> ... {new_svc::<..., ...>}>` to implement `Layer<Upgrade<RestJson1, (PostOperationInput, _), PostOperationService<aws_smithy_http_server::operation::IntoService<simple::operation_shape::PostOperation, _>, _>>>`
       = note: the full type name has been written to '/local/home/davidpz/workplace/smithy-ws/src/SmithyRsSource/target/debug/deps/simple-6577f9f79749ceb9.long-type-4938700695428041031.txt'
    ```
    
    This commit introduces the `HttpPlugin` and `ModelPlugin` marker traits,
    allowing plugins to be marked as an HTTP plugin, a model plugin, or
    both. It also removes the primary way of concatenating plugins,
    `PluginPipeline`, in favor of `HttpPlugins` and `ModelPlugins`, which
    eagerly check that whenever a plugin is `push`ed, it is of the expected
    type. The generated service type in the server SDKs'
    `builder_with_plugins` constructor now takes an `HttpPlugin` as its
    first parameter, and a `ModelPlugin` as its second parameter.
    
    I think this change perhaps goes counter to the generally accepted
    wisdom that trait bounds in Rust should be enforced "at the latest
    possible moment", that is, only when the behavior encoded in the trait
    implementation is relied upon in the code (citation needed).
    However, the result is that exposing the concepts of HTTP plugin and
    model plugin in the type system makes for code that is easier to reason
    about, and produces more helpful compiler error messages.
    
    Documentation about the plugin system has been expanded, particularly on
    how to implement model plugins.
    david-perez committed Jul 3, 2023
    Configuration menu
    Copy the full SHA
    f865317 View commit details
    Browse the repository at this point in the history
  2. Better changelog

    david-perez committed Jul 3, 2023
    Configuration menu
    Copy the full SHA
    a58ec48 View commit details
    Browse the repository at this point in the history
  3. fix cargo doc

    david-perez committed Jul 3, 2023
    Configuration menu
    Copy the full SHA
    8e1af65 View commit details
    Browse the repository at this point in the history
  4. fix mdbook

    david-perez committed Jul 3, 2023
    Configuration menu
    Copy the full SHA
    ff2aab6 View commit details
    Browse the repository at this point in the history

Commits on Jul 4, 2023

  1. HttpPlugin -> HttpMarker

    david-perez committed Jul 4, 2023
    Configuration menu
    Copy the full SHA
    6caec26 View commit details
    Browse the repository at this point in the history
  2. Configuration menu
    Copy the full SHA
    113802d View commit details
    Browse the repository at this point in the history