in codegen/smithy-aws-kotlin-codegen/src/main/kotlin/aws/sdk/kotlin/codegen/customization/s3/S3Generator.kt [42:120]
override fun renderThrowOperationError(
ctx: ProtocolGenerator.GenerationContext,
op: OperationShape,
writer: KotlinWriter
) {
val exceptionBaseSymbol = ExceptionBaseClassGenerator.baseExceptionSymbol(ctx.settings)
val setS3ErrorMetadata = buildSymbol {
name = "setS3ErrorMetadata"
namespace = "${ctx.settings.pkg.name}.internal"
}
val parseS3ErrorResponse = buildSymbol {
name = "parseS3ErrorResponse"
namespace = "${ctx.settings.pkg.name}.internal"
}
val s3ErrorDetails = buildSymbol {
name = "S3ErrorDetails"
namespace = "${ctx.settings.pkg.name}.internal"
}
listOf(
exceptionBaseSymbol,
RuntimeTypes.Http.readAll,
RuntimeTypes.Http.StatusCode,
AwsRuntimeTypes.Http.withPayload,
s3ErrorDetails,
setS3ErrorMetadata,
parseS3ErrorResponse,
).forEach(writer::addImport)
writer.write("""val payload = response.body.readAll()""")
.write("val wrappedResponse = response.withPayload(payload)")
.write("")
.write("val errorDetails = try {")
.indent()
.call {
// customize error matching to handle HeadObject/HeadBucket error responses which have no payload
writer.write("if (payload == null && response.status == HttpStatusCode.NotFound) {")
.indent()
.write("""S3ErrorDetails(code = "NotFound")""")
.dedent()
.write("} else {")
.indent()
.write("""checkNotNull(payload){ "unable to parse error from empty response" }""")
.write("#T(payload)", parseS3ErrorResponse)
.dedent()
.write("}")
}
.dedent()
.withBlock("} catch (ex: Exception) {", "}") {
withBlock("""throw #T("Failed to parse response as '${ctx.protocol.name}' error", ex).also {""", "}", exceptionBaseSymbol) {
write("#T(it, wrappedResponse, null)", setS3ErrorMetadata)
}
}
.write("")
if (op.errors.isEmpty()) {
writer.write("throw #T(errorDetails.message)", exceptionBaseSymbol)
} else {
writer.openBlock("val modeledExceptionDeserializer = when(errorDetails.code) {", "}") {
op.errors.forEach { err ->
val errSymbol = ctx.symbolProvider.toSymbol(ctx.model.expectShape(err))
val errDeserializerSymbol = buildSymbol {
name = "${errSymbol.name}Deserializer"
namespace = "${ctx.settings.pkg.name}.transform"
}
writer.write("#S -> #T()", getErrorCode(ctx, err), errDeserializerSymbol)
}
writer.write("else -> throw #T(errorDetails.message)", exceptionBaseSymbol)
}
writer.write("")
.write("val modeledException = modeledExceptionDeserializer.deserialize(context, wrappedResponse)")
.write("#T(modeledException, wrappedResponse, errorDetails)", setS3ErrorMetadata)
.write("throw modeledException")
}
}