Skip to content

Commit 83b7885

Browse files
authored
misc: Add HttpResponseBuilder and use message from DeprecatedTrait if set (#1071)
1 parent 516da06 commit 83b7885

File tree

4 files changed

+95
-1
lines changed

4 files changed

+95
-1
lines changed

codegen/smithy-kotlin-codegen/src/main/kotlin/software/amazon/smithy/kotlin/codegen/core/KotlinWriter.kt

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ import software.amazon.smithy.kotlin.codegen.utils.getOrNull
1717
import software.amazon.smithy.model.Model
1818
import software.amazon.smithy.model.shapes.MemberShape
1919
import software.amazon.smithy.model.shapes.Shape
20+
import software.amazon.smithy.model.traits.DeprecatedTrait
2021
import software.amazon.smithy.model.traits.DocumentationTrait
2122
import software.amazon.smithy.model.traits.EnumDefinition
2223
import software.amazon.smithy.utils.AbstractCodeWriter
@@ -219,7 +220,9 @@ class KotlinWriter(
219220
*/
220221
private fun renderDeprecatedAnnotation(shape: Shape) {
221222
if (shape.isDeprecated) {
222-
write("""@Deprecated("No longer recommended for use. See AWS API documentation for more details.")""")
223+
val message = shape.expectTrait<DeprecatedTrait>().message?.getOrNull()
224+
?: "No longer recommended for use. See AWS API documentation for more details."
225+
write("""@Deprecated(#S)""", message)
223226
}
224227
}
225228

runtime/protocol/http/api/http.api

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -316,6 +316,24 @@ public abstract interface class aws/smithy/kotlin/runtime/http/response/HttpResp
316316
public abstract fun getStatus ()Laws/smithy/kotlin/runtime/http/HttpStatusCode;
317317
}
318318

319+
public final class aws/smithy/kotlin/runtime/http/response/HttpResponseBuilder : aws/smithy/kotlin/runtime/util/CanDeepCopy {
320+
public fun <init> ()V
321+
public final fun build ()Laws/smithy/kotlin/runtime/http/response/HttpResponse;
322+
public fun deepCopy ()Laws/smithy/kotlin/runtime/http/response/HttpResponseBuilder;
323+
public synthetic fun deepCopy ()Ljava/lang/Object;
324+
public final fun getBody ()Laws/smithy/kotlin/runtime/http/HttpBody;
325+
public final fun getHeaders ()Laws/smithy/kotlin/runtime/http/HeadersBuilder;
326+
public final fun getStatus ()Laws/smithy/kotlin/runtime/http/HttpStatusCode;
327+
public final fun setBody (Laws/smithy/kotlin/runtime/http/HttpBody;)V
328+
public final fun setStatus (Laws/smithy/kotlin/runtime/http/HttpStatusCode;)V
329+
public fun toString ()Ljava/lang/String;
330+
}
331+
332+
public final class aws/smithy/kotlin/runtime/http/response/HttpResponseBuilderKt {
333+
public static final fun immutableView (Laws/smithy/kotlin/runtime/http/response/HttpResponseBuilder;Z)Laws/smithy/kotlin/runtime/http/response/HttpResponse;
334+
public static synthetic fun immutableView$default (Laws/smithy/kotlin/runtime/http/response/HttpResponseBuilder;ZILjava/lang/Object;)Laws/smithy/kotlin/runtime/http/response/HttpResponse;
335+
}
336+
319337
public final class aws/smithy/kotlin/runtime/http/response/HttpResponseKt {
320338
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;
321339
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;
@@ -325,6 +343,7 @@ public final class aws/smithy/kotlin/runtime/http/response/HttpResponseKt {
325343
public static final fun getAllHeaders (Laws/smithy/kotlin/runtime/ProtocolResponse;Ljava/lang/String;)Ljava/util/List;
326344
public static final fun header (Laws/smithy/kotlin/runtime/ProtocolResponse;Ljava/lang/String;)Ljava/lang/String;
327345
public static final fun statusCode (Laws/smithy/kotlin/runtime/ProtocolResponse;)Laws/smithy/kotlin/runtime/http/HttpStatusCode;
346+
public static final fun toBuilder (Laws/smithy/kotlin/runtime/http/response/HttpResponse;)Laws/smithy/kotlin/runtime/http/response/HttpResponseBuilder;
328347
}
329348

330349
public final class aws/smithy/kotlin/runtime/http/util/HeaderListsKt {

runtime/protocol/http/common/src/aws/smithy/kotlin/runtime/http/response/HttpResponse.kt

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -119,3 +119,21 @@ public suspend fun dumpResponse(response: HttpResponse, dumpBody: Boolean): Pair
119119

120120
return respCopy to buffer.readUtf8()
121121
}
122+
123+
/**
124+
* Convert an HttpResponse to an [HttpResponseBuilder]
125+
*/
126+
public fun HttpResponse.toBuilder(): HttpResponseBuilder = when (this) {
127+
is HttpResponseBuilderView -> {
128+
check(allowToBuilder) { "This is an immutable HttpResponse that should not be converted to a builder" }
129+
builder
130+
}
131+
else -> {
132+
val resp = this
133+
HttpResponseBuilder().apply {
134+
status = resp.status
135+
headers.appendAll(resp.headers)
136+
body = resp.body
137+
}
138+
}
139+
}
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
/*
2+
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
3+
* SPDX-License-Identifier: Apache-2.0
4+
*/
5+
package aws.smithy.kotlin.runtime.http.response
6+
7+
import aws.smithy.kotlin.runtime.InternalApi
8+
import aws.smithy.kotlin.runtime.http.*
9+
import aws.smithy.kotlin.runtime.util.CanDeepCopy
10+
11+
/**
12+
* Used to construct an HTTP response
13+
* @param status The HTTP status of the response
14+
* @param headers Response HTTP headers
15+
* @param body Response payload
16+
*/
17+
@InternalApi
18+
public class HttpResponseBuilder private constructor(
19+
public var status: HttpStatusCode,
20+
public val headers: HeadersBuilder,
21+
public var body: HttpBody,
22+
) : CanDeepCopy<HttpResponseBuilder> {
23+
public constructor() : this(HttpStatusCode.OK, HeadersBuilder(), HttpBody.Empty)
24+
25+
public fun build(): HttpResponse = HttpResponse(status, if (headers.isEmpty()) Headers.Empty else headers.build(), body)
26+
27+
override fun deepCopy(): HttpResponseBuilder = HttpResponseBuilder(status, headers.deepCopy(), body)
28+
29+
override fun toString(): String = "HttpResponseBuilder(status=$status, headers=$headers, body=$body)"
30+
}
31+
32+
internal data class HttpResponseBuilderView(
33+
internal val builder: HttpResponseBuilder,
34+
internal val allowToBuilder: Boolean,
35+
) : HttpResponse {
36+
override val status: HttpStatusCode = builder.status
37+
override val headers: Headers by lazy { builder.headers.build() }
38+
override val body: HttpBody = builder.body
39+
override val summary: String = "HTTP ${status.value} ${status.description}"
40+
}
41+
42+
/**
43+
* Create a read-only view of a builder. Often, we need a read-only view of a builder that _may_ get modified.
44+
* This would normally require a round trip invoking [HttpResponseBuilder.build] and then converting that back
45+
* to a builder using [HttpResponse.toBuilder]. Instead, we can create an immutable view of a builder that
46+
* is cheap to convert to a builder.
47+
*
48+
* @param allowToBuilder flag controlling how this type will behave when [HttpResponse.toBuilder] is invoked. When
49+
* false an exception will be thrown, otherwise it will succeed.
50+
*/
51+
@InternalApi
52+
public fun HttpResponseBuilder.immutableView(
53+
allowToBuilder: Boolean = false,
54+
): HttpResponse = HttpResponseBuilderView(this, allowToBuilder)

0 commit comments

Comments
 (0)