Skip to content
Snippets Groups Projects
Verified Commit eb53d644 authored by Volker Schukai's avatar Volker Schukai :alien:
Browse files

chore: update go vendor

parent 4e2ab573
Branches
Tags
No related merge requests found
Showing
with 1870 additions and 0 deletions
// Code generated by aws/logging_generate.go DO NOT EDIT.
package aws
// ClientLogMode represents the logging mode of SDK clients. The client logging mode is a bit-field where
// each bit is a flag that describes the logging behavior for one or more client components.
// The entire 64-bit group is reserved for later expansion by the SDK.
//
// Example: Setting ClientLogMode to enable logging of retries and requests
//
// clientLogMode := aws.LogRetries | aws.LogRequest
//
// Example: Adding an additional log mode to an existing ClientLogMode value
//
// clientLogMode |= aws.LogResponse
type ClientLogMode uint64
// Supported ClientLogMode bits that can be configured to toggle logging of specific SDK events.
const (
LogSigning ClientLogMode = 1 << (64 - 1 - iota)
LogRetries
LogRequest
LogRequestWithBody
LogResponse
LogResponseWithBody
LogDeprecatedUsage
LogRequestEventMessage
LogResponseEventMessage
)
// IsSigning returns whether the Signing logging mode bit is set
func (m ClientLogMode) IsSigning() bool {
return m&LogSigning != 0
}
// IsRetries returns whether the Retries logging mode bit is set
func (m ClientLogMode) IsRetries() bool {
return m&LogRetries != 0
}
// IsRequest returns whether the Request logging mode bit is set
func (m ClientLogMode) IsRequest() bool {
return m&LogRequest != 0
}
// IsRequestWithBody returns whether the RequestWithBody logging mode bit is set
func (m ClientLogMode) IsRequestWithBody() bool {
return m&LogRequestWithBody != 0
}
// IsResponse returns whether the Response logging mode bit is set
func (m ClientLogMode) IsResponse() bool {
return m&LogResponse != 0
}
// IsResponseWithBody returns whether the ResponseWithBody logging mode bit is set
func (m ClientLogMode) IsResponseWithBody() bool {
return m&LogResponseWithBody != 0
}
// IsDeprecatedUsage returns whether the DeprecatedUsage logging mode bit is set
func (m ClientLogMode) IsDeprecatedUsage() bool {
return m&LogDeprecatedUsage != 0
}
// IsRequestEventMessage returns whether the RequestEventMessage logging mode bit is set
func (m ClientLogMode) IsRequestEventMessage() bool {
return m&LogRequestEventMessage != 0
}
// IsResponseEventMessage returns whether the ResponseEventMessage logging mode bit is set
func (m ClientLogMode) IsResponseEventMessage() bool {
return m&LogResponseEventMessage != 0
}
// ClearSigning clears the Signing logging mode bit
func (m *ClientLogMode) ClearSigning() {
*m &^= LogSigning
}
// ClearRetries clears the Retries logging mode bit
func (m *ClientLogMode) ClearRetries() {
*m &^= LogRetries
}
// ClearRequest clears the Request logging mode bit
func (m *ClientLogMode) ClearRequest() {
*m &^= LogRequest
}
// ClearRequestWithBody clears the RequestWithBody logging mode bit
func (m *ClientLogMode) ClearRequestWithBody() {
*m &^= LogRequestWithBody
}
// ClearResponse clears the Response logging mode bit
func (m *ClientLogMode) ClearResponse() {
*m &^= LogResponse
}
// ClearResponseWithBody clears the ResponseWithBody logging mode bit
func (m *ClientLogMode) ClearResponseWithBody() {
*m &^= LogResponseWithBody
}
// ClearDeprecatedUsage clears the DeprecatedUsage logging mode bit
func (m *ClientLogMode) ClearDeprecatedUsage() {
*m &^= LogDeprecatedUsage
}
// ClearRequestEventMessage clears the RequestEventMessage logging mode bit
func (m *ClientLogMode) ClearRequestEventMessage() {
*m &^= LogRequestEventMessage
}
// ClearResponseEventMessage clears the ResponseEventMessage logging mode bit
func (m *ClientLogMode) ClearResponseEventMessage() {
*m &^= LogResponseEventMessage
}
//go:build clientlogmode
// +build clientlogmode
package main
import (
"fmt"
"log"
"os"
"strings"
"text/template"
)
var config = struct {
ModeBits []string
}{
// Items should be appended only to keep bit-flag positions stable
ModeBits: []string{
"Signing",
"Retries",
"Request",
"RequestWithBody",
"Response",
"ResponseWithBody",
"DeprecatedUsage",
"RequestEventMessage",
"ResponseEventMessage",
},
}
func bitName(name string) string {
return strings.ToUpper(name[:1]) + name[1:]
}
var tmpl = template.Must(template.New("ClientLogMode").Funcs(map[string]interface{}{
"symbolName": func(name string) string {
return "Log" + bitName(name)
},
"bitName": bitName,
}).Parse(`// Code generated by aws/logging_generate.go DO NOT EDIT.
package aws
// ClientLogMode represents the logging mode of SDK clients. The client logging mode is a bit-field where
// each bit is a flag that describes the logging behavior for one or more client components.
// The entire 64-bit group is reserved for later expansion by the SDK.
//
// Example: Setting ClientLogMode to enable logging of retries and requests
// clientLogMode := aws.LogRetries | aws.LogRequest
//
// Example: Adding an additional log mode to an existing ClientLogMode value
// clientLogMode |= aws.LogResponse
type ClientLogMode uint64
// Supported ClientLogMode bits that can be configured to toggle logging of specific SDK events.
const (
{{- range $index, $field := .ModeBits }}
{{ (symbolName $field) }}{{- if (eq 0 $index) }} ClientLogMode = 1 << (64 - 1 - iota){{- end }}
{{- end }}
)
{{ range $_, $field := .ModeBits }}
// Is{{- bitName $field }} returns whether the {{ bitName $field }} logging mode bit is set
func (m ClientLogMode) Is{{- bitName $field }}() bool {
return m&{{- (symbolName $field) }} != 0
}
{{ end }}
{{- range $_, $field := .ModeBits }}
// Clear{{- bitName $field }} clears the {{ bitName $field }} logging mode bit
func (m *ClientLogMode) Clear{{- bitName $field }}() {
*m &^= {{ (symbolName $field) }}
}
{{ end -}}
`))
func main() {
uniqueBitFields := make(map[string]struct{})
for _, bitName := range config.ModeBits {
if _, ok := uniqueBitFields[strings.ToLower(bitName)]; ok {
panic(fmt.Sprintf("duplicate bit field: %s", bitName))
}
uniqueBitFields[bitName] = struct{}{}
}
file, err := os.Create("logging.go")
if err != nil {
log.Fatal(err)
}
defer file.Close()
err = tmpl.Execute(file, config)
if err != nil {
log.Fatal(err)
}
}
package middleware
import (
"context"
"github.com/aws/aws-sdk-go-v2/aws"
"github.com/aws/smithy-go/middleware"
)
// RegisterServiceMetadata registers metadata about the service and operation into the middleware context
// so that it is available at runtime for other middleware to introspect.
type RegisterServiceMetadata struct {
ServiceID string
SigningName string
Region string
OperationName string
}
// ID returns the middleware identifier.
func (s *RegisterServiceMetadata) ID() string {
return "RegisterServiceMetadata"
}
// HandleInitialize registers service metadata information into the middleware context, allowing for introspection.
func (s RegisterServiceMetadata) HandleInitialize(
ctx context.Context, in middleware.InitializeInput, next middleware.InitializeHandler,
) (out middleware.InitializeOutput, metadata middleware.Metadata, err error) {
if len(s.ServiceID) > 0 {
ctx = SetServiceID(ctx, s.ServiceID)
}
if len(s.SigningName) > 0 {
ctx = SetSigningName(ctx, s.SigningName)
}
if len(s.Region) > 0 {
ctx = setRegion(ctx, s.Region)
}
if len(s.OperationName) > 0 {
ctx = setOperationName(ctx, s.OperationName)
}
return next.HandleInitialize(ctx, in)
}
// service metadata keys for storing and lookup of runtime stack information.
type (
serviceIDKey struct{}
signingNameKey struct{}
signingRegionKey struct{}
regionKey struct{}
operationNameKey struct{}
partitionIDKey struct{}
requiresLegacyEndpointsKey struct{}
)
// GetServiceID retrieves the service id from the context.
//
// Scoped to stack values. Use github.com/aws/smithy-go/middleware#ClearStackValues
// to clear all stack values.
func GetServiceID(ctx context.Context) (v string) {
v, _ = middleware.GetStackValue(ctx, serviceIDKey{}).(string)
return v
}
// GetSigningName retrieves the service signing name from the context.
//
// Scoped to stack values. Use github.com/aws/smithy-go/middleware#ClearStackValues
// to clear all stack values.
//
// Deprecated: This value is unstable. The resolved signing name is available
// in the signer properties object passed to the signer.
func GetSigningName(ctx context.Context) (v string) {
v, _ = middleware.GetStackValue(ctx, signingNameKey{}).(string)
return v
}
// GetSigningRegion retrieves the region from the context.
//
// Scoped to stack values. Use github.com/aws/smithy-go/middleware#ClearStackValues
// to clear all stack values.
//
// Deprecated: This value is unstable. The resolved signing region is available
// in the signer properties object passed to the signer.
func GetSigningRegion(ctx context.Context) (v string) {
v, _ = middleware.GetStackValue(ctx, signingRegionKey{}).(string)
return v
}
// GetRegion retrieves the endpoint region from the context.
//
// Scoped to stack values. Use github.com/aws/smithy-go/middleware#ClearStackValues
// to clear all stack values.
func GetRegion(ctx context.Context) (v string) {
v, _ = middleware.GetStackValue(ctx, regionKey{}).(string)
return v
}
// GetOperationName retrieves the service operation metadata from the context.
//
// Scoped to stack values. Use github.com/aws/smithy-go/middleware#ClearStackValues
// to clear all stack values.
func GetOperationName(ctx context.Context) (v string) {
v, _ = middleware.GetStackValue(ctx, operationNameKey{}).(string)
return v
}
// GetPartitionID retrieves the endpoint partition id from the context.
//
// Scoped to stack values. Use github.com/aws/smithy-go/middleware#ClearStackValues
// to clear all stack values.
func GetPartitionID(ctx context.Context) string {
v, _ := middleware.GetStackValue(ctx, partitionIDKey{}).(string)
return v
}
// GetRequiresLegacyEndpoints the flag used to indicate if legacy endpoint
// customizations need to be executed.
//
// Scoped to stack values. Use github.com/aws/smithy-go/middleware#ClearStackValues
// to clear all stack values.
func GetRequiresLegacyEndpoints(ctx context.Context) bool {
v, _ := middleware.GetStackValue(ctx, requiresLegacyEndpointsKey{}).(bool)
return v
}
// SetRequiresLegacyEndpoints set or modifies the flag indicated that
// legacy endpoint customizations are needed.
//
// Scoped to stack values. Use github.com/aws/smithy-go/middleware#ClearStackValues
// to clear all stack values.
func SetRequiresLegacyEndpoints(ctx context.Context, value bool) context.Context {
return middleware.WithStackValue(ctx, requiresLegacyEndpointsKey{}, value)
}
// SetSigningName set or modifies the sigv4 or sigv4a signing name on the context.
//
// Scoped to stack values. Use github.com/aws/smithy-go/middleware#ClearStackValues
// to clear all stack values.
//
// Deprecated: This value is unstable. Use WithSigV4SigningName client option
// funcs instead.
func SetSigningName(ctx context.Context, value string) context.Context {
return middleware.WithStackValue(ctx, signingNameKey{}, value)
}
// SetSigningRegion sets or modifies the region on the context.
//
// Scoped to stack values. Use github.com/aws/smithy-go/middleware#ClearStackValues
// to clear all stack values.
//
// Deprecated: This value is unstable. Use WithSigV4SigningRegion client option
// funcs instead.
func SetSigningRegion(ctx context.Context, value string) context.Context {
return middleware.WithStackValue(ctx, signingRegionKey{}, value)
}
// SetServiceID sets the service id on the context.
//
// Scoped to stack values. Use github.com/aws/smithy-go/middleware#ClearStackValues
// to clear all stack values.
func SetServiceID(ctx context.Context, value string) context.Context {
return middleware.WithStackValue(ctx, serviceIDKey{}, value)
}
// setRegion sets the endpoint region on the context.
//
// Scoped to stack values. Use github.com/aws/smithy-go/middleware#ClearStackValues
// to clear all stack values.
func setRegion(ctx context.Context, value string) context.Context {
return middleware.WithStackValue(ctx, regionKey{}, value)
}
// setOperationName sets the service operation on the context.
//
// Scoped to stack values. Use github.com/aws/smithy-go/middleware#ClearStackValues
// to clear all stack values.
func setOperationName(ctx context.Context, value string) context.Context {
return middleware.WithStackValue(ctx, operationNameKey{}, value)
}
// SetPartitionID sets the partition id of a resolved region on the context
//
// Scoped to stack values. Use github.com/aws/smithy-go/middleware#ClearStackValues
// to clear all stack values.
func SetPartitionID(ctx context.Context, value string) context.Context {
return middleware.WithStackValue(ctx, partitionIDKey{}, value)
}
// EndpointSource key
type endpointSourceKey struct{}
// GetEndpointSource returns an endpoint source if set on context
func GetEndpointSource(ctx context.Context) (v aws.EndpointSource) {
v, _ = middleware.GetStackValue(ctx, endpointSourceKey{}).(aws.EndpointSource)
return v
}
// SetEndpointSource sets endpoint source on context
func SetEndpointSource(ctx context.Context, value aws.EndpointSource) context.Context {
return middleware.WithStackValue(ctx, endpointSourceKey{}, value)
}
type signingCredentialsKey struct{}
// GetSigningCredentials returns the credentials that were used for signing if set on context.
func GetSigningCredentials(ctx context.Context) (v aws.Credentials) {
v, _ = middleware.GetStackValue(ctx, signingCredentialsKey{}).(aws.Credentials)
return v
}
// SetSigningCredentials sets the credentails used for signing on the context.
func SetSigningCredentials(ctx context.Context, value aws.Credentials) context.Context {
return middleware.WithStackValue(ctx, signingCredentialsKey{}, value)
}
package middleware
import (
"context"
"fmt"
"time"
"github.com/aws/aws-sdk-go-v2/internal/rand"
"github.com/aws/aws-sdk-go-v2/internal/sdk"
"github.com/aws/smithy-go/logging"
"github.com/aws/smithy-go/middleware"
smithyrand "github.com/aws/smithy-go/rand"
smithyhttp "github.com/aws/smithy-go/transport/http"
)
// ClientRequestID is a Smithy BuildMiddleware that will generate a unique ID for logical API operation
// invocation.
type ClientRequestID struct{}
// ID the identifier for the ClientRequestID
func (r *ClientRequestID) ID() string {
return "ClientRequestID"
}
// HandleBuild attaches a unique operation invocation id for the operation to the request
func (r ClientRequestID) HandleBuild(ctx context.Context, in middleware.BuildInput, next middleware.BuildHandler) (
out middleware.BuildOutput, metadata middleware.Metadata, err error,
) {
req, ok := in.Request.(*smithyhttp.Request)
if !ok {
return out, metadata, fmt.Errorf("unknown transport type %T", req)
}
invocationID, err := smithyrand.NewUUID(rand.Reader).GetUUID()
if err != nil {
return out, metadata, err
}
const invocationIDHeader = "Amz-Sdk-Invocation-Id"
req.Header[invocationIDHeader] = append(req.Header[invocationIDHeader][:0], invocationID)
return next.HandleBuild(ctx, in)
}
// RecordResponseTiming records the response timing for the SDK client requests.
type RecordResponseTiming struct{}
// ID is the middleware identifier
func (a *RecordResponseTiming) ID() string {
return "RecordResponseTiming"
}
// HandleDeserialize calculates response metadata and clock skew
func (a RecordResponseTiming) HandleDeserialize(ctx context.Context, in middleware.DeserializeInput, next middleware.DeserializeHandler) (
out middleware.DeserializeOutput, metadata middleware.Metadata, err error,
) {
out, metadata, err = next.HandleDeserialize(ctx, in)
responseAt := sdk.NowTime()
setResponseAt(&metadata, responseAt)
var serverTime time.Time
switch resp := out.RawResponse.(type) {
case *smithyhttp.Response:
respDateHeader := resp.Header.Get("Date")
if len(respDateHeader) == 0 {
break
}
var parseErr error
serverTime, parseErr = smithyhttp.ParseTime(respDateHeader)
if parseErr != nil {
logger := middleware.GetLogger(ctx)
logger.Logf(logging.Warn, "failed to parse response Date header value, got %v",
parseErr.Error())
break
}
setServerTime(&metadata, serverTime)
}
if !serverTime.IsZero() {
attemptSkew := serverTime.Sub(responseAt)
setAttemptSkew(&metadata, attemptSkew)
}
return out, metadata, err
}
type responseAtKey struct{}
// GetResponseAt returns the time response was received at.
func GetResponseAt(metadata middleware.Metadata) (v time.Time, ok bool) {
v, ok = metadata.Get(responseAtKey{}).(time.Time)
return v, ok
}
// setResponseAt sets the response time on the metadata.
func setResponseAt(metadata *middleware.Metadata, v time.Time) {
metadata.Set(responseAtKey{}, v)
}
type serverTimeKey struct{}
// GetServerTime returns the server time for response.
func GetServerTime(metadata middleware.Metadata) (v time.Time, ok bool) {
v, ok = metadata.Get(serverTimeKey{}).(time.Time)
return v, ok
}
// setServerTime sets the server time on the metadata.
func setServerTime(metadata *middleware.Metadata, v time.Time) {
metadata.Set(serverTimeKey{}, v)
}
type attemptSkewKey struct{}
// GetAttemptSkew returns Attempt clock skew for response from metadata.
func GetAttemptSkew(metadata middleware.Metadata) (v time.Duration, ok bool) {
v, ok = metadata.Get(attemptSkewKey{}).(time.Duration)
return v, ok
}
// setAttemptSkew sets the attempt clock skew on the metadata.
func setAttemptSkew(metadata *middleware.Metadata, v time.Duration) {
metadata.Set(attemptSkewKey{}, v)
}
// AddClientRequestIDMiddleware adds ClientRequestID to the middleware stack
func AddClientRequestIDMiddleware(stack *middleware.Stack) error {
return stack.Build.Add(&ClientRequestID{}, middleware.After)
}
// AddRecordResponseTiming adds RecordResponseTiming middleware to the
// middleware stack.
func AddRecordResponseTiming(stack *middleware.Stack) error {
return stack.Deserialize.Add(&RecordResponseTiming{}, middleware.After)
}
// rawResponseKey is the accessor key used to store and access the
// raw response within the response metadata.
type rawResponseKey struct{}
// AddRawResponse middleware adds raw response on to the metadata
type AddRawResponse struct{}
// ID the identifier for the ClientRequestID
func (m *AddRawResponse) ID() string {
return "AddRawResponseToMetadata"
}
// HandleDeserialize adds raw response on the middleware metadata
func (m AddRawResponse) HandleDeserialize(ctx context.Context, in middleware.DeserializeInput, next middleware.DeserializeHandler) (
out middleware.DeserializeOutput, metadata middleware.Metadata, err error,
) {
out, metadata, err = next.HandleDeserialize(ctx, in)
metadata.Set(rawResponseKey{}, out.RawResponse)
return out, metadata, err
}
// AddRawResponseToMetadata adds middleware to the middleware stack that
// store raw response on to the metadata.
func AddRawResponseToMetadata(stack *middleware.Stack) error {
return stack.Deserialize.Add(&AddRawResponse{}, middleware.Before)
}
// GetRawResponse returns raw response set on metadata
func GetRawResponse(metadata middleware.Metadata) interface{} {
return metadata.Get(rawResponseKey{})
}
//go:build go1.16
// +build go1.16
package middleware
import "runtime"
func getNormalizedOSName() (os string) {
switch runtime.GOOS {
case "android":
os = "android"
case "linux":
os = "linux"
case "windows":
os = "windows"
case "darwin":
os = "macos"
case "ios":
os = "ios"
default:
os = "other"
}
return os
}
//go:build !go1.16
// +build !go1.16
package middleware
import "runtime"
func getNormalizedOSName() (os string) {
switch runtime.GOOS {
case "android":
os = "android"
case "linux":
os = "linux"
case "windows":
os = "windows"
case "darwin":
// Due to Apple M1 we can't distinguish between macOS and iOS when GOOS/GOARCH is darwin/amd64
// For now declare this as "other" until we have a better detection mechanism.
fallthrough
default:
os = "other"
}
return os
}
package middleware
import (
"context"
"fmt"
"github.com/aws/smithy-go/middleware"
smithyhttp "github.com/aws/smithy-go/transport/http"
"os"
)
const envAwsLambdaFunctionName = "AWS_LAMBDA_FUNCTION_NAME"
const envAmznTraceID = "_X_AMZN_TRACE_ID"
const amznTraceIDHeader = "X-Amzn-Trace-Id"
// AddRecursionDetection adds recursionDetection to the middleware stack
func AddRecursionDetection(stack *middleware.Stack) error {
return stack.Build.Add(&RecursionDetection{}, middleware.After)
}
// RecursionDetection detects Lambda environment and sets its X-Ray trace ID to request header if absent
// to avoid recursion invocation in Lambda
type RecursionDetection struct{}
// ID returns the middleware identifier
func (m *RecursionDetection) ID() string {
return "RecursionDetection"
}
// HandleBuild detects Lambda environment and adds its trace ID to request header if absent
func (m *RecursionDetection) HandleBuild(
ctx context.Context, in middleware.BuildInput, next middleware.BuildHandler,
) (
out middleware.BuildOutput, metadata middleware.Metadata, err error,
) {
req, ok := in.Request.(*smithyhttp.Request)
if !ok {
return out, metadata, fmt.Errorf("unknown request type %T", req)
}
_, hasLambdaEnv := os.LookupEnv(envAwsLambdaFunctionName)
xAmznTraceID, hasTraceID := os.LookupEnv(envAmznTraceID)
value := req.Header.Get(amznTraceIDHeader)
// only set the X-Amzn-Trace-Id header when it is not set initially, the
// current environment is Lambda and the _X_AMZN_TRACE_ID env variable exists
if value != "" || !hasLambdaEnv || !hasTraceID {
return next.HandleBuild(ctx, in)
}
req.Header.Set(amznTraceIDHeader, percentEncode(xAmznTraceID))
return next.HandleBuild(ctx, in)
}
func percentEncode(s string) string {
upperhex := "0123456789ABCDEF"
hexCount := 0
for i := 0; i < len(s); i++ {
c := s[i]
if shouldEncode(c) {
hexCount++
}
}
if hexCount == 0 {
return s
}
required := len(s) + 2*hexCount
t := make([]byte, required)
j := 0
for i := 0; i < len(s); i++ {
if c := s[i]; shouldEncode(c) {
t[j] = '%'
t[j+1] = upperhex[c>>4]
t[j+2] = upperhex[c&15]
j += 3
} else {
t[j] = c
j++
}
}
return string(t)
}
func shouldEncode(c byte) bool {
if 'a' <= c && c <= 'z' || 'A' <= c && c <= 'Z' || '0' <= c && c <= '9' {
return false
}
switch c {
case '-', '=', ';', ':', '+', '&', '[', ']', '{', '}', '"', '\'', ',':
return false
default:
return true
}
}
package middleware
import (
"github.com/aws/smithy-go/middleware"
)
// requestIDKey is used to retrieve request id from response metadata
type requestIDKey struct{}
// SetRequestIDMetadata sets the provided request id over middleware metadata
func SetRequestIDMetadata(metadata *middleware.Metadata, id string) {
metadata.Set(requestIDKey{}, id)
}
// GetRequestIDMetadata retrieves the request id from middleware metadata
// returns string and bool indicating value of request id, whether request id was set.
func GetRequestIDMetadata(metadata middleware.Metadata) (string, bool) {
if !metadata.Has(requestIDKey{}) {
return "", false
}
v, ok := metadata.Get(requestIDKey{}).(string)
if !ok {
return "", true
}
return v, true
}
package middleware
import (
"context"
"github.com/aws/smithy-go/middleware"
"github.com/aws/smithy-go/tracing"
smithyhttp "github.com/aws/smithy-go/transport/http"
)
// AddRequestIDRetrieverMiddleware adds request id retriever middleware
func AddRequestIDRetrieverMiddleware(stack *middleware.Stack) error {
// add error wrapper middleware before operation deserializers so that it can wrap the error response
// returned by operation deserializers
return stack.Deserialize.Insert(&RequestIDRetriever{}, "OperationDeserializer", middleware.Before)
}
// RequestIDRetriever middleware captures the AWS service request ID from the
// raw response.
type RequestIDRetriever struct {
}
// ID returns the middleware identifier
func (m *RequestIDRetriever) ID() string {
return "RequestIDRetriever"
}
// HandleDeserialize pulls the AWS request ID from the response, storing it in
// operation metadata.
func (m *RequestIDRetriever) HandleDeserialize(ctx context.Context, in middleware.DeserializeInput, next middleware.DeserializeHandler) (
out middleware.DeserializeOutput, metadata middleware.Metadata, err error,
) {
out, metadata, err = next.HandleDeserialize(ctx, in)
resp, ok := out.RawResponse.(*smithyhttp.Response)
if !ok {
// No raw response to wrap with.
return out, metadata, err
}
// Different header which can map to request id
requestIDHeaderList := []string{"X-Amzn-Requestid", "X-Amz-RequestId"}
for _, h := range requestIDHeaderList {
// check for headers known to contain Request id
if v := resp.Header.Get(h); len(v) != 0 {
// set reqID on metadata for successful responses.
SetRequestIDMetadata(&metadata, v)
span, _ := tracing.GetSpan(ctx)
span.SetProperty("aws.request_id", v)
break
}
}
return out, metadata, err
}
package middleware
import (
"context"
"fmt"
"os"
"runtime"
"sort"
"strings"
"github.com/aws/aws-sdk-go-v2/aws"
"github.com/aws/smithy-go/middleware"
smithyhttp "github.com/aws/smithy-go/transport/http"
)
var languageVersion = strings.TrimPrefix(runtime.Version(), "go")
// SDKAgentKeyType is the metadata type to add to the SDK agent string
type SDKAgentKeyType int
// The set of valid SDKAgentKeyType constants. If an unknown value is assigned for SDKAgentKeyType it will
// be mapped to AdditionalMetadata.
const (
_ SDKAgentKeyType = iota
APIMetadata
OperatingSystemMetadata
LanguageMetadata
EnvironmentMetadata
FeatureMetadata
ConfigMetadata
FrameworkMetadata
AdditionalMetadata
ApplicationIdentifier
FeatureMetadata2
)
// Hardcoded value to specify which version of the user agent we're using
const uaMetadata = "ua/2.1"
func (k SDKAgentKeyType) string() string {
switch k {
case APIMetadata:
return "api"
case OperatingSystemMetadata:
return "os"
case LanguageMetadata:
return "lang"
case EnvironmentMetadata:
return "exec-env"
case FeatureMetadata:
return "ft"
case ConfigMetadata:
return "cfg"
case FrameworkMetadata:
return "lib"
case ApplicationIdentifier:
return "app"
case FeatureMetadata2:
return "m"
case AdditionalMetadata:
fallthrough
default:
return "md"
}
}
const execEnvVar = `AWS_EXECUTION_ENV`
var validChars = map[rune]bool{
'!': true, '#': true, '$': true, '%': true, '&': true, '\'': true, '*': true, '+': true,
'-': true, '.': true, '^': true, '_': true, '`': true, '|': true, '~': true,
}
// UserAgentFeature enumerates tracked SDK features.
type UserAgentFeature string
// Enumerates UserAgentFeature.
const (
UserAgentFeatureResourceModel UserAgentFeature = "A" // n/a (we don't generate separate resource types)
UserAgentFeatureWaiter = "B"
UserAgentFeaturePaginator = "C"
UserAgentFeatureRetryModeLegacy = "D" // n/a (equivalent to standard)
UserAgentFeatureRetryModeStandard = "E"
UserAgentFeatureRetryModeAdaptive = "F"
UserAgentFeatureS3Transfer = "G"
UserAgentFeatureS3CryptoV1N = "H" // n/a (crypto client is external)
UserAgentFeatureS3CryptoV2 = "I" // n/a
UserAgentFeatureS3ExpressBucket = "J"
UserAgentFeatureS3AccessGrants = "K" // not yet implemented
UserAgentFeatureGZIPRequestCompression = "L"
UserAgentFeatureProtocolRPCV2CBOR = "M"
UserAgentFeatureAccountIDEndpoint = "O" // DO NOT IMPLEMENT: rules output is not currently defined. SDKs should not parse endpoints for feature information.
UserAgentFeatureAccountIDModePreferred = "P"
UserAgentFeatureAccountIDModeDisabled = "Q"
UserAgentFeatureAccountIDModeRequired = "R"
UserAgentFeatureRequestChecksumCRC32 = "U"
UserAgentFeatureRequestChecksumCRC32C = "V"
UserAgentFeatureRequestChecksumCRC64 = "W"
UserAgentFeatureRequestChecksumSHA1 = "X"
UserAgentFeatureRequestChecksumSHA256 = "Y"
UserAgentFeatureRequestChecksumWhenSupported = "Z"
UserAgentFeatureRequestChecksumWhenRequired = "a"
UserAgentFeatureResponseChecksumWhenSupported = "b"
UserAgentFeatureResponseChecksumWhenRequired = "c"
)
// RequestUserAgent is a build middleware that set the User-Agent for the request.
type RequestUserAgent struct {
sdkAgent, userAgent *smithyhttp.UserAgentBuilder
features map[UserAgentFeature]struct{}
}
// NewRequestUserAgent returns a new requestUserAgent which will set the User-Agent and X-Amz-User-Agent for the
// request.
//
// User-Agent example:
//
// aws-sdk-go-v2/1.2.3
//
// X-Amz-User-Agent example:
//
// aws-sdk-go-v2/1.2.3 md/GOOS/linux md/GOARCH/amd64 lang/go/1.15
func NewRequestUserAgent() *RequestUserAgent {
userAgent, sdkAgent := smithyhttp.NewUserAgentBuilder(), smithyhttp.NewUserAgentBuilder()
addProductName(userAgent)
addUserAgentMetadata(userAgent)
addProductName(sdkAgent)
r := &RequestUserAgent{
sdkAgent: sdkAgent,
userAgent: userAgent,
features: map[UserAgentFeature]struct{}{},
}
addSDKMetadata(r)
return r
}
func addSDKMetadata(r *RequestUserAgent) {
r.AddSDKAgentKey(OperatingSystemMetadata, getNormalizedOSName())
r.AddSDKAgentKeyValue(LanguageMetadata, "go", languageVersion)
r.AddSDKAgentKeyValue(AdditionalMetadata, "GOOS", runtime.GOOS)
r.AddSDKAgentKeyValue(AdditionalMetadata, "GOARCH", runtime.GOARCH)
if ev := os.Getenv(execEnvVar); len(ev) > 0 {
r.AddSDKAgentKey(EnvironmentMetadata, ev)
}
}
func addProductName(builder *smithyhttp.UserAgentBuilder) {
builder.AddKeyValue(aws.SDKName, aws.SDKVersion)
}
func addUserAgentMetadata(builder *smithyhttp.UserAgentBuilder) {
builder.AddKey(uaMetadata)
}
// AddUserAgentKey retrieves a requestUserAgent from the provided stack, or initializes one.
func AddUserAgentKey(key string) func(*middleware.Stack) error {
return func(stack *middleware.Stack) error {
requestUserAgent, err := getOrAddRequestUserAgent(stack)
if err != nil {
return err
}
requestUserAgent.AddUserAgentKey(key)
return nil
}
}
// AddUserAgentKeyValue retrieves a requestUserAgent from the provided stack, or initializes one.
func AddUserAgentKeyValue(key, value string) func(*middleware.Stack) error {
return func(stack *middleware.Stack) error {
requestUserAgent, err := getOrAddRequestUserAgent(stack)
if err != nil {
return err
}
requestUserAgent.AddUserAgentKeyValue(key, value)
return nil
}
}
// AddSDKAgentKey retrieves a requestUserAgent from the provided stack, or initializes one.
func AddSDKAgentKey(keyType SDKAgentKeyType, key string) func(*middleware.Stack) error {
return func(stack *middleware.Stack) error {
requestUserAgent, err := getOrAddRequestUserAgent(stack)
if err != nil {
return err
}
requestUserAgent.AddSDKAgentKey(keyType, key)
return nil
}
}
// AddSDKAgentKeyValue retrieves a requestUserAgent from the provided stack, or initializes one.
func AddSDKAgentKeyValue(keyType SDKAgentKeyType, key, value string) func(*middleware.Stack) error {
return func(stack *middleware.Stack) error {
requestUserAgent, err := getOrAddRequestUserAgent(stack)
if err != nil {
return err
}
requestUserAgent.AddSDKAgentKeyValue(keyType, key, value)
return nil
}
}
// AddRequestUserAgentMiddleware registers a requestUserAgent middleware on the stack if not present.
func AddRequestUserAgentMiddleware(stack *middleware.Stack) error {
_, err := getOrAddRequestUserAgent(stack)
return err
}
func getOrAddRequestUserAgent(stack *middleware.Stack) (*RequestUserAgent, error) {
id := (*RequestUserAgent)(nil).ID()
bm, ok := stack.Build.Get(id)
if !ok {
bm = NewRequestUserAgent()
err := stack.Build.Add(bm, middleware.After)
if err != nil {
return nil, err
}
}
requestUserAgent, ok := bm.(*RequestUserAgent)
if !ok {
return nil, fmt.Errorf("%T for %s middleware did not match expected type", bm, id)
}
return requestUserAgent, nil
}
// AddUserAgentKey adds the component identified by name to the User-Agent string.
func (u *RequestUserAgent) AddUserAgentKey(key string) {
u.userAgent.AddKey(strings.Map(rules, key))
}
// AddUserAgentKeyValue adds the key identified by the given name and value to the User-Agent string.
func (u *RequestUserAgent) AddUserAgentKeyValue(key, value string) {
u.userAgent.AddKeyValue(strings.Map(rules, key), strings.Map(rules, value))
}
// AddUserAgentFeature adds the feature ID to the tracking list to be emitted
// in the final User-Agent string.
func (u *RequestUserAgent) AddUserAgentFeature(feature UserAgentFeature) {
u.features[feature] = struct{}{}
}
// AddSDKAgentKey adds the component identified by name to the User-Agent string.
func (u *RequestUserAgent) AddSDKAgentKey(keyType SDKAgentKeyType, key string) {
// TODO: should target sdkAgent
u.userAgent.AddKey(keyType.string() + "/" + strings.Map(rules, key))
}
// AddSDKAgentKeyValue adds the key identified by the given name and value to the User-Agent string.
func (u *RequestUserAgent) AddSDKAgentKeyValue(keyType SDKAgentKeyType, key, value string) {
// TODO: should target sdkAgent
u.userAgent.AddKeyValue(keyType.string(), strings.Map(rules, key)+"#"+strings.Map(rules, value))
}
// ID the name of the middleware.
func (u *RequestUserAgent) ID() string {
return "UserAgent"
}
// HandleBuild adds or appends the constructed user agent to the request.
func (u *RequestUserAgent) HandleBuild(ctx context.Context, in middleware.BuildInput, next middleware.BuildHandler) (
out middleware.BuildOutput, metadata middleware.Metadata, err error,
) {
switch req := in.Request.(type) {
case *smithyhttp.Request:
u.addHTTPUserAgent(req)
// TODO: To be re-enabled
// u.addHTTPSDKAgent(req)
default:
return out, metadata, fmt.Errorf("unknown transport type %T", in)
}
return next.HandleBuild(ctx, in)
}
func (u *RequestUserAgent) addHTTPUserAgent(request *smithyhttp.Request) {
const userAgent = "User-Agent"
if len(u.features) > 0 {
updateHTTPHeader(request, userAgent, buildFeatureMetrics(u.features))
}
updateHTTPHeader(request, userAgent, u.userAgent.Build())
}
func (u *RequestUserAgent) addHTTPSDKAgent(request *smithyhttp.Request) {
const sdkAgent = "X-Amz-User-Agent"
updateHTTPHeader(request, sdkAgent, u.sdkAgent.Build())
}
func updateHTTPHeader(request *smithyhttp.Request, header string, value string) {
var current string
if v := request.Header[header]; len(v) > 0 {
current = v[0]
}
if len(current) > 0 {
current = value + " " + current
} else {
current = value
}
request.Header[header] = append(request.Header[header][:0], current)
}
func rules(r rune) rune {
switch {
case r >= '0' && r <= '9':
return r
case r >= 'A' && r <= 'Z' || r >= 'a' && r <= 'z':
return r
case validChars[r]:
return r
default:
return '-'
}
}
func buildFeatureMetrics(features map[UserAgentFeature]struct{}) string {
fs := make([]string, 0, len(features))
for f := range features {
fs = append(fs, string(f))
}
sort.Strings(fs)
return fmt.Sprintf("%s/%s", FeatureMetadata2.string(), strings.Join(fs, ","))
}
package query
import (
"net/url"
"strconv"
)
// Array represents the encoding of Query lists and sets. A Query array is a
// representation of a list of values of a fixed type. A serialized array might
// look like the following:
//
// ListName.member.1=foo
// &ListName.member.2=bar
// &Listname.member.3=baz
type Array struct {
// The query values to add the array to.
values url.Values
// The array's prefix, which includes the names of all parent structures
// and ends with the name of the list. For example, the prefix might be
// "ParentStructure.ListName". This prefix will be used to form the full
// keys for each element in the list. For example, an entry might have the
// key "ParentStructure.ListName.member.MemberName.1".
//
// When the array is not flat the prefix will contain the memberName otherwise the memberName is ignored
prefix string
// Elements are stored in values, so we keep track of the list size here.
size int32
// Empty lists are encoded as "<prefix>=", if we add a value later we will
// remove this encoding
emptyValue Value
}
func newArray(values url.Values, prefix string, flat bool, memberName string) *Array {
emptyValue := newValue(values, prefix, flat)
emptyValue.String("")
if !flat {
// This uses string concatenation in place of fmt.Sprintf as fmt.Sprintf has a much higher resource overhead
prefix = prefix + keySeparator + memberName
}
return &Array{
values: values,
prefix: prefix,
emptyValue: emptyValue,
}
}
// Value adds a new element to the Query Array. Returns a Value type used to
// encode the array element.
func (a *Array) Value() Value {
if a.size == 0 {
delete(a.values, a.emptyValue.key)
}
// Query lists start a 1, so adjust the size first
a.size++
// Lists can't have flat members
// This uses string concatenation in place of fmt.Sprintf as fmt.Sprintf has a much higher resource overhead
return newValue(a.values, a.prefix+keySeparator+strconv.FormatInt(int64(a.size), 10), false)
}
package query
import (
"io"
"net/url"
"sort"
)
// Encoder is a Query encoder that supports construction of Query body
// values using methods.
type Encoder struct {
// The query values that will be built up to manage encoding.
values url.Values
// The writer that the encoded body will be written to.
writer io.Writer
Value
}
// NewEncoder returns a new Query body encoder
func NewEncoder(writer io.Writer) *Encoder {
values := url.Values{}
return &Encoder{
values: values,
writer: writer,
Value: newBaseValue(values),
}
}
// Encode returns the []byte slice representing the current
// state of the Query encoder.
func (e Encoder) Encode() error {
ws, ok := e.writer.(interface{ WriteString(string) (int, error) })
if !ok {
// Fall back to less optimal byte slice casting if WriteString isn't available.
ws = &wrapWriteString{writer: e.writer}
}
// Get the keys and sort them to have a stable output
keys := make([]string, 0, len(e.values))
for k := range e.values {
keys = append(keys, k)
}
sort.Strings(keys)
isFirstEntry := true
for _, key := range keys {
queryValues := e.values[key]
escapedKey := url.QueryEscape(key)
for _, value := range queryValues {
if !isFirstEntry {
if _, err := ws.WriteString(`&`); err != nil {
return err
}
} else {
isFirstEntry = false
}
if _, err := ws.WriteString(escapedKey); err != nil {
return err
}
if _, err := ws.WriteString(`=`); err != nil {
return err
}
if _, err := ws.WriteString(url.QueryEscape(value)); err != nil {
return err
}
}
}
return nil
}
// wrapWriteString wraps an io.Writer to provide a WriteString method
// where one is not available.
type wrapWriteString struct {
writer io.Writer
}
// WriteString writes a string to the wrapped writer by casting it to
// a byte array first.
func (w wrapWriteString) WriteString(v string) (int, error) {
return w.writer.Write([]byte(v))
}
package query
import (
"fmt"
"net/url"
)
// Map represents the encoding of Query maps. A Query map is a representation
// of a mapping of arbitrary string keys to arbitrary values of a fixed type.
// A Map differs from an Object in that the set of keys is not fixed, in that
// the values must all be of the same type, and that map entries are ordered.
// A serialized map might look like the following:
//
// MapName.entry.1.key=Foo
// &MapName.entry.1.value=spam
// &MapName.entry.2.key=Bar
// &MapName.entry.2.value=eggs
type Map struct {
// The query values to add the map to.
values url.Values
// The map's prefix, which includes the names of all parent structures
// and ends with the name of the object. For example, the prefix might be
// "ParentStructure.MapName". This prefix will be used to form the full
// keys for each key-value pair of the map. For example, a value might have
// the key "ParentStructure.MapName.1.value".
//
// While this is currently represented as a string that gets added to, it
// could also be represented as a stack that only gets condensed into a
// string when a finalized key is created. This could potentially reduce
// allocations.
prefix string
// Whether the map is flat or not. A map that is not flat will produce the
// following entries to the url.Values for a given key-value pair:
// MapName.entry.1.KeyLocationName=mykey
// MapName.entry.1.ValueLocationName=myvalue
// A map that is flat will produce the following:
// MapName.1.KeyLocationName=mykey
// MapName.1.ValueLocationName=myvalue
flat bool
// The location name of the key. In most cases this should be "key".
keyLocationName string
// The location name of the value. In most cases this should be "value".
valueLocationName string
// Elements are stored in values, so we keep track of the list size here.
size int32
}
func newMap(values url.Values, prefix string, flat bool, keyLocationName string, valueLocationName string) *Map {
return &Map{
values: values,
prefix: prefix,
flat: flat,
keyLocationName: keyLocationName,
valueLocationName: valueLocationName,
}
}
// Key adds the given named key to the Query map.
// Returns a Value encoder that should be used to encode a Query value type.
func (m *Map) Key(name string) Value {
// Query lists start a 1, so adjust the size first
m.size++
var key string
var value string
if m.flat {
key = fmt.Sprintf("%s.%d.%s", m.prefix, m.size, m.keyLocationName)
value = fmt.Sprintf("%s.%d.%s", m.prefix, m.size, m.valueLocationName)
} else {
key = fmt.Sprintf("%s.entry.%d.%s", m.prefix, m.size, m.keyLocationName)
value = fmt.Sprintf("%s.entry.%d.%s", m.prefix, m.size, m.valueLocationName)
}
// The key can only be a string, so we just go ahead and set it here
newValue(m.values, key, false).String(name)
// Maps can't have flat members
return newValue(m.values, value, false)
}
package query
import (
"context"
"fmt"
"io/ioutil"
"github.com/aws/smithy-go/middleware"
smithyhttp "github.com/aws/smithy-go/transport/http"
)
// AddAsGetRequestMiddleware adds a middleware to the Serialize stack after the
// operation serializer that will convert the query request body to a GET
// operation with the query message in the HTTP request querystring.
func AddAsGetRequestMiddleware(stack *middleware.Stack) error {
return stack.Serialize.Insert(&asGetRequest{}, "OperationSerializer", middleware.After)
}
type asGetRequest struct{}
func (*asGetRequest) ID() string { return "Query:AsGetRequest" }
func (m *asGetRequest) HandleSerialize(
ctx context.Context, input middleware.SerializeInput, next middleware.SerializeHandler,
) (
out middleware.SerializeOutput, metadata middleware.Metadata, err error,
) {
req, ok := input.Request.(*smithyhttp.Request)
if !ok {
return out, metadata, fmt.Errorf("expect smithy HTTP Request, got %T", input.Request)
}
req.Method = "GET"
// If the stream is not set, nothing else to do.
stream := req.GetStream()
if stream == nil {
return next.HandleSerialize(ctx, input)
}
// Clear the stream since there will not be any body.
req.Header.Del("Content-Type")
req, err = req.SetStream(nil)
if err != nil {
return out, metadata, fmt.Errorf("unable update request body %w", err)
}
input.Request = req
// Update request query with the body's query string value.
delim := ""
if len(req.URL.RawQuery) != 0 {
delim = "&"
}
b, err := ioutil.ReadAll(stream)
if err != nil {
return out, metadata, fmt.Errorf("unable to get request body %w", err)
}
req.URL.RawQuery += delim + string(b)
return next.HandleSerialize(ctx, input)
}
package query
import "net/url"
// Object represents the encoding of Query structures and unions. A Query
// object is a representation of a mapping of string keys to arbitrary
// values where there is a fixed set of keys whose values each have their
// own known type. A serialized object might look like the following:
//
// ObjectName.Foo=value
// &ObjectName.Bar=5
type Object struct {
// The query values to add the object to.
values url.Values
// The object's prefix, which includes the names of all parent structures
// and ends with the name of the object. For example, the prefix might be
// "ParentStructure.ObjectName". This prefix will be used to form the full
// keys for each member of the object. For example, a member might have the
// key "ParentStructure.ObjectName.MemberName".
//
// While this is currently represented as a string that gets added to, it
// could also be represented as a stack that only gets condensed into a
// string when a finalized key is created. This could potentially reduce
// allocations.
prefix string
}
func newObject(values url.Values, prefix string) *Object {
return &Object{
values: values,
prefix: prefix,
}
}
// Key adds the given named key to the Query object.
// Returns a Value encoder that should be used to encode a Query value type.
func (o *Object) Key(name string) Value {
return o.key(name, false)
}
// KeyWithValues adds the given named key to the Query object.
// Returns a Value encoder that should be used to encode a Query list of values.
func (o *Object) KeyWithValues(name string) Value {
return o.keyWithValues(name, false)
}
// FlatKey adds the given named key to the Query object.
// Returns a Value encoder that should be used to encode a Query value type. The
// value will be flattened if it is a map or array.
func (o *Object) FlatKey(name string) Value {
return o.key(name, true)
}
func (o *Object) key(name string, flatValue bool) Value {
if o.prefix != "" {
// This uses string concatenation in place of fmt.Sprintf as fmt.Sprintf has a much higher resource overhead
return newValue(o.values, o.prefix+keySeparator+name, flatValue)
}
return newValue(o.values, name, flatValue)
}
func (o *Object) keyWithValues(name string, flatValue bool) Value {
if o.prefix != "" {
// This uses string concatenation in place of fmt.Sprintf as fmt.Sprintf has a much higher resource overhead
return newAppendValue(o.values, o.prefix+keySeparator+name, flatValue)
}
return newAppendValue(o.values, name, flatValue)
}
package query
import (
"math/big"
"net/url"
"github.com/aws/smithy-go/encoding/httpbinding"
)
const keySeparator = "."
// Value represents a Query Value type.
type Value struct {
// The query values to add the value to.
values url.Values
// The value's key, which will form the prefix for complex types.
key string
// Whether the value should be flattened or not if it's a flattenable type.
flat bool
queryValue httpbinding.QueryValue
}
func newValue(values url.Values, key string, flat bool) Value {
return Value{
values: values,
key: key,
flat: flat,
queryValue: httpbinding.NewQueryValue(values, key, false),
}
}
func newAppendValue(values url.Values, key string, flat bool) Value {
return Value{
values: values,
key: key,
flat: flat,
queryValue: httpbinding.NewQueryValue(values, key, true),
}
}
func newBaseValue(values url.Values) Value {
return Value{
values: values,
queryValue: httpbinding.NewQueryValue(nil, "", false),
}
}
// Array returns a new Array encoder.
func (qv Value) Array(locationName string) *Array {
return newArray(qv.values, qv.key, qv.flat, locationName)
}
// Object returns a new Object encoder.
func (qv Value) Object() *Object {
return newObject(qv.values, qv.key)
}
// Map returns a new Map encoder.
func (qv Value) Map(keyLocationName string, valueLocationName string) *Map {
return newMap(qv.values, qv.key, qv.flat, keyLocationName, valueLocationName)
}
// Base64EncodeBytes encodes v as a base64 query string value.
// This is intended to enable compatibility with the JSON encoder.
func (qv Value) Base64EncodeBytes(v []byte) {
qv.queryValue.Blob(v)
}
// Boolean encodes v as a query string value
func (qv Value) Boolean(v bool) {
qv.queryValue.Boolean(v)
}
// String encodes v as a query string value
func (qv Value) String(v string) {
qv.queryValue.String(v)
}
// Byte encodes v as a query string value
func (qv Value) Byte(v int8) {
qv.queryValue.Byte(v)
}
// Short encodes v as a query string value
func (qv Value) Short(v int16) {
qv.queryValue.Short(v)
}
// Integer encodes v as a query string value
func (qv Value) Integer(v int32) {
qv.queryValue.Integer(v)
}
// Long encodes v as a query string value
func (qv Value) Long(v int64) {
qv.queryValue.Long(v)
}
// Float encodes v as a query string value
func (qv Value) Float(v float32) {
qv.queryValue.Float(v)
}
// Double encodes v as a query string value
func (qv Value) Double(v float64) {
qv.queryValue.Double(v)
}
// BigInteger encodes v as a query string value
func (qv Value) BigInteger(v *big.Int) {
qv.queryValue.BigInteger(v)
}
// BigDecimal encodes v as a query string value
func (qv Value) BigDecimal(v *big.Float) {
qv.queryValue.BigDecimal(v)
}
package restjson
import (
"encoding/json"
"io"
"strings"
"github.com/aws/smithy-go"
)
// GetErrorInfo util looks for code, __type, and message members in the
// json body. These members are optionally available, and the function
// returns the value of member if it is available. This function is useful to
// identify the error code, msg in a REST JSON error response.
func GetErrorInfo(decoder *json.Decoder) (errorType string, message string, err error) {
var errInfo struct {
Code string
Type string `json:"__type"`
Message string
}
err = decoder.Decode(&errInfo)
if err != nil {
if err == io.EOF {
return errorType, message, nil
}
return errorType, message, err
}
// assign error type
if len(errInfo.Code) != 0 {
errorType = errInfo.Code
} else if len(errInfo.Type) != 0 {
errorType = errInfo.Type
}
// assign error message
if len(errInfo.Message) != 0 {
message = errInfo.Message
}
// sanitize error
if len(errorType) != 0 {
errorType = SanitizeErrorCode(errorType)
}
return errorType, message, nil
}
// SanitizeErrorCode sanitizes the errorCode string .
// The rule for sanitizing is if a `:` character is present, then take only the
// contents before the first : character in the value.
// If a # character is present, then take only the contents after the
// first # character in the value.
func SanitizeErrorCode(errorCode string) string {
if strings.ContainsAny(errorCode, ":") {
errorCode = strings.SplitN(errorCode, ":", 2)[0]
}
if strings.ContainsAny(errorCode, "#") {
errorCode = strings.SplitN(errorCode, "#", 2)[1]
}
return errorCode
}
// GetSmithyGenericAPIError returns smithy generic api error and an error interface.
// Takes in json decoder, and error Code string as args. The function retrieves error message
// and error code from the decoder body. If errorCode of length greater than 0 is passed in as
// an argument, it is used instead.
func GetSmithyGenericAPIError(decoder *json.Decoder, errorCode string) (*smithy.GenericAPIError, error) {
errorType, message, err := GetErrorInfo(decoder)
if err != nil {
return nil, err
}
if len(errorCode) == 0 {
errorCode = errorType
}
return &smithy.GenericAPIError{
Code: errorCode,
Message: message,
}, nil
}
package xml
import (
"encoding/xml"
"fmt"
"io"
)
// ErrorComponents represents the error response fields
// that will be deserialized from an xml error response body
type ErrorComponents struct {
Code string
Message string
RequestID string
}
// GetErrorResponseComponents returns the error fields from an xml error response body
func GetErrorResponseComponents(r io.Reader, noErrorWrapping bool) (ErrorComponents, error) {
if noErrorWrapping {
var errResponse noWrappedErrorResponse
if err := xml.NewDecoder(r).Decode(&errResponse); err != nil && err != io.EOF {
return ErrorComponents{}, fmt.Errorf("error while deserializing xml error response: %w", err)
}
return ErrorComponents(errResponse), nil
}
var errResponse wrappedErrorResponse
if err := xml.NewDecoder(r).Decode(&errResponse); err != nil && err != io.EOF {
return ErrorComponents{}, fmt.Errorf("error while deserializing xml error response: %w", err)
}
return ErrorComponents(errResponse), nil
}
// noWrappedErrorResponse represents the error response body with
// no internal Error wrapping
type noWrappedErrorResponse struct {
Code string `xml:"Code"`
Message string `xml:"Message"`
RequestID string `xml:"RequestId"`
}
// wrappedErrorResponse represents the error response body
// wrapped within Error
type wrappedErrorResponse struct {
Code string `xml:"Error>Code"`
Message string `xml:"Error>Message"`
RequestID string `xml:"RequestId"`
}
package ratelimit
import "context"
// None implements a no-op rate limiter which effectively disables client-side
// rate limiting (also known as "retry quotas").
//
// GetToken does nothing and always returns a nil error. The returned
// token-release function does nothing, and always returns a nil error.
//
// AddTokens does nothing and always returns a nil error.
var None = &none{}
type none struct{}
func (*none) GetToken(ctx context.Context, cost uint) (func() error, error) {
return func() error { return nil }, nil
}
func (*none) AddTokens(v uint) error { return nil }
package ratelimit
import (
"sync"
)
// TokenBucket provides a concurrency safe utility for adding and removing
// tokens from the available token bucket.
type TokenBucket struct {
remainingTokens uint
maxCapacity uint
minCapacity uint
mu sync.Mutex
}
// NewTokenBucket returns an initialized TokenBucket with the capacity
// specified.
func NewTokenBucket(i uint) *TokenBucket {
return &TokenBucket{
remainingTokens: i,
maxCapacity: i,
minCapacity: 1,
}
}
// Retrieve attempts to reduce the available tokens by the amount requested. If
// there are tokens available true will be returned along with the number of
// available tokens remaining. If amount requested is larger than the available
// capacity, false will be returned along with the available capacity. If the
// amount is less than the available capacity, the capacity will be reduced by
// that amount, and the remaining capacity and true will be returned.
func (t *TokenBucket) Retrieve(amount uint) (available uint, retrieved bool) {
t.mu.Lock()
defer t.mu.Unlock()
if amount > t.remainingTokens {
return t.remainingTokens, false
}
t.remainingTokens -= amount
return t.remainingTokens, true
}
// Refund returns the amount of tokens back to the available token bucket, up
// to the initial capacity.
func (t *TokenBucket) Refund(amount uint) {
t.mu.Lock()
defer t.mu.Unlock()
// Capacity cannot exceed max capacity.
t.remainingTokens = uintMin(t.remainingTokens+amount, t.maxCapacity)
}
// Capacity returns the maximum capacity of tokens that the bucket could
// contain.
func (t *TokenBucket) Capacity() uint {
t.mu.Lock()
defer t.mu.Unlock()
return t.maxCapacity
}
// Remaining returns the number of tokens that remaining in the bucket.
func (t *TokenBucket) Remaining() uint {
t.mu.Lock()
defer t.mu.Unlock()
return t.remainingTokens
}
// Resize adjusts the size of the token bucket. Returns the capacity remaining.
func (t *TokenBucket) Resize(size uint) uint {
t.mu.Lock()
defer t.mu.Unlock()
t.maxCapacity = uintMax(size, t.minCapacity)
// Capacity needs to be capped at max capacity, if max size reduced.
t.remainingTokens = uintMin(t.remainingTokens, t.maxCapacity)
return t.remainingTokens
}
func uintMin(a, b uint) uint {
if a < b {
return a
}
return b
}
func uintMax(a, b uint) uint {
if a > b {
return a
}
return b
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment