Skip to content

Commit dfb3c94

Browse files
committed
fix: populate parseBody() for errors or command responses
When preparing reponse body for command deserializers or error deserializers, we don't always collect response body binaries in structured JS object. If the command ouput or error has a streaming trait, we need to keep the response body intact and return users the raw response stream.
1 parent 557293f commit dfb3c94

File tree

1 file changed

+16
-4
lines changed

1 file changed

+16
-4
lines changed

smithy-typescript-codegen/src/main/java/software/amazon/smithy/typescript/codegen/integration/HttpBindingProtocolGenerator.java

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -19,16 +19,19 @@
1919

2020
import java.util.Comparator;
2121
import java.util.List;
22+
import java.util.Optional;
2223
import java.util.Set;
2324
import java.util.TreeMap;
2425
import java.util.TreeSet;
2526
import java.util.logging.Logger;
27+
2628
import software.amazon.smithy.codegen.core.CodegenException;
2729
import software.amazon.smithy.codegen.core.Symbol;
2830
import software.amazon.smithy.codegen.core.SymbolProvider;
2931
import software.amazon.smithy.codegen.core.SymbolReference;
3032
import software.amazon.smithy.model.knowledge.HttpBinding;
3133
import software.amazon.smithy.model.knowledge.HttpBindingIndex;
34+
import software.amazon.smithy.model.knowledge.OperationIndex;
3235
import software.amazon.smithy.model.knowledge.TopDownIndex;
3336
import software.amazon.smithy.model.shapes.BlobShape;
3437
import software.amazon.smithy.model.shapes.BooleanShape;
@@ -662,11 +665,20 @@ private List<HttpBinding> readResponseBody(
662665
documentBindings.sort(Comparator.comparing(HttpBinding::getMemberName));
663666
List<HttpBinding> payloadBindings = bindingIndex.getResponseBindings(operationOrError, Location.PAYLOAD);
664667

665-
if (operationOrError.isOperationShape() && !payloadBindings.get(0).getMember().hasTrait(StreamingTrait.class)) {
666-
writer.write("const data: any = await parseBody(output.body, context)");
667-
} else {
668-
// Don't collect stream for errors and streaming payload
668+
// Prepare response body for deserializing.
669+
OperationIndex operationIndex = context.getModel().getKnowledge(OperationIndex.class);
670+
StructureShape operationOutputOrError = operationOrError.asStructureShape()
671+
.orElseGet(() -> operationIndex.getOutput(operationOrError).orElse(null));
672+
boolean hasStreamingComponent = Optional.ofNullable(operationOutputOrError)
673+
.map(structure -> structure.getAllMembers().values().stream()
674+
.anyMatch(memberShape -> memberShape.hasTrait(StreamingTrait.class)))
675+
.orElse(false);
676+
if (hasStreamingComponent) {
677+
// For operations with streaming output or errors with streaming body we keep the body intact.
669678
writer.write("const data: any = output.body;");
679+
} else {
680+
// Otherwise, we collect the response body to structured object with parseBody().
681+
writer.write("const data: any = await parseBody(output.body, context);");
670682
}
671683

672684
if (!documentBindings.isEmpty()) {

0 commit comments

Comments
 (0)