-
Notifications
You must be signed in to change notification settings - Fork 80
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: move AWSEndpoint.swift, Partition.swift classes to aws-sdk-swift
- Loading branch information
1 parent
0ea2d08
commit c13ba4c
Showing
3 changed files
with
182 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,58 @@ | ||
// | ||
// Copyright Amazon.com Inc. or its affiliates. | ||
// All Rights Reserved. | ||
// | ||
// SPDX-License-Identifier: Apache-2.0 | ||
// | ||
import ClientRuntime | ||
|
||
/** | ||
A structure used by the service client to determine the endpoint. | ||
The SDK will automatically resolve endpoints per API client using an internal resolver. | ||
*/ | ||
public struct AWSEndpoint: Equatable { | ||
/** | ||
The endpoint object contains the host name (e.g. "{service-id}.{region}.amazonaws.com"), | ||
the transport protocol (e.g. "HTTPS") and the port to connect to when making requests to this endpoint. | ||
*/ | ||
public let endpoint: Endpoint | ||
|
||
/** | ||
Flag indicating that the hostname can be modified by the SDK client. | ||
If the hostname is mutable the SDK clients may modify any part of the hostname based | ||
on the requirements of the API (e.g. adding or removing content in the hostname). If the hostname | ||
is expected to be mutable and the client cannot modify the endpoint correctly, the operation | ||
will likely fail. | ||
*/ | ||
public let isHostnameImmutable: Bool | ||
/** | ||
The service name that should be used for signing requests to this endpoint. | ||
This overrides the default signing name used by an SDK client. | ||
*/ | ||
public let signingName: String? | ||
/** | ||
The region that should be used for signing requests to this endpoint. | ||
This overrides the default signing region used by an SDK client. | ||
*/ | ||
public let signingRegion: String? | ||
|
||
public init(endpoint: Endpoint, | ||
isHostnameImmutable: Bool = false, | ||
signingName: String? = nil, | ||
signingRegion: String? = nil) { | ||
self.endpoint = endpoint | ||
self.isHostnameImmutable = isHostnameImmutable | ||
self.signingName = signingName | ||
self.signingRegion = signingRegion | ||
} | ||
|
||
public static func resolveEndpoint(partitions: [Partition], region: String) throws -> AWSEndpoint { | ||
guard !partitions.isEmpty else { | ||
throw EndpointError.partitionsEmpty( | ||
"The partitions array cannot be empty in order to properly resolve an AWS endpoint") | ||
} | ||
|
||
let candidate = partitions.first { $0.canResolveEndpoint(region: region)} ?? partitions[0] | ||
return try candidate.resolveEndpoint(region: region) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,68 @@ | ||
// | ||
// Copyright Amazon.com Inc. or its affiliates. | ||
// All Rights Reserved. | ||
// | ||
// SPDX-License-Identifier: Apache-2.0 | ||
// | ||
import ClientRuntime | ||
|
||
public struct Partition { | ||
|
||
/// The partition name/id e.g. "aws" | ||
let id: String | ||
|
||
/// The regular expression that specified the pattern that region names in the endpoint adhere to | ||
let regionRegex: String | ||
|
||
/// Endpoint that works across all regions or if [isRegionalized] is false | ||
let partitionEndpoint: String | ||
|
||
/// Flag indicating whether or not the service is regionalized in the partition. Some services have only a single, | ||
/// partition-global endpoint (e.g. CloudFront). | ||
let isRegionalized: Bool | ||
|
||
/** | ||
Default endpoint values for the partition. Some or all of the defaults specified may be superseded | ||
by an entry in [endpoints]. | ||
*/ | ||
let defaults: ServiceEndpointMetadata | ||
|
||
/// Map of endpoint names to their definitions | ||
let endpoints: [String: ServiceEndpointMetadata] | ||
|
||
public init(id: String, | ||
regionRegex: String, | ||
partitionEndpoint: String, | ||
isRegionalized: Bool, | ||
defaults: ServiceEndpointMetadata, | ||
endpoints: [String: ServiceEndpointMetadata]) { | ||
self.id = id | ||
self.regionRegex = regionRegex | ||
self.partitionEndpoint = partitionEndpoint | ||
self.isRegionalized = isRegionalized | ||
self.defaults = defaults | ||
self.endpoints = endpoints | ||
} | ||
|
||
public func canResolveEndpoint(region: String) -> Bool { | ||
return endpoints[region] != nil || region.range(of: regionRegex, | ||
options: .regularExpression) != nil | ||
} | ||
|
||
public func resolveEndpoint(region: String) throws -> AWSEndpoint { | ||
let shouldUsePartitionEndpoint = region.isEmpty && !partitionEndpoint.isEmpty | ||
let resolvedRegion = shouldUsePartitionEndpoint ? partitionEndpoint : region | ||
let endpointDefinition = endpointDefinitionForRegion(region: resolvedRegion) | ||
return try endpointDefinition.resolve(region: region, defaults: defaults) | ||
} | ||
|
||
public func endpointDefinitionForRegion(region: String) -> ServiceEndpointMetadata { | ||
if let endpointMetadata = endpoints[region] { | ||
return endpointMetadata | ||
} else if !isRegionalized { | ||
return endpoints[partitionEndpoint] ?? ServiceEndpointMetadata() | ||
} else { | ||
return ServiceEndpointMetadata() | ||
} | ||
} | ||
} |
56 changes: 56 additions & 0 deletions
56
Sources/Core/AWSClientRuntime/Endpoints/ServiceEndpointMetadata+Extension.swift
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,56 @@ | ||
// | ||
// Copyright Amazon.com Inc. or its affiliates. | ||
// All Rights Reserved. | ||
// | ||
// SPDX-License-Identifier: Apache-2.0 | ||
// | ||
import ClientRuntime | ||
|
||
extension ServiceEndpointMetadata { | ||
func resolve(region: String, defaults: ServiceEndpointMetadata) throws -> AWSEndpoint { | ||
let serviceEndpointMetadata = buildEndpointMetadataIfNotSet(defaults: defaults) | ||
guard let hostname = serviceEndpointMetadata.hostName else { | ||
throw EndpointError.hostnameIsNil("EndpointDefinition.hostname cannot be nil at this point") | ||
} | ||
let editedHostName = hostname.replacingOccurrences(of: "{region}", with: region) | ||
let transportProtocol = getProtocolByPriority(from: serviceEndpointMetadata.protocols) | ||
let signingName = serviceEndpointMetadata.credentialScope?.serviceId | ||
let signingRegion = serviceEndpointMetadata.credentialScope?.region ?? region | ||
|
||
return AWSEndpoint(endpoint: Endpoint(host: editedHostName, | ||
path: "/", | ||
protocolType: ProtocolType(rawValue: transportProtocol)), | ||
signingName: signingName, | ||
signingRegion: signingRegion) | ||
} | ||
|
||
private func buildEndpointMetadataIfNotSet(defaults: ServiceEndpointMetadata) -> ServiceEndpointMetadata { | ||
let hostName = self.hostName ?? defaults.hostName | ||
let protocols = !self.protocols.isEmpty ? self.protocols : defaults.protocols | ||
let credentialScope = CredentialScope( | ||
region: self.credentialScope?.region ?? defaults.credentialScope?.region, | ||
serviceId: self.credentialScope?.serviceId ?? defaults.credentialScope?.serviceId | ||
) | ||
let signatureVersions = !self.signatureVersions.isEmpty ? self.signatureVersions : defaults.signatureVersions | ||
return ServiceEndpointMetadata( | ||
hostName: hostName, | ||
protocols: protocols, | ||
credentialScope: credentialScope, | ||
signatureVersions: signatureVersions | ||
) | ||
} | ||
|
||
private func getProtocolByPriority(from: [String]) -> String { | ||
guard from.isEmpty else { | ||
return defaultProtocol | ||
} | ||
|
||
for p in protocolPriority { | ||
if let candidate = from.first(where: { $0 == p}) { | ||
return candidate | ||
} | ||
} | ||
|
||
return defaultProtocol | ||
} | ||
} | ||