Skip to content

Commit

Permalink
misc: Add HttpResponseBuilder and use message from `DeprecatedTrait…
Browse files Browse the repository at this point in the history
…` if set (#1071)
  • Loading branch information
lauzadis authored Apr 19, 2024
1 parent 516da06 commit 83b7885
Show file tree
Hide file tree
Showing 4 changed files with 95 additions and 1 deletion.
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import software.amazon.smithy.kotlin.codegen.utils.getOrNull
import software.amazon.smithy.model.Model
import software.amazon.smithy.model.shapes.MemberShape
import software.amazon.smithy.model.shapes.Shape
import software.amazon.smithy.model.traits.DeprecatedTrait
import software.amazon.smithy.model.traits.DocumentationTrait
import software.amazon.smithy.model.traits.EnumDefinition
import software.amazon.smithy.utils.AbstractCodeWriter
Expand Down Expand Up @@ -219,7 +220,9 @@ class KotlinWriter(
*/
private fun renderDeprecatedAnnotation(shape: Shape) {
if (shape.isDeprecated) {
write("""@Deprecated("No longer recommended for use. See AWS API documentation for more details.")""")
val message = shape.expectTrait<DeprecatedTrait>().message?.getOrNull()
?: "No longer recommended for use. See AWS API documentation for more details."
write("""@Deprecated(#S)""", message)
}
}

Expand Down
19 changes: 19 additions & 0 deletions runtime/protocol/http/api/http.api
Original file line number Diff line number Diff line change
Expand Up @@ -316,6 +316,24 @@ public abstract interface class aws/smithy/kotlin/runtime/http/response/HttpResp
public abstract fun getStatus ()Laws/smithy/kotlin/runtime/http/HttpStatusCode;
}

public final class aws/smithy/kotlin/runtime/http/response/HttpResponseBuilder : aws/smithy/kotlin/runtime/util/CanDeepCopy {
public fun <init> ()V
public final fun build ()Laws/smithy/kotlin/runtime/http/response/HttpResponse;
public fun deepCopy ()Laws/smithy/kotlin/runtime/http/response/HttpResponseBuilder;
public synthetic fun deepCopy ()Ljava/lang/Object;
public final fun getBody ()Laws/smithy/kotlin/runtime/http/HttpBody;
public final fun getHeaders ()Laws/smithy/kotlin/runtime/http/HeadersBuilder;
public final fun getStatus ()Laws/smithy/kotlin/runtime/http/HttpStatusCode;
public final fun setBody (Laws/smithy/kotlin/runtime/http/HttpBody;)V
public final fun setStatus (Laws/smithy/kotlin/runtime/http/HttpStatusCode;)V
public fun toString ()Ljava/lang/String;
}

public final class aws/smithy/kotlin/runtime/http/response/HttpResponseBuilderKt {
public static final fun immutableView (Laws/smithy/kotlin/runtime/http/response/HttpResponseBuilder;Z)Laws/smithy/kotlin/runtime/http/response/HttpResponse;
public static synthetic fun immutableView$default (Laws/smithy/kotlin/runtime/http/response/HttpResponseBuilder;ZILjava/lang/Object;)Laws/smithy/kotlin/runtime/http/response/HttpResponse;
}

public final class aws/smithy/kotlin/runtime/http/response/HttpResponseKt {
public static final fun HttpResponse (Laws/smithy/kotlin/runtime/http/HttpStatusCode;Laws/smithy/kotlin/runtime/http/Headers;Laws/smithy/kotlin/runtime/http/HttpBody;)Laws/smithy/kotlin/runtime/http/response/HttpResponse;
public static synthetic fun HttpResponse$default (Laws/smithy/kotlin/runtime/http/HttpStatusCode;Laws/smithy/kotlin/runtime/http/Headers;Laws/smithy/kotlin/runtime/http/HttpBody;ILjava/lang/Object;)Laws/smithy/kotlin/runtime/http/response/HttpResponse;
Expand All @@ -325,6 +343,7 @@ public final class aws/smithy/kotlin/runtime/http/response/HttpResponseKt {
public static final fun getAllHeaders (Laws/smithy/kotlin/runtime/ProtocolResponse;Ljava/lang/String;)Ljava/util/List;
public static final fun header (Laws/smithy/kotlin/runtime/ProtocolResponse;Ljava/lang/String;)Ljava/lang/String;
public static final fun statusCode (Laws/smithy/kotlin/runtime/ProtocolResponse;)Laws/smithy/kotlin/runtime/http/HttpStatusCode;
public static final fun toBuilder (Laws/smithy/kotlin/runtime/http/response/HttpResponse;)Laws/smithy/kotlin/runtime/http/response/HttpResponseBuilder;
}

public final class aws/smithy/kotlin/runtime/http/util/HeaderListsKt {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -119,3 +119,21 @@ public suspend fun dumpResponse(response: HttpResponse, dumpBody: Boolean): Pair

return respCopy to buffer.readUtf8()
}

/**
* Convert an HttpResponse to an [HttpResponseBuilder]
*/
public fun HttpResponse.toBuilder(): HttpResponseBuilder = when (this) {
is HttpResponseBuilderView -> {
check(allowToBuilder) { "This is an immutable HttpResponse that should not be converted to a builder" }
builder
}
else -> {
val resp = this
HttpResponseBuilder().apply {
status = resp.status
headers.appendAll(resp.headers)
body = resp.body
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
/*
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
* SPDX-License-Identifier: Apache-2.0
*/
package aws.smithy.kotlin.runtime.http.response

import aws.smithy.kotlin.runtime.InternalApi
import aws.smithy.kotlin.runtime.http.*
import aws.smithy.kotlin.runtime.util.CanDeepCopy

/**
* Used to construct an HTTP response
* @param status The HTTP status of the response
* @param headers Response HTTP headers
* @param body Response payload
*/
@InternalApi
public class HttpResponseBuilder private constructor(
public var status: HttpStatusCode,
public val headers: HeadersBuilder,
public var body: HttpBody,
) : CanDeepCopy<HttpResponseBuilder> {
public constructor() : this(HttpStatusCode.OK, HeadersBuilder(), HttpBody.Empty)

public fun build(): HttpResponse = HttpResponse(status, if (headers.isEmpty()) Headers.Empty else headers.build(), body)

override fun deepCopy(): HttpResponseBuilder = HttpResponseBuilder(status, headers.deepCopy(), body)

override fun toString(): String = "HttpResponseBuilder(status=$status, headers=$headers, body=$body)"
}

internal data class HttpResponseBuilderView(
internal val builder: HttpResponseBuilder,
internal val allowToBuilder: Boolean,
) : HttpResponse {
override val status: HttpStatusCode = builder.status
override val headers: Headers by lazy { builder.headers.build() }
override val body: HttpBody = builder.body
override val summary: String = "HTTP ${status.value} ${status.description}"
}

/**
* Create a read-only view of a builder. Often, we need a read-only view of a builder that _may_ get modified.
* This would normally require a round trip invoking [HttpResponseBuilder.build] and then converting that back
* to a builder using [HttpResponse.toBuilder]. Instead, we can create an immutable view of a builder that
* is cheap to convert to a builder.
*
* @param allowToBuilder flag controlling how this type will behave when [HttpResponse.toBuilder] is invoked. When
* false an exception will be thrown, otherwise it will succeed.
*/
@InternalApi
public fun HttpResponseBuilder.immutableView(
allowToBuilder: Boolean = false,
): HttpResponse = HttpResponseBuilderView(this, allowToBuilder)

0 comments on commit 83b7885

Please sign in to comment.