in codegen/smithy-go-codegen/src/main/java/software/amazon/smithy/go/codegen/integration/HttpRpcProtocolGenerator.java [321:393]
private void generateOperationDeserializer(GenerationContext context, OperationShape operation) {
SymbolProvider symbolProvider = context.getSymbolProvider();
Model model = context.getModel();
GoWriter writer = context.getWriter().get();
ServiceShape service = context.getService();
StructureShape outputShape = ProtocolUtils.expectOutput(context.getModel(), operation);
Symbol outputSymbol = symbolProvider.toSymbol(outputShape);
ApplicationProtocol applicationProtocol = getApplicationProtocol();
Symbol responseType = applicationProtocol.getResponseType();
String errorFunctionName = ProtocolGenerator.getOperationErrorDeserFunctionName(
operation, context.getService(), context.getProtocolName());
GoStackStepMiddlewareGenerator middleware = GoStackStepMiddlewareGenerator.createDeserializeStepMiddleware(
ProtocolGenerator.getDeserializeMiddlewareName(operation.getId(), service, getProtocolName()),
ProtocolUtils.OPERATION_DESERIALIZER_MIDDLEWARE_ID);
middleware.writeMiddleware(writer, (generator, w) -> {
writer.addUseImports(SmithyGoDependency.FMT);
writer.addUseImports(SmithyGoDependency.SMITHY);
writer.write("out, metadata, err = next.$L(ctx, in)", generator.getHandleMethodName());
writer.write("if err != nil { return out, metadata, err }");
writer.write("");
writer.write(goTemplate("""
_, span := $T(ctx, "OperationDeserializer")
endTimer := startMetricTimer(ctx, "client.call.deserialization_duration")
defer endTimer()
defer span.End()
""", SMITHY_TRACING.func("StartSpan")));
writer.write("response, ok := out.RawResponse.($P)", responseType);
writer.openBlock("if !ok {", "}", () -> {
writer.write(String.format("return out, metadata, &smithy.DeserializationError{Err: %s}",
"fmt.Errorf(\"unknown transport type %T\", out.RawResponse)"));
});
writer.write("");
writer.openBlock("if response.StatusCode < 200 || response.StatusCode >= 300 {", "}", () -> {
writer.write("return out, metadata, $L(response, &metadata)", errorFunctionName);
});
writer.write("output := &$T{}", outputSymbol);
writer.write("out.Result = output");
writer.write("");
Optional<EventStreamInfo> streamInfoOptional = EventStreamIndex.of(model).getOutputInfo(operation);
// Discard without deserializing the response if the input shape is a stubbed synthetic clone
// without an archetype.
if (CodegenUtils.isStubSynthetic(ProtocolUtils.expectOutput(model, operation))
&& streamInfoOptional.isEmpty()) {
writer.addUseImports(SmithyGoDependency.IOUTIL);
writer.openBlock("if _, err = io.Copy(ioutil.Discard, response.Body); err != nil {", "}",
() -> {
writer.openBlock("return out, metadata, &smithy.DeserializationError{", "}", () -> {
writer.write("Err: fmt.Errorf(\"failed to discard response body, %w\", err),");
});
});
} else if (streamInfoOptional.isEmpty()) {
deserializeOutputDocument(context, operation);
deserializingDocumentShapes.add(ProtocolUtils.expectOutput(model, operation));
}
writer.write("");
writer.write("return out, metadata, err");
});
writer.write("");
Set<StructureShape> errorShapes = generateErrorShapes(context, operation, responseType);
deserializingErrorShapes.addAll(errorShapes);
deserializingDocumentShapes.addAll(errorShapes);
}