diff --git a/aws-runtime/aws-config/common/src/aws/sdk/kotlin/runtime/auth/credentials/EcsCredentialsProvider.kt b/aws-runtime/aws-config/common/src/aws/sdk/kotlin/runtime/auth/credentials/EcsCredentialsProvider.kt index 40e707968ac..cc2f5ccc9e5 100644 --- a/aws-runtime/aws-config/common/src/aws/sdk/kotlin/runtime/auth/credentials/EcsCredentialsProvider.kt +++ b/aws-runtime/aws-config/common/src/aws/sdk/kotlin/runtime/auth/credentials/EcsCredentialsProvider.kt @@ -87,8 +87,8 @@ public class EcsCredentialsProvider( } val op = SdkHttpOperation.build { - serializer = EcsCredentialsSerializer(authToken) - deserializer = EcsCredentialsDeserializer() + serializeWith = EcsCredentialsSerializer(authToken) + deserializeWith = EcsCredentialsDeserializer() operationName = "EcsCredentialsProvider" serviceName = "EcsContainerMetadata" execution.endpointResolver = EndpointResolver { Endpoint(url) } @@ -196,14 +196,14 @@ public class EcsCredentialsProvider( override fun toString(): String = this.simpleClassName } -private class EcsCredentialsDeserializer : HttpDeserialize { - override suspend fun deserialize(context: ExecutionContext, call: HttpCall): Credentials { +private class EcsCredentialsDeserializer : HttpDeserializer.NonStreaming { + override fun deserialize(context: ExecutionContext, call: HttpCall, payload: ByteArray?): Credentials { val response = call.response if (!response.status.isSuccess()) { - throwCredentialsResponseException(response) + throwCredentialsResponseException(response, payload) } - val payload = response.body.readAll() ?: throw CredentialsProviderException("HTTP credentials response did not contain a payload") + if (payload == null) throw CredentialsProviderException("HTTP credentials response did not contain a payload") val deserializer = JsonDeserializer(payload) val resp = deserializeJsonCredentials(deserializer) if (resp !is JsonCredentialsResponse.SessionCredentials) { @@ -221,8 +221,8 @@ private class EcsCredentialsDeserializer : HttpDeserialize { } } -private suspend fun throwCredentialsResponseException(response: HttpResponse): Nothing { - val errorResp = tryParseErrorResponse(response) +private fun throwCredentialsResponseException(response: HttpResponse, payload: ByteArray?): Nothing { + val errorResp = tryParseErrorResponse(response, payload) val messageDetails = errorResp?.run { "code=$code; message=$message" } ?: "HTTP ${response.status}" throw CredentialsProviderException("Error retrieving credentials from container service: $messageDetails").apply { @@ -233,17 +233,15 @@ private suspend fun throwCredentialsResponseException(response: HttpResponse): N } } -private suspend fun tryParseErrorResponse(response: HttpResponse): JsonCredentialsResponse.Error? { - if (response.headers["Content-Type"] != "application/json") return null - val payload = response.body.readAll() ?: return null - +private fun tryParseErrorResponse(response: HttpResponse, payload: ByteArray?): JsonCredentialsResponse.Error? { + if (response.headers["Content-Type"] != "application/json" || payload == null) return null return deserializeJsonCredentials(JsonDeserializer(payload)) as? JsonCredentialsResponse.Error } private class EcsCredentialsSerializer( private val authToken: String? = null, -) : HttpSerialize { - override suspend fun serialize(context: ExecutionContext, input: Unit): HttpRequestBuilder { +) : HttpSerializer.NonStreaming { + override fun serialize(context: ExecutionContext, input: Unit): HttpRequestBuilder { val builder = HttpRequestBuilder() builder.url.path builder.header("Accept", "application/json") diff --git a/aws-runtime/aws-config/common/src/aws/sdk/kotlin/runtime/auth/credentials/JsonCredentialsDeserializer.kt b/aws-runtime/aws-config/common/src/aws/sdk/kotlin/runtime/auth/credentials/JsonCredentialsDeserializer.kt index 21dc4ed3b4e..51eace3bb53 100644 --- a/aws-runtime/aws-config/common/src/aws/sdk/kotlin/runtime/auth/credentials/JsonCredentialsDeserializer.kt +++ b/aws-runtime/aws-config/common/src/aws/sdk/kotlin/runtime/auth/credentials/JsonCredentialsDeserializer.kt @@ -74,7 +74,7 @@ internal sealed class JsonCredentialsResponse { * ``` */ @Suppress("ktlint:standard:property-naming") -internal suspend fun deserializeJsonCredentials(deserializer: Deserializer): JsonCredentialsResponse { +internal fun deserializeJsonCredentials(deserializer: Deserializer): JsonCredentialsResponse { val CODE_DESCRIPTOR = SdkFieldDescriptor(SerialKind.String, JsonSerialName("Code")) val ACCESS_KEY_ID_DESCRIPTOR = SdkFieldDescriptor(SerialKind.String, JsonSerialName("AccessKeyId")) val SECRET_ACCESS_KEY_ID_DESCRIPTOR = SdkFieldDescriptor(SerialKind.String, JsonSerialName("SecretAccessKey")) diff --git a/aws-runtime/aws-config/common/src/aws/sdk/kotlin/runtime/config/imds/ImdsClient.kt b/aws-runtime/aws-config/common/src/aws/sdk/kotlin/runtime/config/imds/ImdsClient.kt index 3f42f62edc4..ac4cbf9549b 100644 --- a/aws-runtime/aws-config/common/src/aws/sdk/kotlin/runtime/config/imds/ImdsClient.kt +++ b/aws-runtime/aws-config/common/src/aws/sdk/kotlin/runtime/config/imds/ImdsClient.kt @@ -12,10 +12,13 @@ import aws.sdk.kotlin.runtime.http.middleware.UserAgent import aws.smithy.kotlin.runtime.client.LogMode import aws.smithy.kotlin.runtime.client.SdkClientOption import aws.smithy.kotlin.runtime.client.endpoints.Endpoint -import aws.smithy.kotlin.runtime.http.* +import aws.smithy.kotlin.runtime.http.HttpCall +import aws.smithy.kotlin.runtime.http.HttpStatusCode +import aws.smithy.kotlin.runtime.http.SdkHttpClient import aws.smithy.kotlin.runtime.http.engine.DefaultHttpEngine import aws.smithy.kotlin.runtime.http.engine.HttpClientEngine import aws.smithy.kotlin.runtime.http.engine.ProxySelector +import aws.smithy.kotlin.runtime.http.isSuccess import aws.smithy.kotlin.runtime.http.operation.* import aws.smithy.kotlin.runtime.io.Closeable import aws.smithy.kotlin.runtime.io.closeIfCloseable @@ -109,15 +112,14 @@ public class ImdsClient private constructor(builder: Builder) : InstanceMetadata */ public override suspend fun get(path: String): String { val op = SdkHttpOperation.build { - serializer = UnitSerializer - deserializer = object : HttpDeserialize { - override suspend fun deserialize(context: ExecutionContext, call: HttpCall): String { + serializeWith = HttpSerializer.Unit + deserializeWith = object : HttpDeserializer.NonStreaming { + override fun deserialize(context: ExecutionContext, call: HttpCall, payload: ByteArray?): String { val response = call.response if (response.status.isSuccess()) { - val payload = response.body.readAll() ?: throw EC2MetadataError(response.status.value, "no metadata payload") - return payload.decodeToString() + return payload!!.decodeToString() } else { - throw EC2MetadataError(response.status.value, "error retrieving instance metadata: ${response.status.description}") + throw EC2MetadataError(response.status, "error retrieving instance metadata: ${response.status.description}") } } } @@ -232,9 +234,9 @@ public enum class EndpointMode(internal val defaultEndpoint: Endpoint) { * @param message The error message */ public class EC2MetadataError(public val status: HttpStatusCode, message: String) : AwsServiceException(message) { - @Deprecated("This constructor passes HTTP status as an Int instead of as HttpStatusCode") + @Deprecated("This constructor passes HTTP status as an Int instead of as HttpStatusCode. This declaration will be removed in version 1.6.x.") public constructor(statusCode: Int, message: String) : this(HttpStatusCode.fromValue(statusCode), message) - @Deprecated("This property is now deprecated and should be fetched from status.value") + @Deprecated("This property is now deprecated and should be fetched from status.value. This declaration will be removed in version 1.6.x.") public val statusCode: Int = status.value } diff --git a/aws-runtime/aws-endpoint/api/aws-endpoint.api b/aws-runtime/aws-endpoint/api/aws-endpoint.api index 422fd99f426..5920133c895 100644 --- a/aws-runtime/aws-endpoint/api/aws-endpoint.api +++ b/aws-runtime/aws-endpoint/api/aws-endpoint.api @@ -42,12 +42,6 @@ public final class aws/sdk/kotlin/runtime/endpoint/functions/Partition { public final class aws/sdk/kotlin/runtime/endpoint/functions/PartitionConfig { public fun ()V - public fun (Ljava/lang/String;)V - public fun (Ljava/lang/String;Ljava/lang/String;)V - public fun (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V - public fun (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/Boolean;)V - public fun (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/Boolean;Ljava/lang/Boolean;)V - public synthetic fun (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/Boolean;Ljava/lang/Boolean;ILkotlin/jvm/internal/DefaultConstructorMarker;)V public fun (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/Boolean;Ljava/lang/Boolean;Ljava/lang/String;)V public synthetic fun (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/Boolean;Ljava/lang/Boolean;Ljava/lang/String;ILkotlin/jvm/internal/DefaultConstructorMarker;)V public final fun component1 ()Ljava/lang/String; diff --git a/aws-runtime/aws-endpoint/common/src/aws/sdk/kotlin/runtime/endpoint/functions/Functions.kt b/aws-runtime/aws-endpoint/common/src/aws/sdk/kotlin/runtime/endpoint/functions/Functions.kt index c59fc81c891..6493cc1d4d1 100644 --- a/aws-runtime/aws-endpoint/common/src/aws/sdk/kotlin/runtime/endpoint/functions/Functions.kt +++ b/aws-runtime/aws-endpoint/common/src/aws/sdk/kotlin/runtime/endpoint/functions/Functions.kt @@ -9,7 +9,6 @@ import aws.sdk.kotlin.runtime.InternalSdkApi import aws.smithy.kotlin.runtime.client.endpoints.functions.isValidHostLabel import aws.smithy.kotlin.runtime.net.isIpv4 import aws.smithy.kotlin.runtime.net.isIpv6 -import kotlin.jvm.JvmOverloads // the number of top-level components an arn contains (separated by colons) private const val ARN_COMPONENT_COUNT = 6 @@ -70,23 +69,6 @@ public data class PartitionConfig( public val supportsDualStack: Boolean? = null, public val implicitGlobalRegion: String? = null, ) { - @Deprecated("This constructor does not support implicitGlobalRegion") // but is added for backwards compatibility - @JvmOverloads - public constructor ( - name: String? = null, - dnsSuffix: String? = null, - dualStackDnsSuffix: String? = null, - supportsFIPS: Boolean? = null, - supportsDualStack: Boolean? = null, - ) : this( - name, - dnsSuffix, - dualStackDnsSuffix, - supportsFIPS, - supportsDualStack, - null, - ) - public fun mergeWith(other: PartitionConfig): PartitionConfig = PartitionConfig( other.name ?: name, diff --git a/aws-runtime/aws-http/api/aws-http.api b/aws-runtime/aws-http/api/aws-http.api index 1b6ced4a550..fea5bdc046c 100644 --- a/aws-runtime/aws-http/api/aws-http.api +++ b/aws-runtime/aws-http/api/aws-http.api @@ -168,29 +168,6 @@ public final class aws/sdk/kotlin/runtime/http/interceptors/IgnoreCompositeFlexi public fun ignoreChecksum (Ljava/lang/String;Laws/smithy/kotlin/runtime/client/ProtocolResponseInterceptorContext;)Z } -public final class aws/sdk/kotlin/runtime/http/interceptors/UnsupportedSigningAlgorithmInterceptor : aws/smithy/kotlin/runtime/client/Interceptor { - public fun ()V - public fun modifyBeforeAttemptCompletion-gIAlu-s (Laws/smithy/kotlin/runtime/client/ResponseInterceptorContext;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public fun modifyBeforeCompletion-gIAlu-s (Laws/smithy/kotlin/runtime/client/ResponseInterceptorContext;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public fun modifyBeforeDeserialization (Laws/smithy/kotlin/runtime/client/ProtocolResponseInterceptorContext;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public fun modifyBeforeRetryLoop (Laws/smithy/kotlin/runtime/client/ProtocolRequestInterceptorContext;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public fun modifyBeforeSerialization (Laws/smithy/kotlin/runtime/client/RequestInterceptorContext;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public fun modifyBeforeSigning (Laws/smithy/kotlin/runtime/client/ProtocolRequestInterceptorContext;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public fun modifyBeforeTransmit (Laws/smithy/kotlin/runtime/client/ProtocolRequestInterceptorContext;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public fun readAfterAttempt (Laws/smithy/kotlin/runtime/client/ResponseInterceptorContext;)V - public fun readAfterDeserialization (Laws/smithy/kotlin/runtime/client/ResponseInterceptorContext;)V - public fun readAfterExecution (Laws/smithy/kotlin/runtime/client/ResponseInterceptorContext;)V - public fun readAfterSerialization (Laws/smithy/kotlin/runtime/client/ProtocolRequestInterceptorContext;)V - public fun readAfterSigning (Laws/smithy/kotlin/runtime/client/ProtocolRequestInterceptorContext;)V - public fun readAfterTransmit (Laws/smithy/kotlin/runtime/client/ProtocolResponseInterceptorContext;)V - public fun readBeforeAttempt (Laws/smithy/kotlin/runtime/client/ProtocolRequestInterceptorContext;)V - public fun readBeforeDeserialization (Laws/smithy/kotlin/runtime/client/ProtocolResponseInterceptorContext;)V - public fun readBeforeExecution (Laws/smithy/kotlin/runtime/client/RequestInterceptorContext;)V - public fun readBeforeSerialization (Laws/smithy/kotlin/runtime/client/RequestInterceptorContext;)V - public fun readBeforeSigning (Laws/smithy/kotlin/runtime/client/ProtocolRequestInterceptorContext;)V - public fun readBeforeTransmit (Laws/smithy/kotlin/runtime/client/ProtocolRequestInterceptorContext;)V -} - public final class aws/sdk/kotlin/runtime/http/interceptors/businessmetrics/AwsBusinessMetric : java/lang/Enum, aws/smithy/kotlin/runtime/businessmetrics/BusinessMetric { public static final field DDB_MAPPER Laws/sdk/kotlin/runtime/http/interceptors/businessmetrics/AwsBusinessMetric; public static final field S3_EXPRESS_BUCKET Laws/sdk/kotlin/runtime/http/interceptors/businessmetrics/AwsBusinessMetric; diff --git a/aws-runtime/aws-http/common/src/aws/sdk/kotlin/runtime/http/interceptors/UnsupportedSigningAlgorithmInterceptor.kt b/aws-runtime/aws-http/common/src/aws/sdk/kotlin/runtime/http/interceptors/UnsupportedSigningAlgorithmInterceptor.kt deleted file mode 100644 index d1e70eb706f..00000000000 --- a/aws-runtime/aws-http/common/src/aws/sdk/kotlin/runtime/http/interceptors/UnsupportedSigningAlgorithmInterceptor.kt +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. - * SPDX-License-Identifier: Apache-2.0 - */ -package aws.sdk.kotlin.runtime.http.interceptors - -import aws.sdk.kotlin.runtime.InternalSdkApi -import aws.smithy.kotlin.runtime.auth.awssigning.AwsSigningAlgorithm -import aws.smithy.kotlin.runtime.auth.awssigning.UnsupportedSigningAlgorithmException -import aws.smithy.kotlin.runtime.client.ResponseInterceptorContext -import aws.smithy.kotlin.runtime.http.interceptors.HttpInterceptor -import aws.smithy.kotlin.runtime.http.request.HttpRequest -import aws.smithy.kotlin.runtime.http.response.HttpResponse - -// FIXME: Remove this once sigV4a is supported by default AWS signer -/** - * Looks for an unsupported signing algorithm error caused by sigV4a. - * If so it sends users to a section in the AWS SDK for Kotlin documentation on how to fix it. - */ -@InternalSdkApi -@Deprecated("This interceptor is no longer used. It will be removed in the next minor version, v1.5.x.") -public class UnsupportedSigningAlgorithmInterceptor : HttpInterceptor { - override suspend fun modifyBeforeCompletion(context: ResponseInterceptorContext): Result { - context.response.exceptionOrNull()?.let { - if (it is UnsupportedSigningAlgorithmException && it.signingAlgorithm == AwsSigningAlgorithm.SIGV4_ASYMMETRIC) { - return Result.failure( - UnsupportedSigningAlgorithmException( - "SIGV4A support is not yet implemented for the default signer. For more information on how to enable it with the CRT signer, please refer to: https://a.co/3sf8533", - it.signingAlgorithm, - it, - ), - ) - } - } - return super.modifyBeforeCompletion(context) - } -} diff --git a/aws-runtime/aws-http/common/test/aws/sdk/kotlin/runtime/http/interceptors/UnsupportedSigningAlgorithmInterceptorTest.kt b/aws-runtime/aws-http/common/test/aws/sdk/kotlin/runtime/http/interceptors/UnsupportedSigningAlgorithmInterceptorTest.kt deleted file mode 100644 index d1034d48c29..00000000000 --- a/aws-runtime/aws-http/common/test/aws/sdk/kotlin/runtime/http/interceptors/UnsupportedSigningAlgorithmInterceptorTest.kt +++ /dev/null @@ -1,78 +0,0 @@ -/* - * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. - * SPDX-License-Identifier: Apache-2.0 - */ -package aws.sdk.kotlin.runtime.http.interceptors - -import aws.smithy.kotlin.runtime.auth.awssigning.AwsSigningAlgorithm -import aws.smithy.kotlin.runtime.auth.awssigning.UnsupportedSigningAlgorithmException -import aws.smithy.kotlin.runtime.client.ResponseInterceptorContext -import aws.smithy.kotlin.runtime.client.SdkClientOption -import aws.smithy.kotlin.runtime.http.request.HttpRequest -import aws.smithy.kotlin.runtime.http.response.HttpResponse -import aws.smithy.kotlin.runtime.operation.ExecutionContext -import kotlinx.coroutines.test.runTest -import kotlin.test.Test -import kotlin.test.assertEquals -import kotlin.test.assertIs -import kotlin.test.assertTrue - -class UnsupportedSigningAlgorithmInterceptorTest { - @Test - fun testUnsupportedSigningAlgorithmSigV4a() = runTest { - val result = - UnsupportedSigningAlgorithmInterceptor() - .modifyBeforeCompletion( - context( - Result.failure( - UnsupportedSigningAlgorithmException( - "SIGV4A support is not yet implemented for the default signer.", - AwsSigningAlgorithm.SIGV4_ASYMMETRIC, - ), - ), - ), - ) - - val exception = result.exceptionOrNull() - - assertTrue(result.isFailure) - assertIs(exception) - assertEquals(exception.signingAlgorithm, AwsSigningAlgorithm.SIGV4_ASYMMETRIC) - assertEquals( - "SIGV4A support is not yet implemented for the default signer. For more information on how to enable it with the CRT signer, please refer to: https://a.co/3sf8533", - exception.message, - ) - } - - @Test - fun testUnsupportedSigningAlgorithmNotSigV4a() = runTest { - val result = - UnsupportedSigningAlgorithmInterceptor() - .modifyBeforeCompletion( - context( - Result.failure( - UnsupportedSigningAlgorithmException( - "SIGV4 support is not yet implemented for the default signer.", - AwsSigningAlgorithm.SIGV4, - ), - ), - ), - ) - - val exception = result.exceptionOrNull() - - assertTrue(result.isFailure) - assertIs(exception) - assertEquals(exception.signingAlgorithm, AwsSigningAlgorithm.SIGV4) - assertEquals("SIGV4 support is not yet implemented for the default signer.", exception.message) - } -} - -private fun context(response: Result) = - object : ResponseInterceptorContext { - override val executionContext = ExecutionContext.build { attributes[SdkClientOption.OperationName] = "test" } - override val request = Unit - override val response = response - override val protocolRequest = HttpRequest { } - override val protocolResponse = null - } diff --git a/aws-runtime/aws-http/common/test/aws/sdk/kotlin/runtime/http/middleware/AwsRetryHeaderMiddlewareTest.kt b/aws-runtime/aws-http/common/test/aws/sdk/kotlin/runtime/http/middleware/AwsRetryHeaderMiddlewareTest.kt index d07108a70cf..c34c9e682b0 100644 --- a/aws-runtime/aws-http/common/test/aws/sdk/kotlin/runtime/http/middleware/AwsRetryHeaderMiddlewareTest.kt +++ b/aws-runtime/aws-http/common/test/aws/sdk/kotlin/runtime/http/middleware/AwsRetryHeaderMiddlewareTest.kt @@ -21,8 +21,8 @@ class AwsRetryHeaderMiddlewareTest { fun testItSetsRetryHeaders() = runTest { // see retry-header SEP val op = SdkHttpOperation.build { - serializer = UnitSerializer - deserializer = UnitDeserializer + serializeWith = HttpSerializer.Unit + deserializeWith = HttpDeserializer.Unit operationName = "TestOperation" serviceName = "TestService" } diff --git a/aws-runtime/aws-http/common/test/aws/sdk/kotlin/runtime/http/middleware/RecursionDetectionTest.kt b/aws-runtime/aws-http/common/test/aws/sdk/kotlin/runtime/http/middleware/RecursionDetectionTest.kt index bc957564efa..29a81c62cbb 100644 --- a/aws-runtime/aws-http/common/test/aws/sdk/kotlin/runtime/http/middleware/RecursionDetectionTest.kt +++ b/aws-runtime/aws-http/common/test/aws/sdk/kotlin/runtime/http/middleware/RecursionDetectionTest.kt @@ -21,8 +21,8 @@ import kotlin.test.assertFalse class RecursionDetectionTest { private class TraceHeaderSerializer( private val traceHeader: String, - ) : HttpSerialize { - override suspend fun serialize(context: ExecutionContext, input: Unit): HttpRequestBuilder { + ) : HttpSerializer.NonStreaming { + override fun serialize(context: ExecutionContext, input: Unit): HttpRequestBuilder { val builder = HttpRequestBuilder() builder.headers[HEADER_TRACE_ID] = traceHeader return builder @@ -37,8 +37,13 @@ class RecursionDetectionTest { expectedTraceHeader: String?, ) { val op = SdkHttpOperation.build { - serializer = if (existingTraceHeader != null) TraceHeaderSerializer(existingTraceHeader) else UnitSerializer - deserializer = IdentityDeserializer + serializeWith = if (existingTraceHeader != null) { + TraceHeaderSerializer(existingTraceHeader) + } else { + HttpSerializer.Unit + } + + deserializeWith = HttpDeserializer.Identity operationName = "testOperation" serviceName = "TestService" } diff --git a/aws-runtime/aws-http/common/test/aws/sdk/kotlin/runtime/http/middleware/UserAgentTest.kt b/aws-runtime/aws-http/common/test/aws/sdk/kotlin/runtime/http/middleware/UserAgentTest.kt index a2fcd4259cd..332a5ee3d8d 100644 --- a/aws-runtime/aws-http/common/test/aws/sdk/kotlin/runtime/http/middleware/UserAgentTest.kt +++ b/aws-runtime/aws-http/common/test/aws/sdk/kotlin/runtime/http/middleware/UserAgentTest.kt @@ -27,8 +27,8 @@ class UserAgentTest { private fun initializeOp(platformProvider: PlatformProvider = TestPlatformProvider()) = SdkHttpOperation.build { - serializer = UnitSerializer - deserializer = IdentityDeserializer + serializeWith = HttpSerializer.Unit + deserializeWith = HttpDeserializer.Identity operationName = "testOperation" serviceName = "TestService" }.apply {