Skip to content

Commit 72d6843

Browse files
authored
fix: delegate when to set content-type to binding resolver; fix content-length for empty bodies (#525)
1 parent 12c6f78 commit 72d6843

File tree

6 files changed

+19
-36
lines changed

6 files changed

+19
-36
lines changed

gradle.properties

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ ktorVersion=1.6.3
2424
atomicFuVersion=0.16.1
2525

2626
# codegen
27-
smithyVersion=1.13.0
27+
smithyVersion=1.13.1
2828
smithyGradleVersion=0.5.3
2929

3030
# testing/utility

runtime/smithy-test/common/src/aws/smithy/kotlin/runtime/smithy/test/HttpRequestTest.kt

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -59,11 +59,12 @@ fun httpRequestTest(block: HttpRequestTestBuilder.() -> Unit) = runSuspendTest {
5959
}
6060

6161
// capture the request that was built by the service operation
62-
if (request.body.contentLength != null) {
62+
val contentLength = request.body.contentLength
63+
if (contentLength != null && contentLength > 0) {
6364
// Content-Length header is not expected to be set by serialize implementations. It is expected
6465
// to be read from [HttpBody::contentLength] by the underlying engine and set appropriately
6566
// add it in here so tests that define it can pass
66-
testHeaders["Content-Length"] = request.body.contentLength.toString()
67+
testHeaders["Content-Length"] = contentLength.toString()
6768
}
6869

6970
actual = request.copy(headers = testHeaders.build())

smithy-kotlin-codegen/src/main/kotlin/software/amazon/smithy/kotlin/codegen/rendering/protocol/HttpBindingProtocolGenerator.kt

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -415,8 +415,7 @@ abstract class HttpBindingProtocolGenerator : ProtocolGenerator {
415415
.write("builder.body = #T(payload)", RuntimeTypes.Http.ByteArrayContent)
416416
}
417417

418-
writer.openBlock("if (builder.body !is #T.Empty) {", "}", RuntimeTypes.Http.HttpBody) {
419-
val contentType = resolver.determineRequestContentType(op)
418+
resolver.determineRequestContentType(op)?.let { contentType ->
420419
writer.write("builder.headers.setMissing(\"Content-Type\", #S)", contentType)
421420
}
422421
}

smithy-kotlin-codegen/src/main/kotlin/software/amazon/smithy/kotlin/codegen/rendering/protocol/HttpBindingResolver.kt

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ package software.amazon.smithy.kotlin.codegen.rendering.protocol
77

88
import software.amazon.smithy.kotlin.codegen.model.expectTrait
99
import software.amazon.smithy.kotlin.codegen.model.hasTrait
10+
import software.amazon.smithy.kotlin.codegen.utils.getOrNull
1011
import software.amazon.smithy.model.Model
1112
import software.amazon.smithy.model.knowledge.HttpBinding
1213
import software.amazon.smithy.model.knowledge.HttpBindingIndex
@@ -68,9 +69,9 @@ interface HttpBindingResolver {
6869
* Determine the request content type for the protocol.
6970
*
7071
* @param operationShape [OperationShape] associated with content type
71-
* @return content type
72+
* @return content type or null if no content-type header should be set
7273
*/
73-
fun determineRequestContentType(operationShape: OperationShape): String
74+
fun determineRequestContentType(operationShape: OperationShape): String?
7475

7576
/**
7677
* Determine the timestamp format depending on input parameter values.
@@ -140,9 +141,9 @@ class HttpTraitResolver(
140141
else -> error { "Unimplemented resolving bindings for ${shape.javaClass.canonicalName}" }
141142
}
142143

143-
override fun determineRequestContentType(operationShape: OperationShape): String = bindingIndex
144+
override fun determineRequestContentType(operationShape: OperationShape): String? = bindingIndex
144145
.determineRequestContentType(operationShape, defaultContentType)
145-
.orElse(defaultContentType)
146+
.getOrNull()
146147

147148
override fun determineTimestampFormat(
148149
member: ToShapeId,

smithy-kotlin-codegen/src/test/kotlin/software/amazon/smithy/kotlin/codegen/IdempotentTokenGeneratorTest.kt

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -43,9 +43,7 @@ class IdempotentTokenGeneratorTest {
4343
4444
val payload = serializeAllocateWidgetOperationBody(context, input)
4545
builder.body = ByteArrayContent(payload)
46-
if (builder.body !is HttpBody.Empty) {
47-
builder.headers.setMissing("Content-Type", "application/json")
48-
}
46+
builder.headers.setMissing("Content-Type", "application/json")
4947
return builder
5048
}
5149
}

smithy-kotlin-codegen/src/test/kotlin/software/amazon/smithy/kotlin/codegen/rendering/protocol/HttpBindingProtocolGeneratorTest.kt

Lines changed: 8 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -86,9 +86,7 @@ internal class SmokeTestOperationSerializer: HttpSerialize<SmokeTestRequest> {
8686
8787
val payload = serializeSmokeTestOperationBody(context, input)
8888
builder.body = ByteArrayContent(payload)
89-
if (builder.body !is HttpBody.Empty) {
90-
builder.headers.setMissing("Content-Type", "application/json")
91-
}
89+
builder.headers.setMissing("Content-Type", "application/json")
9290
return builder
9391
}
9492
}
@@ -115,9 +113,7 @@ internal class ExplicitStringOperationSerializer: HttpSerialize<ExplicitStringRe
115113
if (input.payload1 != null) {
116114
builder.body = ByteArrayContent(input.payload1.toByteArray())
117115
}
118-
if (builder.body !is HttpBody.Empty) {
119-
builder.headers.setMissing("Content-Type", "text/plain")
120-
}
116+
builder.headers.setMissing("Content-Type", "text/plain")
121117
return builder
122118
}
123119
}
@@ -142,9 +138,7 @@ internal class ExplicitBlobOperationSerializer: HttpSerialize<ExplicitBlobReques
142138
if (input.payload1 != null) {
143139
builder.body = ByteArrayContent(input.payload1)
144140
}
145-
if (builder.body !is HttpBody.Empty) {
146-
builder.headers.setMissing("Content-Type", "application/octet-stream")
147-
}
141+
builder.headers.setMissing("Content-Type", "application/octet-stream")
148142
return builder
149143
}
150144
}
@@ -169,9 +163,7 @@ internal class ExplicitBlobStreamOperationSerializer: HttpSerialize<ExplicitBlob
169163
if (input.payload1 != null) {
170164
builder.body = input.payload1.toHttpBody() ?: HttpBody.Empty
171165
}
172-
if (builder.body !is HttpBody.Empty) {
173-
builder.headers.setMissing("Content-Type", "application/octet-stream")
174-
}
166+
builder.headers.setMissing("Content-Type", "application/octet-stream")
175167
return builder
176168
}
177169
}
@@ -197,9 +189,7 @@ internal class ExplicitStructOperationSerializer: HttpSerialize<ExplicitStructRe
197189
val payload = serializeExplicitStructOperationBody(context, input)
198190
builder.body = ByteArrayContent(payload)
199191
}
200-
if (builder.body !is HttpBody.Empty) {
201-
builder.headers.setMissing("Content-Type", "application/json")
202-
}
192+
builder.headers.setMissing("Content-Type", "application/json")
203193
return builder
204194
}
205195
}
@@ -238,9 +228,7 @@ internal class EnumInputOperationSerializer: HttpSerialize<EnumInputRequest> {
238228
239229
val payload = serializeEnumInputOperationBody(context, input)
240230
builder.body = ByteArrayContent(payload)
241-
if (builder.body !is HttpBody.Empty) {
242-
builder.headers.setMissing("Content-Type", "application/json")
243-
}
231+
builder.headers.setMissing("Content-Type", "application/json")
244232
return builder
245233
}
246234
}
@@ -280,9 +268,7 @@ internal class TimestampInputOperationSerializer: HttpSerialize<TimestampInputRe
280268
281269
val payload = serializeTimestampInputOperationBody(context, input)
282270
builder.body = ByteArrayContent(payload)
283-
if (builder.body !is HttpBody.Empty) {
284-
builder.headers.setMissing("Content-Type", "application/json")
285-
}
271+
builder.headers.setMissing("Content-Type", "application/json")
286272
return builder
287273
}
288274
}
@@ -313,9 +299,7 @@ internal class BlobInputOperationSerializer: HttpSerialize<BlobInputRequest> {
313299
314300
val payload = serializeBlobInputOperationBody(context, input)
315301
builder.body = ByteArrayContent(payload)
316-
if (builder.body !is HttpBody.Empty) {
317-
builder.headers.setMissing("Content-Type", "application/json")
318-
}
302+
builder.headers.setMissing("Content-Type", "application/json")
319303
return builder
320304
}
321305
}

0 commit comments

Comments
 (0)