Skip to content

Commit

Permalink
chore: Add signer protocol. (#598)
Browse files Browse the repository at this point in the history
* Add signer protocol & refactor HttpContext

---------

Co-authored-by: Sichan Yoo <chanyoo@amazon.com>
  • Loading branch information
sichanyoo and Sichan Yoo authored Oct 9, 2023
1 parent fb6ab10 commit 272aec6
Show file tree
Hide file tree
Showing 2 changed files with 94 additions and 72 deletions.
16 changes: 16 additions & 0 deletions Sources/ClientRuntime/Auth/HTTPAuthAPI/Signer.swift
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
}
150 changes: 78 additions & 72 deletions Sources/ClientRuntime/Networking/Http/HttpContext.swift
Original file line number Diff line number Diff line change
Expand Up @@ -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)!
}

/// 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)!
}

public func getMessageSigner() -> MessageSigner? {
return attributes.get(key: HttpContext.messageSigner)
public func getServiceName() -> String {
return attributes.get(key: AttributeKeys.serviceName)!
}

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`
Expand All @@ -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
Expand All @@ -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 {
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")
}

0 comments on commit 272aec6

Please sign in to comment.