10 type partitions []partition
12 func (ps partitions) EndpointFor(service, region string, opts ...func(*Options)) (ResolvedEndpoint, error) {
16 for i := 0; i < len(ps); i++ {
17 if !ps[i].canResolveEndpoint(service, region, opt.StrictMatching) {
21 return ps[i].EndpointFor(service, region, opts...)
24 // If loose matching fallback to first partition format to use
25 // when resolving the endpoint.
26 if !opt.StrictMatching && len(ps) > 0 {
27 return ps[0].EndpointFor(service, region, opts...)
30 return ResolvedEndpoint{}, NewUnknownEndpointError("all partitions", service, region, []string{})
33 // Partitions satisfies the EnumPartitions interface and returns a list
34 // of Partitions representing each partition represented in the SDK's
36 func (ps partitions) Partitions() []Partition {
37 parts := make([]Partition, 0, len(ps))
38 for i := 0; i < len(ps); i++ {
39 parts = append(parts, ps[i].Partition())
45 type partition struct {
46 ID string `json:"partition"`
47 Name string `json:"partitionName"`
48 DNSSuffix string `json:"dnsSuffix"`
49 RegionRegex regionRegex `json:"regionRegex"`
50 Defaults endpoint `json:"defaults"`
51 Regions regions `json:"regions"`
52 Services services `json:"services"`
55 func (p partition) Partition() Partition {
62 func (p partition) canResolveEndpoint(service, region string, strictMatch bool) bool {
63 s, hasService := p.Services[service]
64 _, hasEndpoint := s.Endpoints[region]
66 if hasEndpoint && hasService {
74 return p.RegionRegex.MatchString(region)
77 func (p partition) EndpointFor(service, region string, opts ...func(*Options)) (resolved ResolvedEndpoint, err error) {
81 s, hasService := p.Services[service]
82 if !(hasService || opt.ResolveUnknownService) {
83 // Only return error if the resolver will not fallback to creating
84 // endpoint based on service endpoint ID passed in.
85 return resolved, NewUnknownServiceError(p.ID, service, serviceList(p.Services))
88 e, hasEndpoint := s.endpointForRegion(region)
89 if !hasEndpoint && opt.StrictMatching {
90 return resolved, NewUnknownEndpointError(p.ID, service, region, endpointList(s.Endpoints))
93 defs := []endpoint{p.Defaults, s.Defaults}
94 return e.resolve(service, region, p.DNSSuffix, defs, opt), nil
97 func serviceList(ss services) []string {
98 list := make([]string, 0, len(ss))
100 list = append(list, k)
104 func endpointList(es endpoints) []string {
105 list := make([]string, 0, len(es))
107 list = append(list, k)
112 type regionRegex struct {
116 func (rr *regionRegex) UnmarshalJSON(b []byte) (err error) {
117 // Strip leading and trailing quotes
118 regex, err := strconv.Unquote(string(b))
120 return fmt.Errorf("unable to strip quotes from regex, %v", err)
123 rr.Regexp, err = regexp.Compile(regex)
125 return fmt.Errorf("unable to unmarshal region regex, %v", err)
130 type regions map[string]region
133 Description string `json:"description"`
136 type services map[string]service
138 type service struct {
139 PartitionEndpoint string `json:"partitionEndpoint"`
140 IsRegionalized boxedBool `json:"isRegionalized,omitempty"`
141 Defaults endpoint `json:"defaults"`
142 Endpoints endpoints `json:"endpoints"`
145 func (s *service) endpointForRegion(region string) (endpoint, bool) {
146 if s.IsRegionalized == boxedFalse {
147 return s.Endpoints[s.PartitionEndpoint], region == s.PartitionEndpoint
150 if e, ok := s.Endpoints[region]; ok {
154 // Unable to find any matching endpoint, return
155 // blank that will be used for generic endpoint creation.
156 return endpoint{}, false
159 type endpoints map[string]endpoint
161 type endpoint struct {
162 Hostname string `json:"hostname"`
163 Protocols []string `json:"protocols"`
164 CredentialScope credentialScope `json:"credentialScope"`
166 // Custom fields not modeled
167 HasDualStack boxedBool `json:"-"`
168 DualStackHostname string `json:"-"`
170 // Signature Version not used
171 SignatureVersions []string `json:"signatureVersions"`
173 // SSLCommonName not used.
174 SSLCommonName string `json:"sslCommonName"`
178 defaultProtocol = "https"
183 protocolPriority = []string{"https", "http"}
184 signerPriority = []string{"v4", "v2"}
187 func getByPriority(s []string, p []string, def string) string {
192 for i := 0; i < len(p); i++ {
193 for j := 0; j < len(s); j++ {
203 func (e endpoint) resolve(service, region, dnsSuffix string, defs []endpoint, opts Options) ResolvedEndpoint {
205 for _, def := range defs {
211 hostname := e.Hostname
213 // Offset the hostname for dualstack if enabled
214 if opts.UseDualStack && e.HasDualStack == boxedTrue {
215 hostname = e.DualStackHostname
218 u := strings.Replace(hostname, "{service}", service, 1)
219 u = strings.Replace(u, "{region}", region, 1)
220 u = strings.Replace(u, "{dnsSuffix}", dnsSuffix, 1)
222 scheme := getEndpointScheme(e.Protocols, opts.DisableSSL)
223 u = fmt.Sprintf("%s://%s", scheme, u)
225 signingRegion := e.CredentialScope.Region
226 if len(signingRegion) == 0 {
227 signingRegion = region
229 signingName := e.CredentialScope.Service
230 if len(signingName) == 0 {
231 signingName = service
234 return ResolvedEndpoint{
236 SigningRegion: signingRegion,
237 SigningName: signingName,
238 SigningMethod: getByPriority(e.SignatureVersions, signerPriority, defaultSigner),
242 func getEndpointScheme(protocols []string, disableSSL bool) string {
247 return getByPriority(protocols, protocolPriority, defaultProtocol)
250 func (e *endpoint) mergeIn(other endpoint) {
251 if len(other.Hostname) > 0 {
252 e.Hostname = other.Hostname
254 if len(other.Protocols) > 0 {
255 e.Protocols = other.Protocols
257 if len(other.SignatureVersions) > 0 {
258 e.SignatureVersions = other.SignatureVersions
260 if len(other.CredentialScope.Region) > 0 {
261 e.CredentialScope.Region = other.CredentialScope.Region
263 if len(other.CredentialScope.Service) > 0 {
264 e.CredentialScope.Service = other.CredentialScope.Service
266 if len(other.SSLCommonName) > 0 {
267 e.SSLCommonName = other.SSLCommonName
269 if other.HasDualStack != boxedBoolUnset {
270 e.HasDualStack = other.HasDualStack
272 if len(other.DualStackHostname) > 0 {
273 e.DualStackHostname = other.DualStackHostname
277 type credentialScope struct {
278 Region string `json:"region"`
279 Service string `json:"service"`
284 func (b *boxedBool) UnmarshalJSON(buf []byte) error {
285 v, err := strconv.ParseBool(string(buf))
300 boxedBoolUnset boxedBool = iota