-
Notifications
You must be signed in to change notification settings - Fork 31
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
chore: Add signer protocol. #598
Changes from all commits
86c7d2c
5eb2c8d
75646fc
dd339a0
f5808fa
9327f98
39b386e
ad8cd2c
1bd5ac5
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
// | ||
// Copyright Amazon.com Inc. or its affiliates. | ||
// All Rights Reserved. | ||
// | ||
// SPDX-License-Identifier: Apache-2.0 | ||
// | ||
|
||
import Foundation | ||
|
||
public protocol Signer { | ||
func sign<IdentityT: Identity>( | ||
requestBuilder: SdkHttpRequestBuilder, | ||
identity: IdentityT, | ||
signingProperties: Attributes | ||
) async throws -> SdkHttpRequestBuilder | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -9,61 +9,65 @@ public class HttpContext: MiddlewareContext { | |
public init(attributes: Attributes) { | ||
self.attributes = attributes | ||
} | ||
// FIXME: Move all defined keys to separate file as constants to be used elsewhere | ||
public func getPath() -> String { | ||
return attributes.get(key: AttributeKey<String>(name: "Path"))! | ||
} | ||
|
||
public func getMethod() -> HttpMethodType { | ||
return attributes.get(key: AttributeKey<HttpMethodType>(name: "Method"))! | ||
public func getDecoder() -> ResponseDecoder { | ||
return attributes.get(key: AttributeKeys.decoder)! | ||
} | ||
|
||
public func getEncoder() -> RequestEncoder { | ||
return attributes.get(key: AttributeKey<RequestEncoder>(name: "Encoder"))! | ||
} | ||
|
||
public func getDecoder() -> ResponseDecoder { | ||
return attributes.get(key: AttributeKey<ResponseDecoder>(name: "Decoder"))! | ||
return attributes.get(key: AttributeKeys.encoder)! | ||
} | ||
|
||
public func getHost() -> String? { | ||
return attributes.get(key: AttributeKey<String>(name: "Host")) | ||
return attributes.get(key: AttributeKeys.host) | ||
} | ||
|
||
public func getServiceName() -> String { | ||
return attributes.get(key: AttributeKey<String>(name: "ServiceName"))! | ||
public func getHostPrefix() -> String? { | ||
return attributes.get(key: AttributeKeys.hostPrefix) | ||
} | ||
|
||
public func getIdempotencyTokenGenerator() -> IdempotencyTokenGenerator { | ||
return attributes.get(key: AttributeKey<IdempotencyTokenGenerator>(name: "IdempotencyTokenGenerator"))! | ||
return attributes.get(key: AttributeKeys.idempotencyTokenGenerator)! | ||
} | ||
|
||
public func getHostPrefix() -> String? { | ||
return attributes.get(key: AttributeKey<String>(name: "HostPrefix")) | ||
public func getIdentityResolvers() -> Attributes { | ||
return attributes.get(key: AttributeKeys.identityResolvers)! | ||
} | ||
|
||
public func getLogger() -> LogAgent? { | ||
return attributes.get(key: AttributeKey<LogAgent>(name: "Logger")) | ||
return attributes.get(key: AttributeKeys.logger) | ||
} | ||
|
||
public func getMessageEncoder() -> MessageEncoder? { | ||
return attributes.get(key: AttributeKeys.messageEncoder) | ||
} | ||
|
||
public func getMessageSigner() -> MessageSigner? { | ||
return attributes.get(key: AttributeKeys.messageSigner) | ||
} | ||
|
||
public func getMethod() -> HttpMethodType { | ||
return attributes.get(key: AttributeKeys.method)! | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. please avoid use of forced unwrapping There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This code existed previously, it shows up as diff because I changed the order of methods in the file to be alphabetical. Avoiding use of forced unwrapping may be refactor task for later time. From what I've gathered, the code force-unwraps because by the time this method is called, this attribute HAS to have been set. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Issue created: awslabs/aws-sdk-swift#1168 Will pick up after finishing SRA Identity & Auth There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The "right" way to unwrap is probably to throw an exception back to the caller if the expected attribute is not set. David's correct though, |
||
} | ||
|
||
/// The partition ID to be used for this context. | ||
/// | ||
/// Requests made with the same partition ID will be grouped together for retry throttling purposes. | ||
/// If no partition ID is provided, requests will be partitioned based on the hostname. | ||
public func getPartitionID() -> String? { | ||
return attributes.get(key: AttributeKey<String>(name: "PartitionID")) | ||
return attributes.get(key: AttributeKeys.partitionId) | ||
} | ||
|
||
public func getMessageEncoder() -> MessageEncoder? { | ||
return attributes.get(key: HttpContext.messageEncoder) | ||
public func getPath() -> String { | ||
return attributes.get(key: AttributeKeys.path)! | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. please avoid use of forced unwrapping There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. See comment above |
||
} | ||
|
||
public func getMessageSigner() -> MessageSigner? { | ||
return attributes.get(key: HttpContext.messageSigner) | ||
public func getServiceName() -> String { | ||
return attributes.get(key: AttributeKeys.serviceName)! | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. please avoid use of forced unwrapping There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. See comment above |
||
} | ||
|
||
public func isBidirectionalStreamingEnabled() -> Bool { | ||
return attributes.get(key: HttpContext.bidirectionalStreaming) ?? false | ||
return attributes.get(key: AttributeKeys.bidirectionalStreaming) ?? false | ||
} | ||
|
||
/// Returns `true` if the request should use `http2` and only `http2` without falling back to `http1` | ||
|
@@ -72,29 +76,11 @@ public class HttpContext: MiddlewareContext { | |
} | ||
} | ||
|
||
extension HttpContext { | ||
public static let messageEncoder = AttributeKey<MessageEncoder>(name: "MessageEncoder") | ||
public static let messageSigner = AttributeKey<MessageSigner>(name: "MessageSigner") | ||
public static let bidirectionalStreaming = AttributeKey<Bool>(name: "BidirectionalStreaming") | ||
} | ||
|
||
public class HttpContextBuilder { | ||
|
||
public init() {} | ||
|
||
public var attributes: Attributes = Attributes() | ||
let encoder = AttributeKey<RequestEncoder>(name: "Encoder") | ||
let method = AttributeKey<HttpMethodType>(name: "Method") | ||
let path = AttributeKey<String>(name: "Path") | ||
let operation = AttributeKey<String>(name: "Operation") | ||
let host = AttributeKey<String>(name: "Host") | ||
let serviceName = AttributeKey<String>(name: "ServiceName") | ||
var response: HttpResponse = HttpResponse() | ||
let decoder = AttributeKey<ResponseDecoder>(name: "Decoder") | ||
let idempotencyTokenGenerator = AttributeKey<IdempotencyTokenGenerator>(name: "IdempotencyTokenGenerator") | ||
let hostPrefix = AttributeKey<String>(name: "HostPrefix") | ||
let logger = AttributeKey<LogAgent>(name: "Logger") | ||
let partitionID = AttributeKey<String>(name: "PartitionID") | ||
|
||
// We follow the convention of returning the builder object | ||
// itself from any configuration methods, and by adding the | ||
|
@@ -108,84 +94,104 @@ public class HttpContextBuilder { | |
} | ||
|
||
@discardableResult | ||
public func withEncoder(value: RequestEncoder) -> HttpContextBuilder { | ||
self.attributes.set(key: encoder, value: value) | ||
public func withDecoder(value: ResponseDecoder) -> HttpContextBuilder { | ||
self.attributes.set(key: AttributeKeys.decoder, value: value) | ||
return self | ||
} | ||
|
||
@discardableResult | ||
public func withMethod(value: HttpMethodType) -> HttpContextBuilder { | ||
self.attributes.set(key: method, value: value) | ||
public func withEncoder(value: RequestEncoder) -> HttpContextBuilder { | ||
self.attributes.set(key: AttributeKeys.encoder, value: value) | ||
return self | ||
} | ||
|
||
@discardableResult | ||
public func withPath(value: String) -> HttpContextBuilder { | ||
self.attributes.set(key: path, value: value) | ||
public func withHost(value: String) -> HttpContextBuilder { | ||
self.attributes.set(key: AttributeKeys.host, value: value) | ||
return self | ||
} | ||
|
||
@discardableResult | ||
public func withHost(value: String) -> HttpContextBuilder { | ||
self.attributes.set(key: host, value: value) | ||
public func withHostPrefix(value: String) -> HttpContextBuilder { | ||
self.attributes.set(key: AttributeKeys.hostPrefix, value: value) | ||
return self | ||
} | ||
|
||
@discardableResult | ||
public func withHostPrefix(value: String) -> HttpContextBuilder { | ||
self.attributes.set(key: hostPrefix, value: value) | ||
public func withIdempotencyTokenGenerator(value: IdempotencyTokenGenerator) -> HttpContextBuilder { | ||
self.attributes.set(key: AttributeKeys.idempotencyTokenGenerator, value: value) | ||
return self | ||
} | ||
|
||
@discardableResult | ||
public func withOperation(value: String) -> HttpContextBuilder { | ||
self.attributes.set(key: operation, value: value) | ||
public func withLogger(value: LogAgent) -> HttpContextBuilder { | ||
self.attributes.set(key: AttributeKeys.logger, value: value) | ||
return self | ||
} | ||
|
||
@discardableResult | ||
public func withServiceName(value: String) -> HttpContextBuilder { | ||
self.attributes.set(key: serviceName, value: value) | ||
public func withMethod(value: HttpMethodType) -> HttpContextBuilder { | ||
self.attributes.set(key: AttributeKeys.method, value: value) | ||
return self | ||
} | ||
|
||
@discardableResult | ||
public func withDecoder(value: ResponseDecoder) -> HttpContextBuilder { | ||
self.attributes.set(key: decoder, value: value) | ||
public func withOperation(value: String) -> HttpContextBuilder { | ||
self.attributes.set(key: AttributeKeys.operation, value: value) | ||
return self | ||
} | ||
|
||
/// Sets the partition ID on the context builder. | ||
/// | ||
/// Requests made with the same partition ID will be grouped together for retry throttling purposes. | ||
/// If no partition ID is provided, requests will be partitioned based on the hostname. | ||
/// - Parameter value: The partition ID to be set on this builder, or `nil`. | ||
/// - Returns: `self`, after the partition ID is set as specified. | ||
@discardableResult | ||
public func withResponse(value: HttpResponse) -> HttpContextBuilder { | ||
self.response = value | ||
public func withPartitionID(value: String?) -> HttpContextBuilder { | ||
self.attributes.set(key: AttributeKeys.partitionId, value: value) | ||
return self | ||
} | ||
|
||
@discardableResult | ||
public func withIdempotencyTokenGenerator(value: IdempotencyTokenGenerator) -> HttpContextBuilder { | ||
self.attributes.set(key: idempotencyTokenGenerator, value: value) | ||
public func withPath(value: String) -> HttpContextBuilder { | ||
self.attributes.set(key: AttributeKeys.path, value: value) | ||
return self | ||
} | ||
|
||
@discardableResult | ||
public func withLogger(value: LogAgent) -> HttpContextBuilder { | ||
self.attributes.set(key: logger, value: value) | ||
public func withResponse(value: HttpResponse) -> HttpContextBuilder { | ||
self.response = value | ||
return self | ||
} | ||
|
||
/// Sets the partition ID on the context builder. | ||
/// | ||
/// Requests made with the same partition ID will be grouped together for retry throttling purposes. | ||
/// If no partition ID is provided, requests will be partitioned based on the hostname. | ||
/// - Parameter value: The partition ID to be set on this builder, or `nil`. | ||
/// - Returns: `self`, after the partition ID is set as specified. | ||
@discardableResult | ||
public func withPartitionID(value: String?) -> HttpContextBuilder { | ||
self.attributes.set(key: partitionID, value: value) | ||
public func withServiceName(value: String) -> HttpContextBuilder { | ||
self.attributes.set(key: AttributeKeys.serviceName, value: value) | ||
return self | ||
} | ||
|
||
public func build() -> HttpContext { | ||
return HttpContext(attributes: attributes) | ||
} | ||
} | ||
|
||
public enum AttributeKeys { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Same comment as on the SDK There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Responded to comment on the SDK side. |
||
public static let bidirectionalStreaming = AttributeKey<Bool>(name: "BidirectionalStreaming") | ||
public static let decoder = AttributeKey<ResponseDecoder>(name: "Decoder") | ||
public static let encoder = AttributeKey<RequestEncoder>(name: "Encoder") | ||
public static let host = AttributeKey<String>(name: "Host") | ||
public static let hostPrefix = AttributeKey<String>(name: "HostPrefix") | ||
public static let idempotencyTokenGenerator = AttributeKey<IdempotencyTokenGenerator>( | ||
name: "IdempotencyTokenGenerator" | ||
) | ||
public static let identityResolvers = AttributeKey<Attributes>(name: "IdentityResolvers") | ||
public static let logger = AttributeKey<LogAgent>(name: "Logger") | ||
public static let messageEncoder = AttributeKey<MessageEncoder>(name: "MessageEncoder") | ||
public static let messageSigner = AttributeKey<MessageSigner>(name: "MessageSigner") | ||
public static let method = AttributeKey<HttpMethodType>(name: "Method") | ||
public static let operation = AttributeKey<String>(name: "Operation") | ||
public static let partitionId = AttributeKey<String>(name: "PartitionID") | ||
public static let path = AttributeKey<String>(name: "Path") | ||
public static let serviceName = AttributeKey<String>(name: "ServiceName") | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Generic in the method signature versus an associated type on the
Signer
protocol provides enough flexibility here?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I believe so, yes.