- Notifications
You must be signed in to change notification settings - Fork 733
Description
As an SDK developer, the middleware API is a fantastic abstraction for building composable API operations.
As an SDK user, the middleware API is a fantastic abstraction for confusing yourself or otherwise breaking your application when trying to do something as simple as adding an HTTP header:
- The interfaces are transport-agnostic, despite the fact that every single AWS service released today is over HTTP. This means that every single middleware implementation in the SDK has to implement the ubiquitous "is this an HTTP request" check that can literally never fail:
-
req, ok := in.Request.(*smithyhttp.Request) if !ok { return out, md, fmt.Errorf("this literally cannot ever happen") }
-
- Function decoration behavior of middleware is confusing and bloats / obfuscates stack traces in error logs
- The stack construct we use for adding middleware also supports an "insert" feature where you can insert a middleware to be executed relative to another in a specific phase. But if you attempt to insert against a middleware that doesn't exist, an error is returned. This is essentially pushing a failure point that should really exist at compile time into the runtime.
We propose a new mechanism known as "Interceptors" which provides a more streamlined API for SDK users to customize request behavior.
Interceptors are transport-typed hooks which a customer can write to insert behavior at well-defined points in an operation's lifecycle. For example:
type ModifyBeforeSendInterceptor interface { ModifyBeforeSend(ctx context.Context, r *smithyhttp.Request, in any) error } // usage type attachHeader struct { h, v string } func (i attachHeader) ModifyBeforeSend(ctx context.Context, r *smithyhttp.Request, in any) error { r.Header.Set(h, v) return nil } svc := sts.NewFromConfig(cfg, func(o *sts.Options)) { o.Interceptors.ModifyBeforeSend.Add(attachHeader{"foo", "bar"}) }To be clear, this does not replace middleware as an abstraction. It simply provides what we believe is a much more customer-friendly alternative for performing the day-to-day request manipulation that our users often require.