7 "github.com/aws/aws-sdk-go/aws/awserr"
10 // Options provide the configuration needed to direct how the
11 // endpoints will be resolved.
13 // DisableSSL forces the endpoint to be resolved as HTTP.
14 // instead of HTTPS if the service supports it.
17 // Sets the resolver to resolve the endpoint as a dualstack endpoint
18 // for the service. If dualstack support for a service is not known and
19 // StrictMatching is not enabled a dualstack endpoint for the service will
20 // be returned. This endpoint may not be valid. If StrictMatching is
21 // enabled only services that are known to support dualstack will return
22 // dualstack endpoints.
25 // Enables strict matching of services and regions resolved endpoints.
26 // If the partition doesn't enumerate the exact service and region an
27 // error will be returned. This option will prevent returning endpoints
28 // that look valid, but may not resolve to any real endpoint.
31 // Enables resolving a service endpoint based on the region provided if the
32 // service does not exist. The service endpoint ID will be used as the service
33 // domain name prefix. By default the endpoint resolver requires the service
34 // to be known when resolving endpoints.
36 // If resolving an endpoint on the partition list the provided region will
37 // be used to determine which partition's domain name pattern to the service
38 // endpoint ID with. If both the service and region are unkonwn and resolving
39 // the endpoint on partition list an UnknownEndpointError error will be returned.
41 // If resolving and endpoint on a partition specific resolver that partition's
42 // domain name pattern will be used with the service endpoint ID. If both
43 // region and service do not exist when resolving an endpoint on a specific
44 // partition the partition's domain pattern will be used to combine the
45 // endpoint and region together.
47 // This option is ignored if StrictMatching is enabled.
48 ResolveUnknownService bool
51 // Set combines all of the option functions together.
52 func (o *Options) Set(optFns ...func(*Options)) {
53 for _, fn := range optFns {
58 // DisableSSLOption sets the DisableSSL options. Can be used as a functional
59 // option when resolving endpoints.
60 func DisableSSLOption(o *Options) {
64 // UseDualStackOption sets the UseDualStack option. Can be used as a functional
65 // option when resolving endpoints.
66 func UseDualStackOption(o *Options) {
70 // StrictMatchingOption sets the StrictMatching option. Can be used as a functional
71 // option when resolving endpoints.
72 func StrictMatchingOption(o *Options) {
73 o.StrictMatching = true
76 // ResolveUnknownServiceOption sets the ResolveUnknownService option. Can be used
77 // as a functional option when resolving endpoints.
78 func ResolveUnknownServiceOption(o *Options) {
79 o.ResolveUnknownService = true
82 // A Resolver provides the interface for functionality to resolve endpoints.
83 // The build in Partition and DefaultResolver return value satisfy this interface.
84 type Resolver interface {
85 EndpointFor(service, region string, opts ...func(*Options)) (ResolvedEndpoint, error)
88 // ResolverFunc is a helper utility that wraps a function so it satisfies the
89 // Resolver interface. This is useful when you want to add additional endpoint
90 // resolving logic, or stub out specific endpoints with custom values.
91 type ResolverFunc func(service, region string, opts ...func(*Options)) (ResolvedEndpoint, error)
93 // EndpointFor wraps the ResolverFunc function to satisfy the Resolver interface.
94 func (fn ResolverFunc) EndpointFor(service, region string, opts ...func(*Options)) (ResolvedEndpoint, error) {
95 return fn(service, region, opts...)
98 var schemeRE = regexp.MustCompile("^([^:]+)://")
100 // AddScheme adds the HTTP or HTTPS schemes to a endpoint URL if there is no
101 // scheme. If disableSSL is true HTTP will set HTTP instead of the default HTTPS.
103 // If disableSSL is set, it will only set the URL's scheme if the URL does not
105 func AddScheme(endpoint string, disableSSL bool) string {
106 if !schemeRE.MatchString(endpoint) {
111 endpoint = fmt.Sprintf("%s://%s", scheme, endpoint)
117 // EnumPartitions a provides a way to retrieve the underlying partitions that
118 // make up the SDK's default Resolver, or any resolver decoded from a model
121 // Use this interface with DefaultResolver and DecodeModels to get the list of
123 type EnumPartitions interface {
124 Partitions() []Partition
127 // RegionsForService returns a map of regions for the partition and service.
128 // If either the partition or service does not exist false will be returned
129 // as the second parameter.
131 // This example shows how to get the regions for DynamoDB in the AWS partition.
132 // rs, exists := endpoints.RegionsForService(endpoints.DefaultPartitions(), endpoints.AwsPartitionID, endpoints.DynamodbServiceID)
134 // This is equivalent to using the partition directly.
135 // rs := endpoints.AwsPartition().Services()[endpoints.DynamodbServiceID].Regions()
136 func RegionsForService(ps []Partition, partitionID, serviceID string) (map[string]Region, bool) {
137 for _, p := range ps {
138 if p.ID() != partitionID {
141 if _, ok := p.p.Services[serviceID]; !ok {
149 return s.Regions(), true
152 return map[string]Region{}, false
155 // PartitionForRegion returns the first partition which includes the region
156 // passed in. This includes both known regions and regions which match
157 // a pattern supported by the partition which may include regions that are
158 // not explicitly known by the partition. Use the Regions method of the
159 // returned Partition if explicit support is needed.
160 func PartitionForRegion(ps []Partition, regionID string) (Partition, bool) {
161 for _, p := range ps {
162 if _, ok := p.p.Regions[regionID]; ok || p.p.RegionRegex.MatchString(regionID) {
167 return Partition{}, false
170 // A Partition provides the ability to enumerate the partition's regions
172 type Partition struct {
177 // ID returns the identifier of the partition.
178 func (p Partition) ID() string { return p.id }
180 // EndpointFor attempts to resolve the endpoint based on service and region.
181 // See Options for information on configuring how the endpoint is resolved.
183 // If the service cannot be found in the metadata the UnknownServiceError
184 // error will be returned. This validation will occur regardless if
185 // StrictMatching is enabled. To enable resolving unknown services set the
186 // "ResolveUnknownService" option to true. When StrictMatching is disabled
187 // this option allows the partition resolver to resolve a endpoint based on
188 // the service endpoint ID provided.
190 // When resolving endpoints you can choose to enable StrictMatching. This will
191 // require the provided service and region to be known by the partition.
192 // If the endpoint cannot be strictly resolved an error will be returned. This
193 // mode is useful to ensure the endpoint resolved is valid. Without
194 // StrictMatching enabled the endpoint returned my look valid but may not work.
195 // StrictMatching requires the SDK to be updated if you want to take advantage
196 // of new regions and services expansions.
198 // Errors that can be returned.
199 // * UnknownServiceError
200 // * UnknownEndpointError
201 func (p Partition) EndpointFor(service, region string, opts ...func(*Options)) (ResolvedEndpoint, error) {
202 return p.p.EndpointFor(service, region, opts...)
205 // Regions returns a map of Regions indexed by their ID. This is useful for
206 // enumerating over the regions in a partition.
207 func (p Partition) Regions() map[string]Region {
208 rs := map[string]Region{}
209 for id := range p.p.Regions {
219 // Services returns a map of Service indexed by their ID. This is useful for
220 // enumerating over the services in a partition.
221 func (p Partition) Services() map[string]Service {
222 ss := map[string]Service{}
223 for id := range p.p.Services {
233 // A Region provides information about a region, and ability to resolve an
234 // endpoint from the context of a region, given a service.
240 // ID returns the region's identifier.
241 func (r Region) ID() string { return r.id }
243 // ResolveEndpoint resolves an endpoint from the context of the region given
244 // a service. See Partition.EndpointFor for usage and errors that can be returned.
245 func (r Region) ResolveEndpoint(service string, opts ...func(*Options)) (ResolvedEndpoint, error) {
246 return r.p.EndpointFor(service, r.id, opts...)
249 // Services returns a list of all services that are known to be in this region.
250 func (r Region) Services() map[string]Service {
251 ss := map[string]Service{}
252 for id, s := range r.p.Services {
253 if _, ok := s.Endpoints[r.id]; ok {
264 // A Service provides information about a service, and ability to resolve an
265 // endpoint from the context of a service, given a region.
266 type Service struct {
271 // ID returns the identifier for the service.
272 func (s Service) ID() string { return s.id }
274 // ResolveEndpoint resolves an endpoint from the context of a service given
275 // a region. See Partition.EndpointFor for usage and errors that can be returned.
276 func (s Service) ResolveEndpoint(region string, opts ...func(*Options)) (ResolvedEndpoint, error) {
277 return s.p.EndpointFor(s.id, region, opts...)
280 // Regions returns a map of Regions that the service is present in.
282 // A region is the AWS region the service exists in. Whereas a Endpoint is
283 // an URL that can be resolved to a instance of a service.
284 func (s Service) Regions() map[string]Region {
285 rs := map[string]Region{}
286 for id := range s.p.Services[s.id].Endpoints {
287 if _, ok := s.p.Regions[id]; ok {
298 // Endpoints returns a map of Endpoints indexed by their ID for all known
299 // endpoints for a service.
301 // A region is the AWS region the service exists in. Whereas a Endpoint is
302 // an URL that can be resolved to a instance of a service.
303 func (s Service) Endpoints() map[string]Endpoint {
304 es := map[string]Endpoint{}
305 for id := range s.p.Services[s.id].Endpoints {
316 // A Endpoint provides information about endpoints, and provides the ability
317 // to resolve that endpoint for the service, and the region the endpoint
319 type Endpoint struct {
325 // ID returns the identifier for an endpoint.
326 func (e Endpoint) ID() string { return e.id }
328 // ServiceID returns the identifier the endpoint belongs to.
329 func (e Endpoint) ServiceID() string { return e.serviceID }
331 // ResolveEndpoint resolves an endpoint from the context of a service and
332 // region the endpoint represents. See Partition.EndpointFor for usage and
333 // errors that can be returned.
334 func (e Endpoint) ResolveEndpoint(opts ...func(*Options)) (ResolvedEndpoint, error) {
335 return e.p.EndpointFor(e.serviceID, e.id, opts...)
338 // A ResolvedEndpoint is an endpoint that has been resolved based on a partition
339 // service, and region.
340 type ResolvedEndpoint struct {
344 // The region that should be used for signing requests.
347 // The service name that should be used for signing requests.
350 // The signing method that should be used for signing requests.
354 // So that the Error interface type can be included as an anonymous field
355 // in the requestError struct and not conflict with the error.Error() method.
356 type awsError awserr.Error
358 // A EndpointNotFoundError is returned when in StrictMatching mode, and the
359 // endpoint for the service and region cannot be found in any of the partitions.
360 type EndpointNotFoundError struct {
367 // A UnknownServiceError is returned when the service does not resolve to an
368 // endpoint. Includes a list of all known services for the partition. Returned
369 // when a partition does not support the service.
370 type UnknownServiceError struct {
377 // NewUnknownServiceError builds and returns UnknownServiceError.
378 func NewUnknownServiceError(p, s string, known []string) UnknownServiceError {
379 return UnknownServiceError{
380 awsError: awserr.New("UnknownServiceError",
381 "could not resolve endpoint for unknown service", nil),
388 // String returns the string representation of the error.
389 func (e UnknownServiceError) Error() string {
390 extra := fmt.Sprintf("partition: %q, service: %q",
391 e.Partition, e.Service)
392 if len(e.Known) > 0 {
393 extra += fmt.Sprintf(", known: %v", e.Known)
395 return awserr.SprintError(e.Code(), e.Message(), extra, e.OrigErr())
398 // String returns the string representation of the error.
399 func (e UnknownServiceError) String() string {
403 // A UnknownEndpointError is returned when in StrictMatching mode and the
404 // service is valid, but the region does not resolve to an endpoint. Includes
405 // a list of all known endpoints for the service.
406 type UnknownEndpointError struct {
414 // NewUnknownEndpointError builds and returns UnknownEndpointError.
415 func NewUnknownEndpointError(p, s, r string, known []string) UnknownEndpointError {
416 return UnknownEndpointError{
417 awsError: awserr.New("UnknownEndpointError",
418 "could not resolve endpoint", nil),
426 // String returns the string representation of the error.
427 func (e UnknownEndpointError) Error() string {
428 extra := fmt.Sprintf("partition: %q, service: %q, region: %q",
429 e.Partition, e.Service, e.Region)
430 if len(e.Known) > 0 {
431 extra += fmt.Sprintf(", known: %v", e.Known)
433 return awserr.SprintError(e.Code(), e.Message(), extra, e.OrigErr())
436 // String returns the string representation of the error.
437 func (e UnknownEndpointError) String() string {