This commit is contained in:
2026-02-19 10:07:43 +00:00
parent 007438e372
commit 6e637ecf77
1763 changed files with 60820 additions and 279516 deletions

View File

@@ -1,3 +1,72 @@
# Release (2025-12-01)
## General Highlights
* **Dependency Update**: Updated to the latest SDK module versions
## Module Highlights
* `github.com/aws/smithy-go`: v1.24.0
* **Feature**: Improve allocation footprint of the middleware stack. This should convey a ~10% reduction in allocations per SDK request.
# Release (2025-11-03)
## General Highlights
* **Dependency Update**: Updated to the latest SDK module versions
## Module Highlights
* `github.com/aws/smithy-go`: v1.23.2
* **Bug Fix**: Adjust the initial sizes of each middleware phase to avoid some unnecessary reallocation.
* **Bug Fix**: Avoid unnecessary allocation overhead from the metrics system when not in use.
# Release (2025-10-15)
## General Highlights
* **Dependency Update**: Bump minimum go version to 1.23.
* **Dependency Update**: Updated to the latest SDK module versions
# Release (2025-09-18)
## Module Highlights
* `github.com/aws/smithy-go/aws-http-auth`: [v1.1.0](aws-http-auth/CHANGELOG.md#v110-2025-09-18)
* **Feature**: Added support for SIG4/SIGV4A querystring authentication.
# Release (2025-08-27)
## General Highlights
* **Dependency Update**: Updated to the latest SDK module versions
## Module Highlights
* `github.com/aws/smithy-go`: v1.23.0
* **Feature**: Sort map keys in JSON Document types.
# Release (2025-07-24)
## General Highlights
* **Dependency Update**: Updated to the latest SDK module versions
## Module Highlights
* `github.com/aws/smithy-go`: v1.22.5
* **Feature**: Add HTTP interceptors.
# Release (2025-06-16)
## General Highlights
* **Dependency Update**: Updated to the latest SDK module versions
## Module Highlights
* `github.com/aws/smithy-go`: v1.22.4
* **Bug Fix**: Fix CBOR serd empty check for string and enum fields
* **Bug Fix**: Fix HTTP metrics data race.
* **Bug Fix**: Replace usages of deprecated ioutil package.
# Release (2025-02-17)
## General Highlights
* **Dependency Update**: Updated to the latest SDK module versions
## Module Highlights
* `github.com/aws/smithy-go`: v1.22.3
* **Dependency Update**: Bump minimum Go version to 1.22 per our language support policy.
# Release (2025-01-21)
## General Highlights

View File

@@ -13,6 +13,7 @@ REPOTOOLS_CMD_GENERATE_CHANGELOG = ${REPOTOOLS_MODULE}/cmd/generatechangelog@${R
REPOTOOLS_CMD_CHANGELOG = ${REPOTOOLS_MODULE}/cmd/changelog@${REPOTOOLS_VERSION}
REPOTOOLS_CMD_TAG_RELEASE = ${REPOTOOLS_MODULE}/cmd/tagrelease@${REPOTOOLS_VERSION}
REPOTOOLS_CMD_MODULE_VERSION = ${REPOTOOLS_MODULE}/cmd/moduleversion@${REPOTOOLS_VERSION}
REPOTOOLS_CMD_EACHMODULE = ${REPOTOOLS_MODULE}/cmd/eachmodule@${REPOTOOLS_VERSION}
UNIT_TEST_TAGS=
BUILD_TAGS=
@@ -30,6 +31,24 @@ smithy-build:
smithy-clean:
cd codegen && ./gradlew clean
GRADLE_RETRIES := 3
GRADLE_SLEEP := 2
# We're making a call to ./gradlew to trigger downloading Gradle and
# starting the daemon. Any call works, so using `./gradlew help`
ensure-gradle-up:
@cd codegen && for i in $(shell seq 1 $(GRADLE_RETRIES)); do \
echo "Checking if Gradle daemon is up, attempt $$i..."; \
if ./gradlew help; then \
echo "Gradle daemon is up!"; \
exit 0; \
fi; \
echo "Failed to start Gradle, retrying in $(GRADLE_SLEEP) seconds..."; \
sleep $(GRADLE_SLEEP); \
done; \
echo "Failed to start Gradle after $(GRADLE_RETRIES) attempts."; \
exit 1
##################
# Linting/Verify #
##################
@@ -37,8 +56,11 @@ smithy-clean:
verify: vet
vet:
go vet ${BUILD_TAGS} --all ./...
vet: vet-modules-.
vet-modules-%:
go run ${REPOTOOLS_CMD_EACHMODULE} -p $(subst vet-modules-,,$@) \
"go vet ${BUILD_TAGS} --all ./..."
cover:
go test ${BUILD_TAGS} -coverprofile c.out ./...
@@ -48,23 +70,22 @@ cover:
################
# Unit Testing #
################
.PHONY: unit unit-race unit-test unit-race-test
.PHONY: test unit unit-race
unit: verify
go vet ${BUILD_TAGS} --all ./... && \
go test ${BUILD_TAGS} ${RUN_NONE} ./... && \
go test -timeout=1m ${UNIT_TEST_TAGS} ./...
test: unit-race
unit-race: verify
go vet ${BUILD_TAGS} --all ./... && \
go test ${BUILD_TAGS} ${RUN_NONE} ./... && \
go test -timeout=1m ${UNIT_TEST_TAGS} -race -cpu=4 ./...
unit: verify unit-modules-.
unit-test: verify
go test -timeout=1m ${UNIT_TEST_TAGS} ./...
unit-modules-%:
go run ${REPOTOOLS_CMD_EACHMODULE} -p $(subst unit-modules-,,$@) \
"go test -timeout=1m ${UNIT_TEST_TAGS} ./..."
unit-race: verify unit-race-modules-.
unit-race-modules-%:
go run ${REPOTOOLS_CMD_EACHMODULE} -p $(subst unit-race-modules-,,$@) \
"go test -timeout=1m ${UNIT_TEST_TAGS} -race -cpu=4 ./..."
unit-race-test: verify
go test -timeout=1m ${UNIT_TEST_TAGS} -race -cpu=4 ./...
#####################
# Release Process #

View File

@@ -4,19 +4,21 @@
[Smithy](https://smithy.io/) code generators for Go and the accompanying smithy-go runtime.
The smithy-go runtime requires a minimum version of Go 1.20.
The smithy-go runtime requires a minimum version of Go 1.23.
**WARNING: All interfaces are subject to change.**
## Can I use the code generators?
## :no_entry_sign: DO NOT use the code generators in this repository
**The code generators in this repository do not generate working clients at
this time.**
In order to generate a usable smithy client you must provide a [protocol definition](https://github.com/aws/smithy-go/blob/main/codegen/smithy-go-codegen/src/main/java/software/amazon/smithy/go/codegen/integration/ProtocolGenerator.java),
such as [AWS restJson1](https://smithy.io/2.0/aws/protocols/aws-restjson1-protocol.html),
in order to generate transport mechanisms and serialization/deserialization
code ("serde") accordingly.
The code generator does not currently support any protocols out of the box other than the new `smithy.protocols#rpcv2Cbor`,
therefore the useability of this project on its own is currently limited.
The code generator does not currently support any protocols out of the box.
Support for all [AWS protocols](https://smithy.io/2.0/aws/protocols/index.html)
exists in [aws-sdk-go-v2](https://github.com/aws/aws-sdk-go-v2). We are
tracking the movement of those out of the SDK into smithy-go in
@@ -31,6 +33,7 @@ This repository implements the following Smithy build plugins:
|----|------------|-------------|
| `go-codegen` | `software.amazon.smithy.go:smithy-go-codegen` | Implements Go client code generation for Smithy models. |
| `go-server-codegen` | `software.amazon.smithy.go:smithy-go-codegen` | Implements Go server code generation for Smithy models. |
| `go-shape-codegen` | `software.amazon.smithy.go:smithy-go-codegen` | Implements Go shape code generation (types only) for Smithy models. |
**NOTE: Build plugins are not currently published to mavenCentral. You must publish to mavenLocal to make the build plugins visible to the Smithy CLI. The artifact version is currently fixed at 0.1.0.**
@@ -77,7 +80,7 @@ example created from `smithy init`:
"service": "example.weather#Weather",
"module": "github.com/example/weather",
"generateGoMod": true,
"goDirective": "1.20"
"goDirective": "1.23"
}
}
}
@@ -87,6 +90,10 @@ example created from `smithy init`:
This plugin is a work-in-progress and is currently undocumented.
## `go-shape-codegen`
This plugin is a work-in-progress and is currently undocumented.
## License
This project is licensed under the Apache-2.0 License.

View File

@@ -9,7 +9,7 @@ import (
// Endpoint is the endpoint object returned by Endpoint resolution V2
type Endpoint struct {
// The complete URL minimally specfiying the scheme and host.
// The complete URL minimally specifying the scheme and host.
// May optionally specify the port and base path component.
URI url.URL

View File

@@ -0,0 +1,4 @@
// Package rulesfn provides endpoint rule functions for evaluating endpoint
// resolution rules.
package rulesfn

View File

@@ -0,0 +1,25 @@
package rulesfn
// Substring returns the substring of the input provided. If the start or stop
// indexes are not valid for the input nil will be returned. If errors occur
// they will be added to the provided [ErrorCollector].
func SubString(input string, start, stop int, reverse bool) *string {
if start < 0 || stop < 1 || start >= stop || len(input) < stop {
return nil
}
for _, r := range input {
if r > 127 {
return nil
}
}
if !reverse {
v := input[start:stop]
return &v
}
rStart := len(input) - stop
rStop := len(input) - start
return SubString(input, rStart, rStop, false)
}

View File

@@ -0,0 +1,130 @@
package rulesfn
import (
"fmt"
"net"
"net/url"
"strings"
smithyhttp "github.com/aws/smithy-go/transport/http"
)
// IsValidHostLabel returns if the input is a single valid [RFC 1123] host
// label. If allowSubDomains is true, will allow validation to include nested
// host labels. Returns false if the input is not a valid host label. If errors
// occur they will be added to the provided [ErrorCollector].
//
// [RFC 1123]: https://www.ietf.org/rfc/rfc1123.txt
func IsValidHostLabel(input string, allowSubDomains bool) bool {
var labels []string
if allowSubDomains {
labels = strings.Split(input, ".")
} else {
labels = []string{input}
}
for _, label := range labels {
if !smithyhttp.ValidHostLabel(label) {
return false
}
}
return true
}
// ParseURL returns a [URL] if the provided string could be parsed. Returns nil
// if the string could not be parsed. Any parsing error will be added to the
// [ErrorCollector].
//
// If the input URL string contains an IP6 address with a zone index. The
// returned [builtin.URL.Authority] value will contain the percent escaped (%)
// zone index separator.
func ParseURL(input string) *URL {
u, err := url.Parse(input)
if err != nil {
return nil
}
if u.RawQuery != "" {
return nil
}
if u.Scheme != "http" && u.Scheme != "https" {
return nil
}
normalizedPath := u.Path
if !strings.HasPrefix(normalizedPath, "/") {
normalizedPath = "/" + normalizedPath
}
if !strings.HasSuffix(normalizedPath, "/") {
normalizedPath = normalizedPath + "/"
}
// IP6 hosts may have zone indexes that need to be escaped to be valid in a
// URI. The Go URL parser will unescape the `%25` into `%`. This needs to
// be reverted since the returned URL will be used in string builders.
authority := strings.ReplaceAll(u.Host, "%", "%25")
return &URL{
Scheme: u.Scheme,
Authority: authority,
Path: u.Path,
NormalizedPath: normalizedPath,
IsIp: net.ParseIP(hostnameWithoutZone(u)) != nil,
}
}
// URL provides the structure describing the parts of a parsed URL returned by
// [ParseURL].
type URL struct {
Scheme string // https://www.rfc-editor.org/rfc/rfc3986#section-3.1
Authority string // https://www.rfc-editor.org/rfc/rfc3986#section-3.2
Path string // https://www.rfc-editor.org/rfc/rfc3986#section-3.3
NormalizedPath string // https://www.rfc-editor.org/rfc/rfc3986#section-6.2.3
IsIp bool
}
// URIEncode returns an percent-encoded [RFC3986 section 2.1] version of the
// input string.
//
// [RFC3986 section 2.1]: https://www.rfc-editor.org/rfc/rfc3986#section-2.1
func URIEncode(input string) string {
var output strings.Builder
for _, c := range []byte(input) {
if validPercentEncodedChar(c) {
output.WriteByte(c)
continue
}
fmt.Fprintf(&output, "%%%X", c)
}
return output.String()
}
func validPercentEncodedChar(c byte) bool {
return (c >= 'a' && c <= 'z') ||
(c >= 'A' && c <= 'Z') ||
(c >= '0' && c <= '9') ||
c == '-' || c == '_' || c == '.' || c == '~'
}
// hostname implements u.Hostname() but strips the ipv6 zone ID (if present)
// such that net.ParseIP can still recognize IPv6 addresses with zone IDs.
//
// FUTURE(10/2023): netip.ParseAddr handles this natively but we can't take
// that package as a dependency yet due to our min go version (1.15, netip
// starts in 1.18). When we align with go runtime deprecation policy in
// 10/2023, we can remove this.
func hostnameWithoutZone(u *url.URL) string {
full := u.Hostname()
// this more or less mimics the internals of net/ (see unexported
// splitHostZone in that source) but throws the zone away because we don't
// need it
if i := strings.LastIndex(full, "%"); i > -1 {
return full[:i]
}
return full
}

View File

@@ -3,4 +3,4 @@
package smithy
// goModuleVersion is the tagged release for this module
const goModuleVersion = "1.22.2"
const goModuleVersion = "1.24.0"

View File

@@ -9,54 +9,82 @@ var _ MeterProvider = (*NopMeterProvider)(nil)
// Meter returns a meter which creates no-op instruments.
func (NopMeterProvider) Meter(string, ...MeterOption) Meter {
return nopMeter{}
return NopMeter{}
}
type nopMeter struct{}
// NopMeter creates no-op instruments.
type NopMeter struct{}
var _ Meter = (*nopMeter)(nil)
var _ Meter = (*NopMeter)(nil)
func (nopMeter) Int64Counter(string, ...InstrumentOption) (Int64Counter, error) {
return nopInstrument[int64]{}, nil
// Int64Counter creates a no-op instrument.
func (NopMeter) Int64Counter(string, ...InstrumentOption) (Int64Counter, error) {
return nopInstrumentInt64, nil
}
func (nopMeter) Int64UpDownCounter(string, ...InstrumentOption) (Int64UpDownCounter, error) {
return nopInstrument[int64]{}, nil
// Int64UpDownCounter creates a no-op instrument.
func (NopMeter) Int64UpDownCounter(string, ...InstrumentOption) (Int64UpDownCounter, error) {
return nopInstrumentInt64, nil
}
func (nopMeter) Int64Gauge(string, ...InstrumentOption) (Int64Gauge, error) {
return nopInstrument[int64]{}, nil
// Int64Gauge creates a no-op instrument.
func (NopMeter) Int64Gauge(string, ...InstrumentOption) (Int64Gauge, error) {
return nopInstrumentInt64, nil
}
func (nopMeter) Int64Histogram(string, ...InstrumentOption) (Int64Histogram, error) {
return nopInstrument[int64]{}, nil
// Int64Histogram creates a no-op instrument.
func (NopMeter) Int64Histogram(string, ...InstrumentOption) (Int64Histogram, error) {
return nopInstrumentInt64, nil
}
func (nopMeter) Int64AsyncCounter(string, Int64Callback, ...InstrumentOption) (AsyncInstrument, error) {
return nopInstrument[int64]{}, nil
// Int64AsyncCounter creates a no-op instrument.
func (NopMeter) Int64AsyncCounter(string, Int64Callback, ...InstrumentOption) (AsyncInstrument, error) {
return nopInstrumentInt64, nil
}
func (nopMeter) Int64AsyncUpDownCounter(string, Int64Callback, ...InstrumentOption) (AsyncInstrument, error) {
return nopInstrument[int64]{}, nil
// Int64AsyncUpDownCounter creates a no-op instrument.
func (NopMeter) Int64AsyncUpDownCounter(string, Int64Callback, ...InstrumentOption) (AsyncInstrument, error) {
return nopInstrumentInt64, nil
}
func (nopMeter) Int64AsyncGauge(string, Int64Callback, ...InstrumentOption) (AsyncInstrument, error) {
return nopInstrument[int64]{}, nil
// Int64AsyncGauge creates a no-op instrument.
func (NopMeter) Int64AsyncGauge(string, Int64Callback, ...InstrumentOption) (AsyncInstrument, error) {
return nopInstrumentInt64, nil
}
func (nopMeter) Float64Counter(string, ...InstrumentOption) (Float64Counter, error) {
return nopInstrument[float64]{}, nil
// Float64Counter creates a no-op instrument.
func (NopMeter) Float64Counter(string, ...InstrumentOption) (Float64Counter, error) {
return nopInstrumentFloat64, nil
}
func (nopMeter) Float64UpDownCounter(string, ...InstrumentOption) (Float64UpDownCounter, error) {
return nopInstrument[float64]{}, nil
// Float64UpDownCounter creates a no-op instrument.
func (NopMeter) Float64UpDownCounter(string, ...InstrumentOption) (Float64UpDownCounter, error) {
return nopInstrumentFloat64, nil
}
func (nopMeter) Float64Gauge(string, ...InstrumentOption) (Float64Gauge, error) {
return nopInstrument[float64]{}, nil
// Float64Gauge creates a no-op instrument.
func (NopMeter) Float64Gauge(string, ...InstrumentOption) (Float64Gauge, error) {
return nopInstrumentFloat64, nil
}
func (nopMeter) Float64Histogram(string, ...InstrumentOption) (Float64Histogram, error) {
return nopInstrument[float64]{}, nil
// Float64Histogram creates a no-op instrument.
func (NopMeter) Float64Histogram(string, ...InstrumentOption) (Float64Histogram, error) {
return nopInstrumentFloat64, nil
}
func (nopMeter) Float64AsyncCounter(string, Float64Callback, ...InstrumentOption) (AsyncInstrument, error) {
return nopInstrument[float64]{}, nil
// Float64AsyncCounter creates a no-op instrument.
func (NopMeter) Float64AsyncCounter(string, Float64Callback, ...InstrumentOption) (AsyncInstrument, error) {
return nopInstrumentFloat64, nil
}
func (nopMeter) Float64AsyncUpDownCounter(string, Float64Callback, ...InstrumentOption) (AsyncInstrument, error) {
return nopInstrument[float64]{}, nil
// Float64AsyncUpDownCounter creates a no-op instrument.
func (NopMeter) Float64AsyncUpDownCounter(string, Float64Callback, ...InstrumentOption) (AsyncInstrument, error) {
return nopInstrumentFloat64, nil
}
func (nopMeter) Float64AsyncGauge(string, Float64Callback, ...InstrumentOption) (AsyncInstrument, error) {
return nopInstrument[float64]{}, nil
// Float64AsyncGauge creates a no-op instrument.
func (NopMeter) Float64AsyncGauge(string, Float64Callback, ...InstrumentOption) (AsyncInstrument, error) {
return nopInstrumentFloat64, nil
}
type nopInstrument[N any] struct{}
@@ -65,3 +93,6 @@ func (nopInstrument[N]) Add(context.Context, N, ...RecordMetricOption) {}
func (nopInstrument[N]) Sample(context.Context, N, ...RecordMetricOption) {}
func (nopInstrument[N]) Record(context.Context, N, ...RecordMetricOption) {}
func (nopInstrument[_]) Stop() {}
var nopInstrumentInt64 = nopInstrument[int64]{}
var nopInstrumentFloat64 = nopInstrument[float64]{}

View File

@@ -23,12 +23,14 @@ type orderedIDs struct {
items map[string]ider
}
const baseOrderedItems = 5
// selected based on the general upper bound of # of middlewares in each step
// in the downstream aws-sdk-go-v2
const baseOrderedItems = 8
func newOrderedIDs() *orderedIDs {
func newOrderedIDs(cap int) *orderedIDs {
return &orderedIDs{
order: newRelativeOrder(),
items: make(map[string]ider, baseOrderedItems),
order: newRelativeOrder(cap),
items: make(map[string]ider, cap),
}
}
@@ -141,9 +143,9 @@ type relativeOrder struct {
order []string
}
func newRelativeOrder() *relativeOrder {
func newRelativeOrder(cap int) *relativeOrder {
return &relativeOrder{
order: make([]string, 0, baseOrderedItems),
order: make([]string, 0, cap),
}
}

View File

@@ -1,7 +1,9 @@
// Code generated by smithy-go/middleware/generate.go DO NOT EDIT.
package middleware
import (
"context"
"fmt"
)
// BuildInput provides the input parameters for the BuildMiddleware to consume.
@@ -25,14 +27,14 @@ type BuildHandler interface {
}
// BuildMiddleware provides the interface for middleware specific to the
// serialize step. Delegates to the next BuildHandler for further
// build step. Delegates to the next BuildHandler for further
// processing.
type BuildMiddleware interface {
// Unique ID for the middleware in theBuildStep. The step does not allow
// duplicate IDs.
// ID returns a unique ID for the middleware in the BuildStep. The step does not
// allow duplicate IDs.
ID() string
// Invokes the middleware behavior which must delegate to the next handler
// HandleBuild invokes the middleware behavior which must delegate to the next handler
// for the middleware chain to continue. The method must return a result or
// error to its caller.
HandleBuild(ctx context.Context, in BuildInput, next BuildHandler) (
@@ -54,7 +56,9 @@ type buildMiddlewareFunc struct {
id string
// Middleware function to be called.
fn func(context.Context, BuildInput, BuildHandler) (BuildOutput, Metadata, error)
fn func(context.Context, BuildInput, BuildHandler) (
BuildOutput, Metadata, error,
)
}
// ID returns the unique ID for the middleware.
@@ -69,23 +73,22 @@ func (s buildMiddlewareFunc) HandleBuild(ctx context.Context, in BuildInput, nex
var _ BuildMiddleware = (buildMiddlewareFunc{})
// BuildStep provides the ordered grouping of BuildMiddleware to be invoked on
// a handler.
// BuildStep provides the ordered grouping of BuildMiddleware to be
// invoked on a handler.
type BuildStep struct {
ids *orderedIDs
head *decoratedBuildHandler
tail *decoratedBuildHandler
}
// NewBuildStep returns a BuildStep ready to have middleware for
// initialization added to it.
// NewBuildStep returns an BuildStep ready to have middleware for
// build added to it.
func NewBuildStep() *BuildStep {
return &BuildStep{
ids: newOrderedIDs(),
}
return &BuildStep{}
}
var _ Middleware = (*BuildStep)(nil)
// ID returns the unique name of the step as a middleware.
// ID returns the unique ID of the step as a middleware.
func (s *BuildStep) ID() string {
return "Build stack step"
}
@@ -97,77 +100,161 @@ func (s *BuildStep) ID() string {
func (s *BuildStep) HandleMiddleware(ctx context.Context, in interface{}, next Handler) (
out interface{}, metadata Metadata, err error,
) {
order := s.ids.GetOrder()
var h BuildHandler = buildWrapHandler{Next: next}
for i := len(order) - 1; i >= 0; i-- {
h = decoratedBuildHandler{
Next: h,
With: order[i].(BuildMiddleware),
}
}
sIn := BuildInput{
Request: in,
}
res, metadata, err := h.HandleBuild(ctx, sIn)
wh := &buildWrapHandler{next}
if s.head == nil {
res, metadata, err := wh.HandleBuild(ctx, sIn)
return res.Result, metadata, err
}
s.tail.Next = wh
res, metadata, err := s.head.HandleBuild(ctx, sIn)
return res.Result, metadata, err
}
// Get retrieves the middleware identified by id. If the middleware is not present, returns false.
func (s *BuildStep) Get(id string) (BuildMiddleware, bool) {
get, ok := s.ids.Get(id)
if !ok {
found, _ := s.get(id)
if found == nil {
return nil, false
}
return get.(BuildMiddleware), ok
return found.With, true
}
// Add injects the middleware to the relative position of the middleware group.
// Returns an error if the middleware already exists.
//
// Add never returns an error. It used to for duplicate phases but this
// behavior has since been removed as part of a performance optimization. The
// return value from Add can be ignored.
func (s *BuildStep) Add(m BuildMiddleware, pos RelativePosition) error {
return s.ids.Add(m, pos)
if s.head == nil {
s.head = &decoratedBuildHandler{nil, m}
s.tail = s.head
return nil
}
if pos == Before {
s.head = &decoratedBuildHandler{s.head, m}
} else {
tail := &decoratedBuildHandler{nil, m}
s.tail.Next = tail
s.tail = tail
}
return nil
}
// Insert injects the middleware relative to an existing middleware id.
// Returns an error if the original middleware does not exist, or the middleware
// Insert injects the middleware relative to an existing middleware ID.
// Returns error if the original middleware does not exist, or the middleware
// being added already exists.
func (s *BuildStep) Insert(m BuildMiddleware, relativeTo string, pos RelativePosition) error {
return s.ids.Insert(m, relativeTo, pos)
found, prev := s.get(relativeTo)
if found == nil {
return fmt.Errorf("not found: %s", m.ID())
}
if pos == Before {
if prev == nil { // at the front
s.head = &decoratedBuildHandler{s.head, m}
} else { // somewhere in the middle
prev.Next = &decoratedBuildHandler{found, m}
}
} else {
if found.Next == nil { // at the end
tail := &decoratedBuildHandler{nil, m}
s.tail.Next = tail
s.tail = tail
} else { // somewhere in the middle
found.Next = &decoratedBuildHandler{found.Next, m}
}
}
return nil
}
// Swap removes the middleware by id, replacing it with the new middleware.
// Returns the middleware removed, or an error if the middleware to be removed
// Returns the middleware removed, or error if the middleware to be removed
// doesn't exist.
func (s *BuildStep) Swap(id string, m BuildMiddleware) (BuildMiddleware, error) {
removed, err := s.ids.Swap(id, m)
if err != nil {
return nil, err
found, _ := s.get(id)
if found == nil {
return nil, fmt.Errorf("not found: %s", m.ID())
}
return removed.(BuildMiddleware), nil
swapped := found.With
found.With = m
return swapped, nil
}
// Remove removes the middleware by id. Returns error if the middleware
// doesn't exist.
func (s *BuildStep) Remove(id string) (BuildMiddleware, error) {
removed, err := s.ids.Remove(id)
if err != nil {
return nil, err
found, prev := s.get(id)
if found == nil {
return nil, fmt.Errorf("not found: %s", id)
}
return removed.(BuildMiddleware), nil
if s.head == s.tail { // it's the only one
s.head = nil
s.tail = nil
} else if found == s.head { // at the front
s.head = s.head.Next.(*decoratedBuildHandler)
} else if found == s.tail { // at the end
prev.Next = nil
s.tail = prev
} else {
prev.Next = found.Next // somewhere in the middle
}
return found.With, nil
}
// List returns a list of the middleware in the step.
func (s *BuildStep) List() []string {
return s.ids.List()
var ids []string
for h := s.head; h != nil; {
ids = append(ids, h.With.ID())
if h.Next == nil {
break
}
// once executed, tail.Next of the list will be set to an
// *buildWrapHandler, make sure to check for that
if hnext, ok := h.Next.(*decoratedBuildHandler); ok {
h = hnext
} else {
break
}
}
return ids
}
// Clear removes all middleware in the step.
func (s *BuildStep) Clear() {
s.ids.Clear()
s.head = nil
s.tail = nil
}
func (s *BuildStep) get(id string) (found, prev *decoratedBuildHandler) {
for h := s.head; h != nil; {
if h.With.ID() == id {
found = h
return
}
prev = h
if h.Next == nil {
return
}
// once executed, tail.Next of the list will be set to an
// *buildWrapHandler
h, _ = h.Next.(*decoratedBuildHandler)
}
return
}
type buildWrapHandler struct {
@@ -176,7 +263,7 @@ type buildWrapHandler struct {
var _ BuildHandler = (*buildWrapHandler)(nil)
// Implements BuildHandler, converts types and delegates to underlying
// HandleBuild implements BuildHandler, converts types and delegates to underlying
// generic handler.
func (w buildWrapHandler) HandleBuild(ctx context.Context, in BuildInput) (
out BuildOutput, metadata Metadata, err error,
@@ -200,12 +287,12 @@ func (h decoratedBuildHandler) HandleBuild(ctx context.Context, in BuildInput) (
return h.With.HandleBuild(ctx, in, h.Next)
}
// BuildHandlerFunc provides a wrapper around a function to be used as a build middleware handler.
// BuildHandlerFunc provides a wrapper around a function to be used as buildMiddleware.
type BuildHandlerFunc func(context.Context, BuildInput) (BuildOutput, Metadata, error)
// HandleBuild invokes the wrapped function with the provided arguments.
func (b BuildHandlerFunc) HandleBuild(ctx context.Context, in BuildInput) (BuildOutput, Metadata, error) {
return b(ctx, in)
// HandleBuild calls the wrapped function with the provided arguments.
func (f BuildHandlerFunc) HandleBuild(ctx context.Context, in BuildInput) (BuildOutput, Metadata, error) {
return f(ctx, in)
}
var _ BuildHandler = BuildHandlerFunc(nil)

View File

@@ -1,7 +1,9 @@
// Code generated by smithy-go/middleware/generate.go DO NOT EDIT.
package middleware
import (
"context"
"fmt"
)
// DeserializeInput provides the input parameters for the DeserializeInput to
@@ -11,10 +13,7 @@ type DeserializeInput struct {
Request interface{}
}
// DeserializeOutput provides the result returned by the next
// DeserializeHandler. The DeserializeMiddleware should deserialize the
// RawResponse into a Result that can be consumed by middleware higher up in
// the stack.
// DeserializeOutput provides the result returned by the next DeserializeHandler.
type DeserializeOutput struct {
RawResponse interface{}
Result interface{}
@@ -29,7 +28,7 @@ type DeserializeHandler interface {
}
// DeserializeMiddleware provides the interface for middleware specific to the
// serialize step. Delegates to the next DeserializeHandler for further
// deserialize step. Delegates to the next DeserializeHandler for further
// processing.
type DeserializeMiddleware interface {
// ID returns a unique ID for the middleware in the DeserializeStep. The step does not
@@ -44,8 +43,8 @@ type DeserializeMiddleware interface {
)
}
// DeserializeMiddlewareFunc returns a DeserializeMiddleware with the unique ID
// provided, and the func to be invoked.
// DeserializeMiddlewareFunc returns a DeserializeMiddleware with the unique ID provided,
// and the func to be invoked.
func DeserializeMiddlewareFunc(id string, fn func(context.Context, DeserializeInput, DeserializeHandler) (DeserializeOutput, Metadata, error)) DeserializeMiddleware {
return deserializeMiddlewareFunc{
id: id,
@@ -78,15 +77,14 @@ var _ DeserializeMiddleware = (deserializeMiddlewareFunc{})
// DeserializeStep provides the ordered grouping of DeserializeMiddleware to be
// invoked on a handler.
type DeserializeStep struct {
ids *orderedIDs
head *decoratedDeserializeHandler
tail *decoratedDeserializeHandler
}
// NewDeserializeStep returns a DeserializeStep ready to have middleware for
// initialization added to it.
// NewDeserializeStep returns an DeserializeStep ready to have middleware for
// deserialize added to it.
func NewDeserializeStep() *DeserializeStep {
return &DeserializeStep{
ids: newOrderedIDs(),
}
return &DeserializeStep{}
}
var _ Middleware = (*DeserializeStep)(nil)
@@ -103,77 +101,161 @@ func (s *DeserializeStep) ID() string {
func (s *DeserializeStep) HandleMiddleware(ctx context.Context, in interface{}, next Handler) (
out interface{}, metadata Metadata, err error,
) {
order := s.ids.GetOrder()
var h DeserializeHandler = deserializeWrapHandler{Next: next}
for i := len(order) - 1; i >= 0; i-- {
h = decoratedDeserializeHandler{
Next: h,
With: order[i].(DeserializeMiddleware),
}
}
sIn := DeserializeInput{
Request: in,
}
res, metadata, err := h.HandleDeserialize(ctx, sIn)
wh := &deserializeWrapHandler{next}
if s.head == nil {
res, metadata, err := wh.HandleDeserialize(ctx, sIn)
return res.Result, metadata, err
}
s.tail.Next = wh
res, metadata, err := s.head.HandleDeserialize(ctx, sIn)
return res.Result, metadata, err
}
// Get retrieves the middleware identified by id. If the middleware is not present, returns false.
func (s *DeserializeStep) Get(id string) (DeserializeMiddleware, bool) {
get, ok := s.ids.Get(id)
if !ok {
found, _ := s.get(id)
if found == nil {
return nil, false
}
return get.(DeserializeMiddleware), ok
return found.With, true
}
// Add injects the middleware to the relative position of the middleware group.
// Returns an error if the middleware already exists.
//
// Add never returns an error. It used to for duplicate phases but this
// behavior has since been removed as part of a performance optimization. The
// return value from Add can be ignored.
func (s *DeserializeStep) Add(m DeserializeMiddleware, pos RelativePosition) error {
return s.ids.Add(m, pos)
if s.head == nil {
s.head = &decoratedDeserializeHandler{nil, m}
s.tail = s.head
return nil
}
if pos == Before {
s.head = &decoratedDeserializeHandler{s.head, m}
} else {
tail := &decoratedDeserializeHandler{nil, m}
s.tail.Next = tail
s.tail = tail
}
return nil
}
// Insert injects the middleware relative to an existing middleware ID.
// Returns error if the original middleware does not exist, or the middleware
// being added already exists.
func (s *DeserializeStep) Insert(m DeserializeMiddleware, relativeTo string, pos RelativePosition) error {
return s.ids.Insert(m, relativeTo, pos)
found, prev := s.get(relativeTo)
if found == nil {
return fmt.Errorf("not found: %s", m.ID())
}
if pos == Before {
if prev == nil { // at the front
s.head = &decoratedDeserializeHandler{s.head, m}
} else { // somewhere in the middle
prev.Next = &decoratedDeserializeHandler{found, m}
}
} else {
if found.Next == nil { // at the end
tail := &decoratedDeserializeHandler{nil, m}
s.tail.Next = tail
s.tail = tail
} else { // somewhere in the middle
found.Next = &decoratedDeserializeHandler{found.Next, m}
}
}
return nil
}
// Swap removes the middleware by id, replacing it with the new middleware.
// Returns the middleware removed, or error if the middleware to be removed
// doesn't exist.
func (s *DeserializeStep) Swap(id string, m DeserializeMiddleware) (DeserializeMiddleware, error) {
removed, err := s.ids.Swap(id, m)
if err != nil {
return nil, err
found, _ := s.get(id)
if found == nil {
return nil, fmt.Errorf("not found: %s", m.ID())
}
return removed.(DeserializeMiddleware), nil
swapped := found.With
found.With = m
return swapped, nil
}
// Remove removes the middleware by id. Returns error if the middleware
// doesn't exist.
func (s *DeserializeStep) Remove(id string) (DeserializeMiddleware, error) {
removed, err := s.ids.Remove(id)
if err != nil {
return nil, err
found, prev := s.get(id)
if found == nil {
return nil, fmt.Errorf("not found: %s", id)
}
return removed.(DeserializeMiddleware), nil
if s.head == s.tail { // it's the only one
s.head = nil
s.tail = nil
} else if found == s.head { // at the front
s.head = s.head.Next.(*decoratedDeserializeHandler)
} else if found == s.tail { // at the end
prev.Next = nil
s.tail = prev
} else {
prev.Next = found.Next // somewhere in the middle
}
return found.With, nil
}
// List returns a list of the middleware in the step.
func (s *DeserializeStep) List() []string {
return s.ids.List()
var ids []string
for h := s.head; h != nil; {
ids = append(ids, h.With.ID())
if h.Next == nil {
break
}
// once executed, tail.Next of the list will be set to an
// *deserializeWrapHandler, make sure to check for that
if hnext, ok := h.Next.(*decoratedDeserializeHandler); ok {
h = hnext
} else {
break
}
}
return ids
}
// Clear removes all middleware in the step.
func (s *DeserializeStep) Clear() {
s.ids.Clear()
s.head = nil
s.tail = nil
}
func (s *DeserializeStep) get(id string) (found, prev *decoratedDeserializeHandler) {
for h := s.head; h != nil; {
if h.With.ID() == id {
found = h
return
}
prev = h
if h.Next == nil {
return
}
// once executed, tail.Next of the list will be set to an
// *deserializeWrapHandler
h, _ = h.Next.(*decoratedDeserializeHandler)
}
return
}
type deserializeWrapHandler struct {
@@ -187,9 +269,10 @@ var _ DeserializeHandler = (*deserializeWrapHandler)(nil)
func (w deserializeWrapHandler) HandleDeserialize(ctx context.Context, in DeserializeInput) (
out DeserializeOutput, metadata Metadata, err error,
) {
resp, metadata, err := w.Next.Handle(ctx, in.Request)
res, metadata, err := w.Next.Handle(ctx, in.Request)
return DeserializeOutput{
RawResponse: resp,
RawResponse: res,
Result: nil,
}, metadata, err
}
@@ -206,12 +289,12 @@ func (h decoratedDeserializeHandler) HandleDeserialize(ctx context.Context, in D
return h.With.HandleDeserialize(ctx, in, h.Next)
}
// DeserializeHandlerFunc provides a wrapper around a function to be used as a deserialize middleware handler.
// DeserializeHandlerFunc provides a wrapper around a function to be used as deserializeMiddleware.
type DeserializeHandlerFunc func(context.Context, DeserializeInput) (DeserializeOutput, Metadata, error)
// HandleDeserialize invokes the wrapped function with the given arguments.
func (d DeserializeHandlerFunc) HandleDeserialize(ctx context.Context, in DeserializeInput) (DeserializeOutput, Metadata, error) {
return d(ctx, in)
// HandleDeserialize calls the wrapped function with the provided arguments.
func (f DeserializeHandlerFunc) HandleDeserialize(ctx context.Context, in DeserializeInput) (DeserializeOutput, Metadata, error) {
return f(ctx, in)
}
var _ DeserializeHandler = DeserializeHandlerFunc(nil)

View File

@@ -1,6 +1,10 @@
// Code generated by smithy-go/middleware/generate.go DO NOT EDIT.
package middleware
import "context"
import (
"context"
"fmt"
)
// FinalizeInput provides the input parameters for the FinalizeMiddleware to
// consume. FinalizeMiddleware may modify the Request value before forwarding
@@ -23,7 +27,7 @@ type FinalizeHandler interface {
}
// FinalizeMiddleware provides the interface for middleware specific to the
// serialize step. Delegates to the next FinalizeHandler for further
// finalize step. Delegates to the next FinalizeHandler for further
// processing.
type FinalizeMiddleware interface {
// ID returns a unique ID for the middleware in the FinalizeStep. The step does not
@@ -38,8 +42,8 @@ type FinalizeMiddleware interface {
)
}
// FinalizeMiddlewareFunc returns a FinalizeMiddleware with the unique ID
// provided, and the func to be invoked.
// FinalizeMiddlewareFunc returns a FinalizeMiddleware with the unique ID provided,
// and the func to be invoked.
func FinalizeMiddlewareFunc(id string, fn func(context.Context, FinalizeInput, FinalizeHandler) (FinalizeOutput, Metadata, error)) FinalizeMiddleware {
return finalizeMiddlewareFunc{
id: id,
@@ -72,20 +76,19 @@ var _ FinalizeMiddleware = (finalizeMiddlewareFunc{})
// FinalizeStep provides the ordered grouping of FinalizeMiddleware to be
// invoked on a handler.
type FinalizeStep struct {
ids *orderedIDs
head *decoratedFinalizeHandler
tail *decoratedFinalizeHandler
}
// NewFinalizeStep returns a FinalizeStep ready to have middleware for
// initialization added to it.
// NewFinalizeStep returns an FinalizeStep ready to have middleware for
// finalize added to it.
func NewFinalizeStep() *FinalizeStep {
return &FinalizeStep{
ids: newOrderedIDs(),
}
return &FinalizeStep{}
}
var _ Middleware = (*FinalizeStep)(nil)
// ID returns the unique id of the step as a middleware.
// ID returns the unique ID of the step as a middleware.
func (s *FinalizeStep) ID() string {
return "Finalize stack step"
}
@@ -97,77 +100,161 @@ func (s *FinalizeStep) ID() string {
func (s *FinalizeStep) HandleMiddleware(ctx context.Context, in interface{}, next Handler) (
out interface{}, metadata Metadata, err error,
) {
order := s.ids.GetOrder()
var h FinalizeHandler = finalizeWrapHandler{Next: next}
for i := len(order) - 1; i >= 0; i-- {
h = decoratedFinalizeHandler{
Next: h,
With: order[i].(FinalizeMiddleware),
}
}
sIn := FinalizeInput{
Request: in,
}
res, metadata, err := h.HandleFinalize(ctx, sIn)
wh := &finalizeWrapHandler{next}
if s.head == nil {
res, metadata, err := wh.HandleFinalize(ctx, sIn)
return res.Result, metadata, err
}
s.tail.Next = wh
res, metadata, err := s.head.HandleFinalize(ctx, sIn)
return res.Result, metadata, err
}
// Get retrieves the middleware identified by id. If the middleware is not present, returns false.
func (s *FinalizeStep) Get(id string) (FinalizeMiddleware, bool) {
get, ok := s.ids.Get(id)
if !ok {
found, _ := s.get(id)
if found == nil {
return nil, false
}
return get.(FinalizeMiddleware), ok
return found.With, true
}
// Add injects the middleware to the relative position of the middleware group.
// Returns an error if the middleware already exists.
//
// Add never returns an error. It used to for duplicate phases but this
// behavior has since been removed as part of a performance optimization. The
// return value from Add can be ignored.
func (s *FinalizeStep) Add(m FinalizeMiddleware, pos RelativePosition) error {
return s.ids.Add(m, pos)
if s.head == nil {
s.head = &decoratedFinalizeHandler{nil, m}
s.tail = s.head
return nil
}
if pos == Before {
s.head = &decoratedFinalizeHandler{s.head, m}
} else {
tail := &decoratedFinalizeHandler{nil, m}
s.tail.Next = tail
s.tail = tail
}
return nil
}
// Insert injects the middleware relative to an existing middleware ID.
// Returns error if the original middleware does not exist, or the middleware
// being added already exists.
func (s *FinalizeStep) Insert(m FinalizeMiddleware, relativeTo string, pos RelativePosition) error {
return s.ids.Insert(m, relativeTo, pos)
found, prev := s.get(relativeTo)
if found == nil {
return fmt.Errorf("not found: %s", m.ID())
}
if pos == Before {
if prev == nil { // at the front
s.head = &decoratedFinalizeHandler{s.head, m}
} else { // somewhere in the middle
prev.Next = &decoratedFinalizeHandler{found, m}
}
} else {
if found.Next == nil { // at the end
tail := &decoratedFinalizeHandler{nil, m}
s.tail.Next = tail
s.tail = tail
} else { // somewhere in the middle
found.Next = &decoratedFinalizeHandler{found.Next, m}
}
}
return nil
}
// Swap removes the middleware by id, replacing it with the new middleware.
// Returns the middleware removed, or error if the middleware to be removed
// doesn't exist.
func (s *FinalizeStep) Swap(id string, m FinalizeMiddleware) (FinalizeMiddleware, error) {
removed, err := s.ids.Swap(id, m)
if err != nil {
return nil, err
found, _ := s.get(id)
if found == nil {
return nil, fmt.Errorf("not found: %s", m.ID())
}
return removed.(FinalizeMiddleware), nil
swapped := found.With
found.With = m
return swapped, nil
}
// Remove removes the middleware by id. Returns error if the middleware
// doesn't exist.
func (s *FinalizeStep) Remove(id string) (FinalizeMiddleware, error) {
removed, err := s.ids.Remove(id)
if err != nil {
return nil, err
found, prev := s.get(id)
if found == nil {
return nil, fmt.Errorf("not found: %s", id)
}
return removed.(FinalizeMiddleware), nil
if s.head == s.tail { // it's the only one
s.head = nil
s.tail = nil
} else if found == s.head { // at the front
s.head = s.head.Next.(*decoratedFinalizeHandler)
} else if found == s.tail { // at the end
prev.Next = nil
s.tail = prev
} else {
prev.Next = found.Next // somewhere in the middle
}
return found.With, nil
}
// List returns a list of the middleware in the step.
func (s *FinalizeStep) List() []string {
return s.ids.List()
var ids []string
for h := s.head; h != nil; {
ids = append(ids, h.With.ID())
if h.Next == nil {
break
}
// once executed, tail.Next of the list will be set to an
// *finalizeWrapHandler, make sure to check for that
if hnext, ok := h.Next.(*decoratedFinalizeHandler); ok {
h = hnext
} else {
break
}
}
return ids
}
// Clear removes all middleware in the step.
func (s *FinalizeStep) Clear() {
s.ids.Clear()
s.head = nil
s.tail = nil
}
func (s *FinalizeStep) get(id string) (found, prev *decoratedFinalizeHandler) {
for h := s.head; h != nil; {
if h.With.ID() == id {
found = h
return
}
prev = h
if h.Next == nil {
return
}
// once executed, tail.Next of the list will be set to an
// *finalizeWrapHandler
h, _ = h.Next.(*decoratedFinalizeHandler)
}
return
}
type finalizeWrapHandler struct {
@@ -200,10 +287,10 @@ func (h decoratedFinalizeHandler) HandleFinalize(ctx context.Context, in Finaliz
return h.With.HandleFinalize(ctx, in, h.Next)
}
// FinalizeHandlerFunc provides a wrapper around a function to be used as a finalize middleware handler.
// FinalizeHandlerFunc provides a wrapper around a function to be used as finalizeMiddleware.
type FinalizeHandlerFunc func(context.Context, FinalizeInput) (FinalizeOutput, Metadata, error)
// HandleFinalize invokes the wrapped function with the given arguments.
// HandleFinalize calls the wrapped function with the provided arguments.
func (f FinalizeHandlerFunc) HandleFinalize(ctx context.Context, in FinalizeInput) (FinalizeOutput, Metadata, error) {
return f(ctx, in)
}

View File

@@ -1,10 +1,15 @@
// Code generated by smithy-go/middleware/generate.go DO NOT EDIT.
package middleware
import "context"
import (
"context"
"fmt"
)
// InitializeInput wraps the input parameters for the InitializeMiddlewares to
// consume. InitializeMiddleware may modify the parameter value before
// forwarding it along to the next InitializeHandler.
type InitializeInput struct {
Parameters interface{}
}
@@ -72,15 +77,14 @@ var _ InitializeMiddleware = (initializeMiddlewareFunc{})
// InitializeStep provides the ordered grouping of InitializeMiddleware to be
// invoked on a handler.
type InitializeStep struct {
ids *orderedIDs
head *decoratedInitializeHandler
tail *decoratedInitializeHandler
}
// NewInitializeStep returns an InitializeStep ready to have middleware for
// initialization added to it.
// initialize added to it.
func NewInitializeStep() *InitializeStep {
return &InitializeStep{
ids: newOrderedIDs(),
}
return &InitializeStep{}
}
var _ Middleware = (*InitializeStep)(nil)
@@ -97,77 +101,161 @@ func (s *InitializeStep) ID() string {
func (s *InitializeStep) HandleMiddleware(ctx context.Context, in interface{}, next Handler) (
out interface{}, metadata Metadata, err error,
) {
order := s.ids.GetOrder()
var h InitializeHandler = initializeWrapHandler{Next: next}
for i := len(order) - 1; i >= 0; i-- {
h = decoratedInitializeHandler{
Next: h,
With: order[i].(InitializeMiddleware),
}
}
sIn := InitializeInput{
Parameters: in,
}
res, metadata, err := h.HandleInitialize(ctx, sIn)
wh := &initializeWrapHandler{next}
if s.head == nil {
res, metadata, err := wh.HandleInitialize(ctx, sIn)
return res.Result, metadata, err
}
s.tail.Next = wh
res, metadata, err := s.head.HandleInitialize(ctx, sIn)
return res.Result, metadata, err
}
// Get retrieves the middleware identified by id. If the middleware is not present, returns false.
func (s *InitializeStep) Get(id string) (InitializeMiddleware, bool) {
get, ok := s.ids.Get(id)
if !ok {
found, _ := s.get(id)
if found == nil {
return nil, false
}
return get.(InitializeMiddleware), ok
return found.With, true
}
// Add injects the middleware to the relative position of the middleware group.
// Returns an error if the middleware already exists.
//
// Add never returns an error. It used to for duplicate phases but this
// behavior has since been removed as part of a performance optimization. The
// return value from Add can be ignored.
func (s *InitializeStep) Add(m InitializeMiddleware, pos RelativePosition) error {
return s.ids.Add(m, pos)
if s.head == nil {
s.head = &decoratedInitializeHandler{nil, m}
s.tail = s.head
return nil
}
if pos == Before {
s.head = &decoratedInitializeHandler{s.head, m}
} else {
tail := &decoratedInitializeHandler{nil, m}
s.tail.Next = tail
s.tail = tail
}
return nil
}
// Insert injects the middleware relative to an existing middleware ID.
// Returns error if the original middleware does not exist, or the middleware
// being added already exists.
func (s *InitializeStep) Insert(m InitializeMiddleware, relativeTo string, pos RelativePosition) error {
return s.ids.Insert(m, relativeTo, pos)
found, prev := s.get(relativeTo)
if found == nil {
return fmt.Errorf("not found: %s", m.ID())
}
if pos == Before {
if prev == nil { // at the front
s.head = &decoratedInitializeHandler{s.head, m}
} else { // somewhere in the middle
prev.Next = &decoratedInitializeHandler{found, m}
}
} else {
if found.Next == nil { // at the end
tail := &decoratedInitializeHandler{nil, m}
s.tail.Next = tail
s.tail = tail
} else { // somewhere in the middle
found.Next = &decoratedInitializeHandler{found.Next, m}
}
}
return nil
}
// Swap removes the middleware by id, replacing it with the new middleware.
// Returns the middleware removed, or error if the middleware to be removed
// doesn't exist.
func (s *InitializeStep) Swap(id string, m InitializeMiddleware) (InitializeMiddleware, error) {
removed, err := s.ids.Swap(id, m)
if err != nil {
return nil, err
found, _ := s.get(id)
if found == nil {
return nil, fmt.Errorf("not found: %s", m.ID())
}
return removed.(InitializeMiddleware), nil
swapped := found.With
found.With = m
return swapped, nil
}
// Remove removes the middleware by id. Returns error if the middleware
// doesn't exist.
func (s *InitializeStep) Remove(id string) (InitializeMiddleware, error) {
removed, err := s.ids.Remove(id)
if err != nil {
return nil, err
found, prev := s.get(id)
if found == nil {
return nil, fmt.Errorf("not found: %s", id)
}
return removed.(InitializeMiddleware), nil
if s.head == s.tail { // it's the only one
s.head = nil
s.tail = nil
} else if found == s.head { // at the front
s.head = s.head.Next.(*decoratedInitializeHandler)
} else if found == s.tail { // at the end
prev.Next = nil
s.tail = prev
} else {
prev.Next = found.Next // somewhere in the middle
}
return found.With, nil
}
// List returns a list of the middleware in the step.
func (s *InitializeStep) List() []string {
return s.ids.List()
var ids []string
for h := s.head; h != nil; {
ids = append(ids, h.With.ID())
if h.Next == nil {
break
}
// once executed, tail.Next of the list will be set to an
// *initializeWrapHandler, make sure to check for that
if hnext, ok := h.Next.(*decoratedInitializeHandler); ok {
h = hnext
} else {
break
}
}
return ids
}
// Clear removes all middleware in the step.
func (s *InitializeStep) Clear() {
s.ids.Clear()
s.head = nil
s.tail = nil
}
func (s *InitializeStep) get(id string) (found, prev *decoratedInitializeHandler) {
for h := s.head; h != nil; {
if h.With.ID() == id {
found = h
return
}
prev = h
if h.Next == nil {
return
}
// once executed, tail.Next of the list will be set to an
// *initializeWrapHandler
h, _ = h.Next.(*decoratedInitializeHandler)
}
return
}
type initializeWrapHandler struct {
@@ -200,12 +288,12 @@ func (h decoratedInitializeHandler) HandleInitialize(ctx context.Context, in Ini
return h.With.HandleInitialize(ctx, in, h.Next)
}
// InitializeHandlerFunc provides a wrapper around a function to be used as an initialize middleware handler.
// InitializeHandlerFunc provides a wrapper around a function to be used as initializeMiddleware.
type InitializeHandlerFunc func(context.Context, InitializeInput) (InitializeOutput, Metadata, error)
// HandleInitialize calls the wrapped function with the provided arguments.
func (i InitializeHandlerFunc) HandleInitialize(ctx context.Context, in InitializeInput) (InitializeOutput, Metadata, error) {
return i(ctx, in)
func (f InitializeHandlerFunc) HandleInitialize(ctx context.Context, in InitializeInput) (InitializeOutput, Metadata, error) {
return f(ctx, in)
}
var _ InitializeHandler = InitializeHandlerFunc(nil)

View File

@@ -1,6 +1,10 @@
// Code generated by smithy-go/middleware/generate.go DO NOT EDIT.
package middleware
import "context"
import (
"context"
"fmt"
)
// SerializeInput provides the input parameters for the SerializeMiddleware to
// consume. SerializeMiddleware may modify the Request value before forwarding
@@ -41,8 +45,8 @@ type SerializeMiddleware interface {
)
}
// SerializeMiddlewareFunc returns a SerializeMiddleware with the unique ID
// provided, and the func to be invoked.
// SerializeMiddlewareFunc returns a SerializeMiddleware with the unique ID provided,
// and the func to be invoked.
func SerializeMiddlewareFunc(id string, fn func(context.Context, SerializeInput, SerializeHandler) (SerializeOutput, Metadata, error)) SerializeMiddleware {
return serializeMiddlewareFunc{
id: id,
@@ -75,17 +79,15 @@ var _ SerializeMiddleware = (serializeMiddlewareFunc{})
// SerializeStep provides the ordered grouping of SerializeMiddleware to be
// invoked on a handler.
type SerializeStep struct {
head *decoratedSerializeHandler
tail *decoratedSerializeHandler
newRequest func() interface{}
ids *orderedIDs
}
// NewSerializeStep returns a SerializeStep ready to have middleware for
// initialization added to it. The newRequest func parameter is used to
// initialize the transport specific request for the stack SerializeStep to
// serialize the input parameters into.
// NewSerializeStep returns an SerializeStep ready to have middleware for
// serialize added to it.
func NewSerializeStep(newRequest func() interface{}) *SerializeStep {
return &SerializeStep{
ids: newOrderedIDs(),
newRequest: newRequest,
}
}
@@ -104,78 +106,162 @@ func (s *SerializeStep) ID() string {
func (s *SerializeStep) HandleMiddleware(ctx context.Context, in interface{}, next Handler) (
out interface{}, metadata Metadata, err error,
) {
order := s.ids.GetOrder()
var h SerializeHandler = serializeWrapHandler{Next: next}
for i := len(order) - 1; i >= 0; i-- {
h = decoratedSerializeHandler{
Next: h,
With: order[i].(SerializeMiddleware),
}
}
sIn := SerializeInput{
Parameters: in,
Request: s.newRequest(),
}
res, metadata, err := h.HandleSerialize(ctx, sIn)
wh := &serializeWrapHandler{next}
if s.head == nil {
res, metadata, err := wh.HandleSerialize(ctx, sIn)
return res.Result, metadata, err
}
s.tail.Next = wh
res, metadata, err := s.head.HandleSerialize(ctx, sIn)
return res.Result, metadata, err
}
// Get retrieves the middleware identified by id. If the middleware is not present, returns false.
func (s *SerializeStep) Get(id string) (SerializeMiddleware, bool) {
get, ok := s.ids.Get(id)
if !ok {
found, _ := s.get(id)
if found == nil {
return nil, false
}
return get.(SerializeMiddleware), ok
return found.With, true
}
// Add injects the middleware to the relative position of the middleware group.
// Returns an error if the middleware already exists.
//
// Add never returns an error. It used to for duplicate phases but this
// behavior has since been removed as part of a performance optimization. The
// return value from Add can be ignored.
func (s *SerializeStep) Add(m SerializeMiddleware, pos RelativePosition) error {
return s.ids.Add(m, pos)
if s.head == nil {
s.head = &decoratedSerializeHandler{nil, m}
s.tail = s.head
return nil
}
if pos == Before {
s.head = &decoratedSerializeHandler{s.head, m}
} else {
tail := &decoratedSerializeHandler{nil, m}
s.tail.Next = tail
s.tail = tail
}
return nil
}
// Insert injects the middleware relative to an existing middleware ID.
// Returns error if the original middleware does not exist, or the middleware
// being added already exists.
func (s *SerializeStep) Insert(m SerializeMiddleware, relativeTo string, pos RelativePosition) error {
return s.ids.Insert(m, relativeTo, pos)
found, prev := s.get(relativeTo)
if found == nil {
return fmt.Errorf("not found: %s", m.ID())
}
if pos == Before {
if prev == nil { // at the front
s.head = &decoratedSerializeHandler{s.head, m}
} else { // somewhere in the middle
prev.Next = &decoratedSerializeHandler{found, m}
}
} else {
if found.Next == nil { // at the end
tail := &decoratedSerializeHandler{nil, m}
s.tail.Next = tail
s.tail = tail
} else { // somewhere in the middle
found.Next = &decoratedSerializeHandler{found.Next, m}
}
}
return nil
}
// Swap removes the middleware by id, replacing it with the new middleware.
// Returns the middleware removed, or error if the middleware to be removed
// doesn't exist.
func (s *SerializeStep) Swap(id string, m SerializeMiddleware) (SerializeMiddleware, error) {
removed, err := s.ids.Swap(id, m)
if err != nil {
return nil, err
found, _ := s.get(id)
if found == nil {
return nil, fmt.Errorf("not found: %s", m.ID())
}
return removed.(SerializeMiddleware), nil
swapped := found.With
found.With = m
return swapped, nil
}
// Remove removes the middleware by id. Returns error if the middleware
// doesn't exist.
func (s *SerializeStep) Remove(id string) (SerializeMiddleware, error) {
removed, err := s.ids.Remove(id)
if err != nil {
return nil, err
found, prev := s.get(id)
if found == nil {
return nil, fmt.Errorf("not found: %s", id)
}
return removed.(SerializeMiddleware), nil
if s.head == s.tail { // it's the only one
s.head = nil
s.tail = nil
} else if found == s.head { // at the front
s.head = s.head.Next.(*decoratedSerializeHandler)
} else if found == s.tail { // at the end
prev.Next = nil
s.tail = prev
} else {
prev.Next = found.Next // somewhere in the middle
}
return found.With, nil
}
// List returns a list of the middleware in the step.
func (s *SerializeStep) List() []string {
return s.ids.List()
var ids []string
for h := s.head; h != nil; {
ids = append(ids, h.With.ID())
if h.Next == nil {
break
}
// once executed, tail.Next of the list will be set to an
// *serializeWrapHandler, make sure to check for that
if hnext, ok := h.Next.(*decoratedSerializeHandler); ok {
h = hnext
} else {
break
}
}
return ids
}
// Clear removes all middleware in the step.
func (s *SerializeStep) Clear() {
s.ids.Clear()
s.head = nil
s.tail = nil
}
func (s *SerializeStep) get(id string) (found, prev *decoratedSerializeHandler) {
for h := s.head; h != nil; {
if h.With.ID() == id {
found = h
return
}
prev = h
if h.Next == nil {
return
}
// once executed, tail.Next of the list will be set to an
// *serializeWrapHandler
h, _ = h.Next.(*decoratedSerializeHandler)
}
return
}
type serializeWrapHandler struct {
@@ -184,7 +270,7 @@ type serializeWrapHandler struct {
var _ SerializeHandler = (*serializeWrapHandler)(nil)
// Implements SerializeHandler, converts types and delegates to underlying
// HandleSerialize implements SerializeHandler, converts types and delegates to underlying
// generic handler.
func (w serializeWrapHandler) HandleSerialize(ctx context.Context, in SerializeInput) (
out SerializeOutput, metadata Metadata, err error,
@@ -208,12 +294,12 @@ func (h decoratedSerializeHandler) HandleSerialize(ctx context.Context, in Seria
return h.With.HandleSerialize(ctx, in, h.Next)
}
// SerializeHandlerFunc provides a wrapper around a function to be used as a serialize middleware handler.
// SerializeHandlerFunc provides a wrapper around a function to be used as serializeMiddleware.
type SerializeHandlerFunc func(context.Context, SerializeInput) (SerializeOutput, Metadata, error)
// HandleSerialize calls the wrapped function with the provided arguments.
func (s SerializeHandlerFunc) HandleSerialize(ctx context.Context, in SerializeInput) (SerializeOutput, Metadata, error) {
return s(ctx, in)
func (f SerializeHandlerFunc) HandleSerialize(ctx context.Context, in SerializeInput) (SerializeOutput, Metadata, error) {
return f(ctx, in)
}
var _ SerializeHandler = SerializeHandlerFunc(nil)

View File

@@ -1,5 +1,4 @@
[dependencies]
"github.com/jmespath/go-jmespath" = "v0.4.0"
[modules]

View File

@@ -0,0 +1,321 @@
package http
import (
"context"
)
func icopy[T any](v []T) []T {
s := make([]T, len(v))
copy(s, v)
return s
}
// InterceptorContext is all the information available in different
// interceptors.
//
// Not all information is available in each interceptor, see each interface
// definition for more details.
type InterceptorContext struct {
Input any
Request *Request
Output any
Response *Response
}
// InterceptorRegistry holds a list of operation interceptors.
//
// Interceptors allow callers to insert custom behavior at well-defined points
// within a client's operation lifecycle.
//
// # Interceptor context
//
// All interceptors are invoked with a context object that contains input and
// output containers for the operation. The individual fields that are
// available will depend on what the interceptor is and, in certain
// interceptors, how far the operation was able to progress. See the
// documentation for each interface definition for more information about field
// availability.
//
// Implementations MUST NOT directly mutate the values of the fields in the
// interceptor context. They are free to mutate the existing values _pointed
// to_ by those fields, however.
//
// # Returning errors
//
// All interceptors can return errors. If an interceptor returns an error
// _before_ the client's retry loop, the operation will fail immediately. If
// one returns an error _within_ the retry loop, the error WILL be considered
// according to the client's retry policy.
//
// # Adding interceptors
//
// Idiomatically you will simply use one of the Add() receiver methods to
// register interceptors as desired. However, the list for each interface is
// exported on the registry struct and the caller is free to manipulate it
// directly, for example, to register a number of interceptors all at once, or
// to remove one that was previously registered.
//
// The base SDK client WILL NOT add any interceptors. SDK operations and
// customizations are implemented in terms of middleware.
//
// Modifications to the registry will not persist across operation calls when
// using per-operation functional options. This means you can register
// interceptors on a per-operation basis without affecting other operations.
type InterceptorRegistry struct {
BeforeExecution []BeforeExecutionInterceptor
BeforeSerialization []BeforeSerializationInterceptor
AfterSerialization []AfterSerializationInterceptor
BeforeRetryLoop []BeforeRetryLoopInterceptor
BeforeAttempt []BeforeAttemptInterceptor
BeforeSigning []BeforeSigningInterceptor
AfterSigning []AfterSigningInterceptor
BeforeTransmit []BeforeTransmitInterceptor
AfterTransmit []AfterTransmitInterceptor
BeforeDeserialization []BeforeDeserializationInterceptor
AfterDeserialization []AfterDeserializationInterceptor
AfterAttempt []AfterAttemptInterceptor
AfterExecution []AfterExecutionInterceptor
}
// Copy returns a deep copy of the registry. This is used by SDK clients on
// each operation call in order to prevent per-op config mutation from
// persisting.
func (i *InterceptorRegistry) Copy() InterceptorRegistry {
return InterceptorRegistry{
BeforeExecution: icopy(i.BeforeExecution),
BeforeSerialization: icopy(i.BeforeSerialization),
AfterSerialization: icopy(i.AfterSerialization),
BeforeRetryLoop: icopy(i.BeforeRetryLoop),
BeforeAttempt: icopy(i.BeforeAttempt),
BeforeSigning: icopy(i.BeforeSigning),
AfterSigning: icopy(i.AfterSigning),
BeforeTransmit: icopy(i.BeforeTransmit),
AfterTransmit: icopy(i.AfterTransmit),
BeforeDeserialization: icopy(i.BeforeDeserialization),
AfterDeserialization: icopy(i.AfterDeserialization),
AfterAttempt: icopy(i.AfterAttempt),
AfterExecution: icopy(i.AfterExecution),
}
}
// AddBeforeExecution registers the provided BeforeExecutionInterceptor.
func (i *InterceptorRegistry) AddBeforeExecution(v BeforeExecutionInterceptor) {
i.BeforeExecution = append(i.BeforeExecution, v)
}
// AddBeforeSerialization registers the provided BeforeSerializationInterceptor.
func (i *InterceptorRegistry) AddBeforeSerialization(v BeforeSerializationInterceptor) {
i.BeforeSerialization = append(i.BeforeSerialization, v)
}
// AddAfterSerialization registers the provided AfterSerializationInterceptor.
func (i *InterceptorRegistry) AddAfterSerialization(v AfterSerializationInterceptor) {
i.AfterSerialization = append(i.AfterSerialization, v)
}
// AddBeforeRetryLoop registers the provided BeforeRetryLoopInterceptor.
func (i *InterceptorRegistry) AddBeforeRetryLoop(v BeforeRetryLoopInterceptor) {
i.BeforeRetryLoop = append(i.BeforeRetryLoop, v)
}
// AddBeforeAttempt registers the provided BeforeAttemptInterceptor.
func (i *InterceptorRegistry) AddBeforeAttempt(v BeforeAttemptInterceptor) {
i.BeforeAttempt = append(i.BeforeAttempt, v)
}
// AddBeforeSigning registers the provided BeforeSigningInterceptor.
func (i *InterceptorRegistry) AddBeforeSigning(v BeforeSigningInterceptor) {
i.BeforeSigning = append(i.BeforeSigning, v)
}
// AddAfterSigning registers the provided AfterSigningInterceptor.
func (i *InterceptorRegistry) AddAfterSigning(v AfterSigningInterceptor) {
i.AfterSigning = append(i.AfterSigning, v)
}
// AddBeforeTransmit registers the provided BeforeTransmitInterceptor.
func (i *InterceptorRegistry) AddBeforeTransmit(v BeforeTransmitInterceptor) {
i.BeforeTransmit = append(i.BeforeTransmit, v)
}
// AddAfterTransmit registers the provided AfterTransmitInterceptor.
func (i *InterceptorRegistry) AddAfterTransmit(v AfterTransmitInterceptor) {
i.AfterTransmit = append(i.AfterTransmit, v)
}
// AddBeforeDeserialization registers the provided BeforeDeserializationInterceptor.
func (i *InterceptorRegistry) AddBeforeDeserialization(v BeforeDeserializationInterceptor) {
i.BeforeDeserialization = append(i.BeforeDeserialization, v)
}
// AddAfterDeserialization registers the provided AfterDeserializationInterceptor.
func (i *InterceptorRegistry) AddAfterDeserialization(v AfterDeserializationInterceptor) {
i.AfterDeserialization = append(i.AfterDeserialization, v)
}
// AddAfterAttempt registers the provided AfterAttemptInterceptor.
func (i *InterceptorRegistry) AddAfterAttempt(v AfterAttemptInterceptor) {
i.AfterAttempt = append(i.AfterAttempt, v)
}
// AddAfterExecution registers the provided AfterExecutionInterceptor.
func (i *InterceptorRegistry) AddAfterExecution(v AfterExecutionInterceptor) {
i.AfterExecution = append(i.AfterExecution, v)
}
// BeforeExecutionInterceptor runs before anything else in the operation
// lifecycle.
//
// Available InterceptorContext fields:
// - Input
type BeforeExecutionInterceptor interface {
BeforeExecution(ctx context.Context, in *InterceptorContext) error
}
// BeforeSerializationInterceptor runs before the operation input is serialized
// into its transport request.
//
// Serialization occurs before the operation's retry loop.
//
// Available InterceptorContext fields:
// - Input
type BeforeSerializationInterceptor interface {
BeforeSerialization(ctx context.Context, in *InterceptorContext) error
}
// AfterSerializationInterceptor runs after the operation input is serialized
// into its transport request.
//
// Available InterceptorContext fields:
// - Input
// - Request
type AfterSerializationInterceptor interface {
AfterSerialization(ctx context.Context, in *InterceptorContext) error
}
// BeforeRetryLoopInterceptor runs right before the operation enters the retry loop.
//
// Available InterceptorContext fields:
// - Input
// - Request
type BeforeRetryLoopInterceptor interface {
BeforeRetryLoop(ctx context.Context, in *InterceptorContext) error
}
// BeforeAttemptInterceptor runs right before every attempt in the retry loop.
//
// If this interceptor returns an error, AfterAttempt interceptors WILL NOT be
// invoked.
//
// Available InterceptorContext fields:
// - Input
// - Request
type BeforeAttemptInterceptor interface {
BeforeAttempt(ctx context.Context, in *InterceptorContext) error
}
// BeforeSigningInterceptor runs right before the request is signed.
//
// Signing occurs within the operation's retry loop.
//
// Available InterceptorContext fields:
// - Input
// - Request
type BeforeSigningInterceptor interface {
BeforeSigning(ctx context.Context, in *InterceptorContext) error
}
// AfterSigningInterceptor runs right after the request is signed.
//
// It is unsafe to modify the outgoing HTTP request at or past this hook, since
// doing so may invalidate the signature of the request.
//
// Available InterceptorContext fields:
// - Input
// - Request
type AfterSigningInterceptor interface {
AfterSigning(ctx context.Context, in *InterceptorContext) error
}
// BeforeTransmitInterceptor runs right before the HTTP request is sent.
//
// HTTP transmit occurs within the operation's retry loop.
//
// Available InterceptorContext fields:
// - Input
// - Request
type BeforeTransmitInterceptor interface {
BeforeTransmit(ctx context.Context, in *InterceptorContext) error
}
// AfterTransmitInterceptor runs right after the HTTP response is received.
//
// It will always be invoked when a response is received, regardless of its
// status code. Conversely, it WILL NOT be invoked if the HTTP round-trip was
// not successful, e.g. because of a DNS resolution error
//
// Available InterceptorContext fields:
// - Input
// - Request
// - Response
type AfterTransmitInterceptor interface {
AfterTransmit(ctx context.Context, in *InterceptorContext) error
}
// BeforeDeserializationInterceptor runs right before the incoming HTTP response
// is deserialized.
//
// This interceptor IS NOT invoked if the HTTP round-trip was not successful.
//
// Deserialization occurs within the operation's retry loop.
//
// Available InterceptorContext fields:
// - Input
// - Request
// - Response
type BeforeDeserializationInterceptor interface {
BeforeDeserialization(ctx context.Context, in *InterceptorContext) error
}
// AfterDeserializationInterceptor runs right after the incoming HTTP response
// is deserialized. This hook is invoked regardless of whether the deserialized
// result was an error.
//
// This interceptor IS NOT invoked if the HTTP round-trip was not successful.
//
// Available InterceptorContext fields:
// - Input
// - Output (IF the operation had a success-level response)
// - Request
// - Response
type AfterDeserializationInterceptor interface {
AfterDeserialization(ctx context.Context, in *InterceptorContext) error
}
// AfterAttemptInterceptor runs right after the incoming HTTP response
// is deserialized. This hook is invoked regardless of whether the deserialized
// result was an error, or if another interceptor within the retry loop
// returned an error.
//
// Available InterceptorContext fields:
// - Input
// - Output (IF the operation had a success-level response)
// - Request (IF the operation did not return an error during serialization)
// - Response (IF the operation was able to transmit the HTTP request)
type AfterAttemptInterceptor interface {
AfterAttempt(ctx context.Context, in *InterceptorContext) error
}
// AfterExecutionInterceptor runs after everything else. It runs regardless of
// how far the operation progressed in its lifecycle, and regardless of whether
// the operation succeeded or failed.
//
// Available InterceptorContext fields:
// - Input
// - Output (IF the operation had a success-level response)
// - Request (IF the operation did not return an error during serialization)
// - Response (IF the operation was able to transmit the HTTP request)
type AfterExecutionInterceptor interface {
AfterExecution(ctx context.Context, in *InterceptorContext) error
}

View File

@@ -0,0 +1,325 @@
package http
import (
"context"
"errors"
"github.com/aws/smithy-go/middleware"
)
type ictxKey struct{}
func withIctx(ctx context.Context) context.Context {
return middleware.WithStackValue(ctx, ictxKey{}, &InterceptorContext{})
}
func getIctx(ctx context.Context) *InterceptorContext {
return middleware.GetStackValue(ctx, ictxKey{}).(*InterceptorContext)
}
// InterceptExecution runs Before/AfterExecutionInterceptors.
type InterceptExecution struct {
BeforeExecution []BeforeExecutionInterceptor
AfterExecution []AfterExecutionInterceptor
}
// ID identifies the middleware.
func (m *InterceptExecution) ID() string {
return "InterceptExecution"
}
// HandleInitialize runs the interceptors.
func (m *InterceptExecution) HandleInitialize(
ctx context.Context, in middleware.InitializeInput, next middleware.InitializeHandler,
) (
out middleware.InitializeOutput, md middleware.Metadata, err error,
) {
ctx = withIctx(ctx)
getIctx(ctx).Input = in.Parameters
for _, i := range m.BeforeExecution {
if err := i.BeforeExecution(ctx, getIctx(ctx)); err != nil {
return out, md, err
}
}
out, md, err = next.HandleInitialize(ctx, in)
for _, i := range m.AfterExecution {
if err := i.AfterExecution(ctx, getIctx(ctx)); err != nil {
return out, md, err
}
}
return out, md, err
}
// InterceptBeforeSerialization runs BeforeSerializationInterceptors.
type InterceptBeforeSerialization struct {
Interceptors []BeforeSerializationInterceptor
}
// ID identifies the middleware.
func (m *InterceptBeforeSerialization) ID() string {
return "InterceptBeforeSerialization"
}
// HandleSerialize runs the interceptors.
func (m *InterceptBeforeSerialization) HandleSerialize(
ctx context.Context, in middleware.SerializeInput, next middleware.SerializeHandler,
) (
out middleware.SerializeOutput, md middleware.Metadata, err error,
) {
for _, i := range m.Interceptors {
if err := i.BeforeSerialization(ctx, getIctx(ctx)); err != nil {
return out, md, err
}
}
return next.HandleSerialize(ctx, in)
}
// InterceptAfterSerialization runs AfterSerializationInterceptors.
type InterceptAfterSerialization struct {
Interceptors []AfterSerializationInterceptor
}
// ID identifies the middleware.
func (m *InterceptAfterSerialization) ID() string {
return "InterceptAfterSerialization"
}
// HandleSerialize runs the interceptors.
func (m *InterceptAfterSerialization) HandleSerialize(
ctx context.Context, in middleware.SerializeInput, next middleware.SerializeHandler,
) (
out middleware.SerializeOutput, md middleware.Metadata, err error,
) {
getIctx(ctx).Request = in.Request.(*Request)
for _, i := range m.Interceptors {
if err := i.AfterSerialization(ctx, getIctx(ctx)); err != nil {
return out, md, err
}
}
return next.HandleSerialize(ctx, in)
}
// InterceptBeforeRetryLoop runs BeforeRetryLoopInterceptors.
type InterceptBeforeRetryLoop struct {
Interceptors []BeforeRetryLoopInterceptor
}
// ID identifies the middleware.
func (m *InterceptBeforeRetryLoop) ID() string {
return "InterceptBeforeRetryLoop"
}
// HandleFinalize runs the interceptors.
func (m *InterceptBeforeRetryLoop) HandleFinalize(
ctx context.Context, in middleware.FinalizeInput, next middleware.FinalizeHandler,
) (
out middleware.FinalizeOutput, md middleware.Metadata, err error,
) {
for _, i := range m.Interceptors {
if err := i.BeforeRetryLoop(ctx, getIctx(ctx)); err != nil {
return out, md, err
}
}
return next.HandleFinalize(ctx, in)
}
// InterceptBeforeSigning runs BeforeSigningInterceptors.
type InterceptBeforeSigning struct {
Interceptors []BeforeSigningInterceptor
}
// ID identifies the middleware.
func (m *InterceptBeforeSigning) ID() string {
return "InterceptBeforeSigning"
}
// HandleFinalize runs the interceptors.
func (m *InterceptBeforeSigning) HandleFinalize(
ctx context.Context, in middleware.FinalizeInput, next middleware.FinalizeHandler,
) (
out middleware.FinalizeOutput, md middleware.Metadata, err error,
) {
for _, i := range m.Interceptors {
if err := i.BeforeSigning(ctx, getIctx(ctx)); err != nil {
return out, md, err
}
}
return next.HandleFinalize(ctx, in)
}
// InterceptAfterSigning runs AfterSigningInterceptors.
type InterceptAfterSigning struct {
Interceptors []AfterSigningInterceptor
}
// ID identifies the middleware.
func (m *InterceptAfterSigning) ID() string {
return "InterceptAfterSigning"
}
// HandleFinalize runs the interceptors.
func (m *InterceptAfterSigning) HandleFinalize(
ctx context.Context, in middleware.FinalizeInput, next middleware.FinalizeHandler,
) (
out middleware.FinalizeOutput, md middleware.Metadata, err error,
) {
for _, i := range m.Interceptors {
if err := i.AfterSigning(ctx, getIctx(ctx)); err != nil {
return out, md, err
}
}
return next.HandleFinalize(ctx, in)
}
// InterceptTransmit runs BeforeTransmitInterceptors and AfterTransmitInterceptors.
type InterceptTransmit struct {
BeforeTransmit []BeforeTransmitInterceptor
AfterTransmit []AfterTransmitInterceptor
}
// ID identifies the middleware.
func (m *InterceptTransmit) ID() string {
return "InterceptTransmit"
}
// HandleDeserialize runs the interceptors.
func (m *InterceptTransmit) HandleDeserialize(
ctx context.Context, in middleware.DeserializeInput, next middleware.DeserializeHandler,
) (
out middleware.DeserializeOutput, md middleware.Metadata, err error,
) {
for _, i := range m.BeforeTransmit {
if err := i.BeforeTransmit(ctx, getIctx(ctx)); err != nil {
return out, md, err
}
}
out, md, err = next.HandleDeserialize(ctx, in)
if err != nil {
return out, md, err
}
// the root of the decorated middleware guarantees this will be here
// (client.go: ClientHandler.Handle)
getIctx(ctx).Response = out.RawResponse.(*Response)
for _, i := range m.AfterTransmit {
if err := i.AfterTransmit(ctx, getIctx(ctx)); err != nil {
return out, md, err
}
}
return out, md, err
}
// InterceptBeforeDeserialization runs BeforeDeserializationInterceptors.
type InterceptBeforeDeserialization struct {
Interceptors []BeforeDeserializationInterceptor
}
// ID identifies the middleware.
func (m *InterceptBeforeDeserialization) ID() string {
return "InterceptBeforeDeserialization"
}
// HandleDeserialize runs the interceptors.
func (m *InterceptBeforeDeserialization) HandleDeserialize(
ctx context.Context, in middleware.DeserializeInput, next middleware.DeserializeHandler,
) (
out middleware.DeserializeOutput, md middleware.Metadata, err error,
) {
out, md, err = next.HandleDeserialize(ctx, in)
if err != nil {
var terr *RequestSendError
if errors.As(err, &terr) {
return out, md, err
}
}
for _, i := range m.Interceptors {
if err := i.BeforeDeserialization(ctx, getIctx(ctx)); err != nil {
return out, md, err
}
}
return out, md, err
}
// InterceptAfterDeserialization runs AfterDeserializationInterceptors.
type InterceptAfterDeserialization struct {
Interceptors []AfterDeserializationInterceptor
}
// ID identifies the middleware.
func (m *InterceptAfterDeserialization) ID() string {
return "InterceptAfterDeserialization"
}
// HandleDeserialize runs the interceptors.
func (m *InterceptAfterDeserialization) HandleDeserialize(
ctx context.Context, in middleware.DeserializeInput, next middleware.DeserializeHandler,
) (
out middleware.DeserializeOutput, md middleware.Metadata, err error,
) {
out, md, err = next.HandleDeserialize(ctx, in)
if err != nil {
var terr *RequestSendError
if errors.As(err, &terr) {
return out, md, err
}
}
getIctx(ctx).Output = out.Result
for _, i := range m.Interceptors {
if err := i.AfterDeserialization(ctx, getIctx(ctx)); err != nil {
return out, md, err
}
}
return out, md, err
}
// InterceptAttempt runs AfterAttemptInterceptors.
type InterceptAttempt struct {
BeforeAttempt []BeforeAttemptInterceptor
AfterAttempt []AfterAttemptInterceptor
}
// ID identifies the middleware.
func (m *InterceptAttempt) ID() string {
return "InterceptAttempt"
}
// HandleFinalize runs the interceptors.
func (m *InterceptAttempt) HandleFinalize(
ctx context.Context, in middleware.FinalizeInput, next middleware.FinalizeHandler,
) (
out middleware.FinalizeOutput, md middleware.Metadata, err error,
) {
for _, i := range m.BeforeAttempt {
if err := i.BeforeAttempt(ctx, getIctx(ctx)); err != nil {
return out, md, err
}
}
out, md, err = next.HandleFinalize(ctx, in)
for _, i := range m.AfterAttempt {
if err := i.AfterAttempt(ctx, getIctx(ctx)); err != nil {
return out, md, err
}
}
return out, md, err
}

View File

@@ -17,6 +17,12 @@ var now = time.Now
func withMetrics(parent context.Context, client ClientDo, meter metrics.Meter) (
context.Context, ClientDo, error,
) {
// WithClientTrace is an expensive operation - avoid calling it if we're
// not actually using a metrics sink.
if _, ok := meter.(metrics.NopMeter); ok {
return parent, client, nil
}
hm, err := newHTTPMetrics(meter)
if err != nil {
return nil, nil, err

View File

@@ -1,36 +0,0 @@
package waiter
import (
"context"
"fmt"
"github.com/aws/smithy-go/logging"
"github.com/aws/smithy-go/middleware"
)
// Logger is the Logger middleware used by the waiter to log an attempt
type Logger struct {
// Attempt is the current attempt to be logged
Attempt int64
}
// ID representing the Logger middleware
func (*Logger) ID() string {
return "WaiterLogger"
}
// HandleInitialize performs handling of request in initialize stack step
func (m *Logger) HandleInitialize(ctx context.Context, in middleware.InitializeInput, next middleware.InitializeHandler) (
out middleware.InitializeOutput, metadata middleware.Metadata, err error,
) {
logger := middleware.GetLogger(ctx)
logger.Logf(logging.Debug, fmt.Sprintf("attempting waiter request, attempt count: %d", m.Attempt))
return next.HandleInitialize(ctx, in)
}
// AddLogger is a helper util to add waiter logger after `SetLogger` middleware in
func (m Logger) AddLogger(stack *middleware.Stack) error {
return stack.Initialize.Insert(&m, "SetLogger", middleware.After)
}

View File

@@ -1,66 +0,0 @@
package waiter
import (
"fmt"
"math"
"time"
"github.com/aws/smithy-go/rand"
)
// ComputeDelay computes delay between waiter attempts. The function takes in a current attempt count,
// minimum delay, maximum delay, and remaining wait time for waiter as input. The inputs minDelay and maxDelay
// must always be greater than 0, along with minDelay lesser than or equal to maxDelay.
//
// Returns the computed delay and if next attempt count is possible within the given input time constraints.
// Note that the zeroth attempt results in no delay.
func ComputeDelay(attempt int64, minDelay, maxDelay, remainingTime time.Duration) (delay time.Duration, err error) {
// zeroth attempt, no delay
if attempt <= 0 {
return 0, nil
}
// remainingTime is zero or less, no delay
if remainingTime <= 0 {
return 0, nil
}
// validate min delay is greater than 0
if minDelay == 0 {
return 0, fmt.Errorf("minDelay must be greater than zero when computing Delay")
}
// validate max delay is greater than 0
if maxDelay == 0 {
return 0, fmt.Errorf("maxDelay must be greater than zero when computing Delay")
}
// Get attempt ceiling to prevent integer overflow.
attemptCeiling := (math.Log(float64(maxDelay/minDelay)) / math.Log(2)) + 1
if attempt > int64(attemptCeiling) {
delay = maxDelay
} else {
// Compute exponential delay based on attempt.
ri := 1 << uint64(attempt-1)
// compute delay
delay = minDelay * time.Duration(ri)
}
if delay != minDelay {
// randomize to get jitter between min delay and delay value
d, err := rand.CryptoRandInt63n(int64(delay - minDelay))
if err != nil {
return 0, fmt.Errorf("error computing retry jitter, %w", err)
}
delay = time.Duration(d) + minDelay
}
// check if this is the last attempt possible and compute delay accordingly
if remainingTime-delay <= minDelay {
delay = remainingTime - minDelay
}
return delay, nil
}