...

Source file src/github.com/aws/aws-sdk-go-v2/internal/endpoints/endpoints.go

Documentation: github.com/aws/aws-sdk-go-v2/internal/endpoints

     1  package endpoints
     2  
     3  import (
     4  	"fmt"
     5  	"regexp"
     6  	"strings"
     7  
     8  	"github.com/aws/aws-sdk-go-v2/aws"
     9  )
    10  
    11  const (
    12  	defaultProtocol = "https"
    13  	defaultSigner   = "v4"
    14  )
    15  
    16  var (
    17  	protocolPriority = []string{"https", "http"}
    18  	signerPriority   = []string{"v4"}
    19  )
    20  
    21  // Options provide configuration needed to direct how endpoints are resolved.
    22  type Options struct {
    23  	// Disable usage of HTTPS (TLS / SSL)
    24  	DisableHTTPS bool
    25  }
    26  
    27  // Partitions is a slice of partition
    28  type Partitions []Partition
    29  
    30  // ResolveEndpoint resolves a service endpoint for the given region and options.
    31  func (ps Partitions) ResolveEndpoint(region string, opts Options) (aws.Endpoint, error) {
    32  	if len(ps) == 0 {
    33  		return aws.Endpoint{}, fmt.Errorf("no partitions found")
    34  	}
    35  
    36  	for i := 0; i < len(ps); i++ {
    37  		if !ps[i].canResolveEndpoint(region) {
    38  			continue
    39  		}
    40  
    41  		return ps[i].ResolveEndpoint(region, opts)
    42  	}
    43  
    44  	// fallback to first partition format to use when resolving the endpoint.
    45  	return ps[0].ResolveEndpoint(region, opts)
    46  }
    47  
    48  // Partition is an AWS partition description for a service and its' region endpoints.
    49  type Partition struct {
    50  	ID                string
    51  	RegionRegex       *regexp.Regexp
    52  	PartitionEndpoint string
    53  	IsRegionalized    bool
    54  	Defaults          Endpoint
    55  	Endpoints         Endpoints
    56  }
    57  
    58  func (p Partition) canResolveEndpoint(region string) bool {
    59  	_, ok := p.Endpoints[region]
    60  	return ok || p.RegionRegex.MatchString(region)
    61  }
    62  
    63  // ResolveEndpoint resolves and service endpoint for the given region and options.
    64  func (p Partition) ResolveEndpoint(region string, options Options) (resolved aws.Endpoint, err error) {
    65  	if len(region) == 0 && len(p.PartitionEndpoint) != 0 {
    66  		region = p.PartitionEndpoint
    67  	}
    68  
    69  	e, _ := p.endpointForRegion(region)
    70  
    71  	return e.resolve(p.ID, region, p.Defaults, options), nil
    72  }
    73  
    74  func (p Partition) endpointForRegion(region string) (Endpoint, bool) {
    75  	if e, ok := p.Endpoints[region]; ok {
    76  		return e, true
    77  	}
    78  
    79  	if !p.IsRegionalized {
    80  		return p.Endpoints[p.PartitionEndpoint], region == p.PartitionEndpoint
    81  	}
    82  
    83  	// Unable to find any matching endpoint, return
    84  	// blank that will be used for generic endpoint creation.
    85  	return Endpoint{}, false
    86  }
    87  
    88  // Endpoints is a map of service config regions to endpoints
    89  type Endpoints map[string]Endpoint
    90  
    91  // CredentialScope is the credential scope of a region and service
    92  type CredentialScope struct {
    93  	Region  string
    94  	Service string
    95  }
    96  
    97  // Endpoint is a service endpoint description
    98  type Endpoint struct {
    99  	// True if the endpoint cannot be resolved for this partition/region/service
   100  	Unresolveable aws.Ternary
   101  
   102  	Hostname  string
   103  	Protocols []string
   104  
   105  	CredentialScope CredentialScope
   106  
   107  	SignatureVersions []string `json:"signatureVersions"`
   108  }
   109  
   110  func (e Endpoint) resolve(partition, region string, def Endpoint, options Options) aws.Endpoint {
   111  	var merged Endpoint
   112  	merged.mergeIn(def)
   113  	merged.mergeIn(e)
   114  	e = merged
   115  
   116  	var u string
   117  	if e.Unresolveable != aws.TrueTernary {
   118  		// Only attempt to resolve the endpoint if it can be resolved.
   119  		hostname := strings.Replace(e.Hostname, "{region}", region, 1)
   120  
   121  		scheme := getEndpointScheme(e.Protocols, options.DisableHTTPS)
   122  		u = scheme + "://" + hostname
   123  	}
   124  
   125  	signingRegion := e.CredentialScope.Region
   126  	if len(signingRegion) == 0 {
   127  		signingRegion = region
   128  	}
   129  	signingName := e.CredentialScope.Service
   130  
   131  	return aws.Endpoint{
   132  		URL:           u,
   133  		PartitionID:   partition,
   134  		SigningRegion: signingRegion,
   135  		SigningName:   signingName,
   136  		SigningMethod: getByPriority(e.SignatureVersions, signerPriority, defaultSigner),
   137  	}
   138  }
   139  
   140  func (e *Endpoint) mergeIn(other Endpoint) {
   141  	if other.Unresolveable != aws.UnknownTernary {
   142  		e.Unresolveable = other.Unresolveable
   143  	}
   144  	if len(other.Hostname) > 0 {
   145  		e.Hostname = other.Hostname
   146  	}
   147  	if len(other.Protocols) > 0 {
   148  		e.Protocols = other.Protocols
   149  	}
   150  	if len(other.CredentialScope.Region) > 0 {
   151  		e.CredentialScope.Region = other.CredentialScope.Region
   152  	}
   153  	if len(other.CredentialScope.Service) > 0 {
   154  		e.CredentialScope.Service = other.CredentialScope.Service
   155  	}
   156  	if len(other.SignatureVersions) > 0 {
   157  		e.SignatureVersions = other.SignatureVersions
   158  	}
   159  }
   160  
   161  func getEndpointScheme(protocols []string, disableHTTPS bool) string {
   162  	if disableHTTPS {
   163  		return "http"
   164  	}
   165  
   166  	return getByPriority(protocols, protocolPriority, defaultProtocol)
   167  }
   168  
   169  func getByPriority(s []string, p []string, def string) string {
   170  	if len(s) == 0 {
   171  		return def
   172  	}
   173  
   174  	for i := 0; i < len(p); i++ {
   175  		for j := 0; j < len(s); j++ {
   176  			if s[j] == p[i] {
   177  				return s[j]
   178  			}
   179  		}
   180  	}
   181  
   182  	return s[0]
   183  }
   184  
   185  // MapFIPSRegion extracts the intrinsic AWS region from one that may have an
   186  // embedded FIPS microformat.
   187  func MapFIPSRegion(region string) string {
   188  	const fipsInfix = "-fips-"
   189  	const fipsPrefix = "fips-"
   190  	const fipsSuffix = "-fips"
   191  
   192  	if strings.Contains(region, fipsInfix) ||
   193  		strings.Contains(region, fipsPrefix) ||
   194  		strings.Contains(region, fipsSuffix) {
   195  		region = strings.ReplaceAll(region, fipsInfix, "-")
   196  		region = strings.ReplaceAll(region, fipsPrefix, "")
   197  		region = strings.ReplaceAll(region, fipsSuffix, "")
   198  	}
   199  
   200  	return region
   201  }
   202  

View as plain text