Skip to content

Commit 14ab532

Browse files
authored
fix: RPCv2CBOR query compatible support (#927)
1 parent fa661d2 commit 14ab532

File tree

7 files changed

+88
-4
lines changed

7 files changed

+88
-4
lines changed

Sources/ClientRuntime/protocols/rpcv2cbor/RpcV2CborError.swift

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,12 +19,13 @@ public struct RpcV2CborError: BaseError {
1919

2020
@_spi(SmithyReadWrite)
2121
public init(httpResponse: HTTPResponse, responseReader: Reader, noErrorWrapping: Bool, code: String? = nil) throws {
22+
let sanitizedCode = code.map { sanitizeErrorType($0) }
2223
switch responseReader.cborValue {
2324
case .map(let errorDetails):
2425
if case let .text(errorCode) = errorDetails["__type"] {
25-
self.code = sanitizeErrorType(errorCode)
26+
self.code = sanitizedCode ?? sanitizeErrorType(errorCode)
2627
} else {
27-
self.code = "UnknownError"
28+
self.code = sanitizedCode ?? "UnknownError"
2829
}
2930

3031
if case let .text(errorMessage) = errorDetails["Message"] {
@@ -33,7 +34,7 @@ public struct RpcV2CborError: BaseError {
3334
self.message = nil
3435
}
3536
default:
36-
self.code = "UnknownError"
37+
self.code = sanitizedCode ?? "UnknownError"
3738
self.message = nil
3839
}
3940

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
//
2+
// Copyright Amazon.com Inc. or its affiliates.
3+
// All Rights Reserved.
4+
//
5+
// SPDX-License-Identifier: Apache-2.0
6+
//
7+
8+
@_spi(SmithyReadWrite) import class SmithyCBOR.Reader
9+
import class SmithyHTTPAPI.HTTPResponse
10+
11+
@_spi(SmithyReadWrite)
12+
public enum RpcV2CborQueryCompatibleUtils {
13+
14+
// This function returns a standard RpcV2Cbor base error
15+
// without the passed error details.
16+
//
17+
// QueryCompatibleUtils with error parsing are implemented
18+
// in AWS SDK for Swift.
19+
public static func makeQueryCompatibleError(
20+
httpResponse: HTTPResponse,
21+
responseReader: SmithyCBOR.Reader,
22+
noErrorWrapping: Bool,
23+
errorDetails: String?
24+
) throws -> RpcV2CborError {
25+
return try RpcV2CborError(
26+
httpResponse: httpResponse,
27+
responseReader: responseReader,
28+
noErrorWrapping: noErrorWrapping
29+
)
30+
}
31+
}
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
//
2+
// Copyright Amazon.com Inc. or its affiliates.
3+
// All Rights Reserved.
4+
//
5+
// SPDX-License-Identifier: Apache-2.0
6+
//
7+
8+
import XCTest
9+
@_spi(SmithyReadWrite) import struct ClientRuntime.RpcV2CborError
10+
import class SmithyHTTPAPI.HTTPResponse
11+
@_spi(SmithyReadWrite) import class SmithyCBOR.Reader
12+
13+
final class RpcV2CborErrorTests: XCTestCase {
14+
let cborCode = "abc-def"
15+
let passedCode = "ghi-jkl"
16+
17+
func test_init_usesCodeInCborMap() throws {
18+
let reader = Reader(nodeInfo: "", cborValue: .map(["__type": .text(cborCode)]))
19+
let httpResponse = HTTPResponse(body: .data(Data()), statusCode: .ok)
20+
let subject = try RpcV2CborError(httpResponse: httpResponse, responseReader: reader, noErrorWrapping: false)
21+
XCTAssertEqual(subject.code, cborCode)
22+
}
23+
24+
func test_init_usesUnknownErrorCodeWhenCborMapIsEmpty() throws {
25+
let reader = Reader(nodeInfo: "", cborValue: .map([:]))
26+
let httpResponse = HTTPResponse(body: .data(Data()), statusCode: .ok)
27+
let subject = try RpcV2CborError(httpResponse: httpResponse, responseReader: reader, noErrorWrapping: false)
28+
XCTAssertEqual(subject.code, "UnknownError")
29+
}
30+
31+
32+
func test_init_usesUnknownErrorCodeWhenDataIsNotCborMap() throws {
33+
let reader = Reader(nodeInfo: "", cborValue: .array([]))
34+
let httpResponse = HTTPResponse(body: .data(Data()), statusCode: .ok)
35+
let subject = try RpcV2CborError(httpResponse: httpResponse, responseReader: reader, noErrorWrapping: false)
36+
XCTAssertEqual(subject.code, "UnknownError")
37+
}
38+
39+
func test_init_overridesCodeWithPassedCodeWhenNonNil() throws {
40+
let reader = Reader(nodeInfo: "", cborValue: .map(["__type": .text(cborCode)]))
41+
let httpResponse = HTTPResponse(body: .data(Data()), statusCode: .ok)
42+
let subject = try RpcV2CborError(httpResponse: httpResponse, responseReader: reader, noErrorWrapping: false, code: passedCode)
43+
XCTAssertEqual(subject.code, passedCode)
44+
}
45+
}

smithy-swift-codegen/src/main/kotlin/software/amazon/smithy/swift/codegen/integration/DefaultHTTPProtocolCustomizations.kt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,8 @@ abstract class DefaultHTTPProtocolCustomizations : HTTPProtocolCustomizable {
4242

4343
override val baseErrorSymbol: Symbol = SmithyTestUtilTypes.TestBaseError
4444

45+
override val queryCompatibleUtilsSymbol: Symbol = ClientRuntimeTypes.RpcV2Cbor.RpcV2CborQueryCompatibleUtils
46+
4547
override val unknownServiceErrorSymbol: Symbol = ClientRuntimeTypes.Http.UnknownHttpServiceError
4648

4749
override val defaultTimestampFormat = TimestampFormatTrait.Format.EPOCH_SECONDS

smithy-swift-codegen/src/main/kotlin/software/amazon/smithy/swift/codegen/integration/HTTPProtocolCustomizable.kt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,8 @@ interface HTTPProtocolCustomizable {
5555

5656
val baseErrorSymbol: Symbol
5757

58+
val queryCompatibleUtilsSymbol: Symbol
59+
5860
val unknownServiceErrorSymbol: Symbol
5961

6062
val defaultTimestampFormat: TimestampFormatTrait.Format

smithy-swift-codegen/src/main/kotlin/software/amazon/smithy/swift/codegen/integration/httpResponse/HTTPResponseBindingErrorGenerator.kt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -103,8 +103,9 @@ class HTTPResponseBindingErrorGenerator(
103103
if (ctx.service.hasTrait<AwsQueryCompatibleTrait>()) {
104104
writer.write("let errorDetails = httpResponse.headers.value(for: \"x-amzn-query-error\")")
105105
writer.write(
106-
"let baseError = try \$N.makeQueryCompatibleError(httpResponse: httpResponse, responseReader: responseReader, noErrorWrapping: \$L, errorDetails: errorDetails)",
106+
"let baseError: \$N = try \$N.makeQueryCompatibleError(httpResponse: httpResponse, responseReader: responseReader, noErrorWrapping: \$L, errorDetails: errorDetails)",
107107
customizations.baseErrorSymbol,
108+
customizations.queryCompatibleUtilsSymbol,
108109
noErrorWrapping,
109110
)
110111
} else {

smithy-swift-codegen/src/main/kotlin/software/amazon/smithy/swift/codegen/swiftmodules/ClientRuntimeTypes.kt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,8 @@ object ClientRuntimeTypes {
9898

9999
object RpcV2Cbor {
100100
val RpcV2CborError = runtimeSymbol("RpcV2CborError", SwiftDeclaration.STRUCT, emptyList(), listOf("SmithyReadWrite"))
101+
val RpcV2CborQueryCompatibleUtils =
102+
runtimeSymbol("RpcV2CborQueryCompatibleUtils", SwiftDeclaration.ENUM, emptyList(), listOf("SmithyReadWrite"))
101103
val CborValidateResponseHeaderMiddleware = runtimeSymbol("CborValidateResponseHeaderMiddleware", SwiftDeclaration.STRUCT)
102104
}
103105
}

0 commit comments

Comments
 (0)