The AWS Middleware doc is quite good, so I just give an overview here.
The generation of an AWS API call has several steps:
The Application corresponds with the stack.
Stack Step | Description |
---|---|
Initialize | Prepares the input, and sets any default parameters as needed. |
Serialize | Serializes the input to a protocol format suitable for the target transport layer. |
Build | Attach additional metadata to the serialized input, such as HTTP Content-Length. |
Finalize | Final message preparation, including retries and authentication (SigV4 signing). |
Deserialize | Deserialize responses from the protocol format into a structured type or error. |
Inside the stack the request is transformed and generated.
Let`s go through them with an example:
Application code snippet:
parms := &lambda.GetFunctionInput{
FunctionName: aws.String("simple"),
}
resp, err := client.GetFunction(context.TODO(), parms)
Inside the library the following steps are called:
api_op_GetFunction.go
GetFunction
invokeOperation
api_client.go
invokeOperation
Smithy-go executes all steps from the stack above:
In Middleware-HandleMiddleware
func (s *Stack) HandleMiddleware(ctx context.Context, input interface{}, next Handler) (
output interface{}, metadata Metadata, err error,
) {
h := DecorateHandler(next,
s.Initialize,
s.Serialize,
s.Build,
s.Finalize,
s.Deserialize,
)
return h.Handle(ctx, input)
}
What we can do to manipulate the steps is to add functionality before or after these steps. An example would be to look kat the original XML
which S3 and EC2 are sending. Maybe you did not know that, because the stack transforms in for you.
Some date which is handled in the steps:
steps_initialize.go
Now the input has to be translated to what the API needs
middleware.SerializeInput
func (s *SerializeStep) HandleMiddleware(ctx context.Context, in interface{}, next Handler) (
Resolve service endpoint (“https://lambda.eu-central-1.amazonaws.com”)
Service Lambda
middleware.SerializeOutput
Lambda API (https://docs.aws.amazon.com/lambda/latest/dg/API_GetFunction.html)
Request Syntax
GET /2015-03-31/functions/FunctionName?Qualifier=Qualifier HTTP/1.1
Request Method: Get Host: “lambda.eu-central-1.amazonaws.com” Path “/2015-03-31/functions/simple”
Middleware
step_build.go
func (s *BuildStep) HandleMiddleware(ctx context.Context, in interface{}, next Handler) (
const invocationIDHeader = "Amz-Sdk-Invocation-Id"
// HandleBuild compute the payload hash for the request payload ctx = SetPayloadHash(ctx, hex.EncodeToString(hash.Sum(nil)))
step_finalize.go
func (s *FinalizeStep) HandleMiddleware(ctx context.Context, in interface{}, next Handler) (
// Record the metadata for the for attempt being started. // HandleFinalize attaches the SDK request metric header to the transport layer get credentials signthttp
Call api HandleDeserialize
middleware `steps_deserialize.go`` Response status 200 ok
Response data as interface
Only Lambda knows how to do that => SDK go v2 lambda -> serializer.go
result, metadata, err := c.invokeOperation(ctx, "GetFunction", params, optFns, c.addOperationGetFunctionMiddlewares)
if err != nil {
return nil, err
}
out := result.(*GetFunctionOutput)