1// Code generated by smithy-go-codegen DO NOT EDIT.
2
3package cloudformation
4
5import (
6	"context"
7	"errors"
8	"fmt"
9	"github.com/aws/aws-sdk-go-v2/aws"
10	awsmiddleware "github.com/aws/aws-sdk-go-v2/aws/middleware"
11	internalendpoints "github.com/aws/aws-sdk-go-v2/service/cloudformation/internal/endpoints"
12	"github.com/aws/smithy-go/middleware"
13	smithyhttp "github.com/aws/smithy-go/transport/http"
14	"net/url"
15)
16
17// EndpointResolverOptions is the service endpoint resolver options
18type EndpointResolverOptions = internalendpoints.Options
19
20// EndpointResolver interface for resolving service endpoints.
21type EndpointResolver interface {
22	ResolveEndpoint(region string, options EndpointResolverOptions) (aws.Endpoint, error)
23}
24
25var _ EndpointResolver = &internalendpoints.Resolver{}
26
27// NewDefaultEndpointResolver constructs a new service endpoint resolver
28func NewDefaultEndpointResolver() *internalendpoints.Resolver {
29	return internalendpoints.New()
30}
31
32// EndpointResolverFunc is a helper utility that wraps a function so it satisfies
33// the EndpointResolver interface. This is useful when you want to add additional
34// endpoint resolving logic, or stub out specific endpoints with custom values.
35type EndpointResolverFunc func(region string, options EndpointResolverOptions) (aws.Endpoint, error)
36
37func (fn EndpointResolverFunc) ResolveEndpoint(region string, options EndpointResolverOptions) (endpoint aws.Endpoint, err error) {
38	return fn(region, options)
39}
40
41func resolveDefaultEndpointConfiguration(o *Options) {
42	if o.EndpointResolver != nil {
43		return
44	}
45	o.EndpointResolver = NewDefaultEndpointResolver()
46}
47
48// EndpointResolverFromURL returns an EndpointResolver configured using the
49// provided endpoint url. By default, the resolved endpoint resolver uses the
50// client region as signing region, and the endpoint source is set to
51// EndpointSourceCustom.You can provide functional options to configure endpoint
52// values for the resolved endpoint.
53func EndpointResolverFromURL(url string, optFns ...func(*aws.Endpoint)) EndpointResolver {
54	e := aws.Endpoint{URL: url, Source: aws.EndpointSourceCustom}
55	for _, fn := range optFns {
56		fn(&e)
57	}
58
59	return EndpointResolverFunc(
60		func(region string, options EndpointResolverOptions) (aws.Endpoint, error) {
61			if len(e.SigningRegion) == 0 {
62				e.SigningRegion = region
63			}
64			return e, nil
65		},
66	)
67}
68
69type ResolveEndpoint struct {
70	Resolver EndpointResolver
71	Options  EndpointResolverOptions
72}
73
74func (*ResolveEndpoint) ID() string {
75	return "ResolveEndpoint"
76}
77
78func (m *ResolveEndpoint) HandleSerialize(ctx context.Context, in middleware.SerializeInput, next middleware.SerializeHandler) (
79	out middleware.SerializeOutput, metadata middleware.Metadata, err error,
80) {
81	req, ok := in.Request.(*smithyhttp.Request)
82	if !ok {
83		return out, metadata, fmt.Errorf("unknown transport type %T", in.Request)
84	}
85
86	if m.Resolver == nil {
87		return out, metadata, fmt.Errorf("expected endpoint resolver to not be nil")
88	}
89
90	var endpoint aws.Endpoint
91	endpoint, err = m.Resolver.ResolveEndpoint(awsmiddleware.GetRegion(ctx), m.Options)
92	if err != nil {
93		return out, metadata, fmt.Errorf("failed to resolve service endpoint, %w", err)
94	}
95
96	req.URL, err = url.Parse(endpoint.URL)
97	if err != nil {
98		return out, metadata, fmt.Errorf("failed to parse endpoint URL: %w", err)
99	}
100
101	if len(awsmiddleware.GetSigningName(ctx)) == 0 {
102		signingName := endpoint.SigningName
103		if len(signingName) == 0 {
104			signingName = "cloudformation"
105		}
106		ctx = awsmiddleware.SetSigningName(ctx, signingName)
107	}
108	ctx = awsmiddleware.SetEndpointSource(ctx, endpoint.Source)
109	ctx = smithyhttp.SetHostnameImmutable(ctx, endpoint.HostnameImmutable)
110	ctx = awsmiddleware.SetSigningRegion(ctx, endpoint.SigningRegion)
111	ctx = awsmiddleware.SetPartitionID(ctx, endpoint.PartitionID)
112	return next.HandleSerialize(ctx, in)
113}
114func addResolveEndpointMiddleware(stack *middleware.Stack, o Options) error {
115	return stack.Serialize.Insert(&ResolveEndpoint{
116		Resolver: o.EndpointResolver,
117		Options:  o.EndpointOptions,
118	}, "OperationSerializer", middleware.Before)
119}
120
121func removeResolveEndpointMiddleware(stack *middleware.Stack) error {
122	_, err := stack.Serialize.Remove((&ResolveEndpoint{}).ID())
123	return err
124}
125
126type wrappedEndpointResolver struct {
127	awsResolver aws.EndpointResolver
128	resolver    EndpointResolver
129}
130
131func (w *wrappedEndpointResolver) ResolveEndpoint(region string, options EndpointResolverOptions) (endpoint aws.Endpoint, err error) {
132	if w.awsResolver == nil {
133		goto fallback
134	}
135	endpoint, err = w.awsResolver.ResolveEndpoint(ServiceID, region)
136	if err == nil {
137		return endpoint, nil
138	}
139
140	if nf := (&aws.EndpointNotFoundError{}); !errors.As(err, &nf) {
141		return endpoint, err
142	}
143
144fallback:
145	if w.resolver == nil {
146		return endpoint, fmt.Errorf("default endpoint resolver provided was nil")
147	}
148	return w.resolver.ResolveEndpoint(region, options)
149}
150
151// withEndpointResolver returns an EndpointResolver that first delegates endpoint
152// resolution to the awsResolver. If awsResolver returns aws.EndpointNotFoundError
153// error, the resolver will use the the provided fallbackResolver for resolution.
154// awsResolver and fallbackResolver must not be nil
155func withEndpointResolver(awsResolver aws.EndpointResolver, fallbackResolver EndpointResolver) EndpointResolver {
156	return &wrappedEndpointResolver{
157		awsResolver: awsResolver,
158		resolver:    fallbackResolver,
159	}
160}
161