From f0aaeaeb0c310bfe48f0d15ba938d2eed8df8b84 Mon Sep 17 00:00:00 2001 From: JordonPhillips Date: Tue, 12 May 2020 17:19:59 -0700 Subject: [PATCH] Add application protocol client defaults --- .../smithy/go/codegen/CodegenVisitor.java | 4 +-- .../smithy/go/codegen/GoDependency.java | 1 + .../smithy/go/codegen/OperationGenerator.java | 24 +++++++++++--- .../smithy/go/codegen/ServiceGenerator.java | 31 +++++++++++++++++-- 4 files changed, 52 insertions(+), 8 deletions(-) diff --git a/codegen/smithy-go-codegen/src/main/java/software/amazon/smithy/go/codegen/CodegenVisitor.java b/codegen/smithy-go-codegen/src/main/java/software/amazon/smithy/go/codegen/CodegenVisitor.java index 0c4243099..589fc1162 100644 --- a/codegen/smithy-go-codegen/src/main/java/software/amazon/smithy/go/codegen/CodegenVisitor.java +++ b/codegen/smithy-go-codegen/src/main/java/software/amazon/smithy/go/codegen/CodegenVisitor.java @@ -217,7 +217,7 @@ public Void serviceShape(ServiceShape shape) { writers.useShapeWriter(shape, serviceWriter -> { new ServiceGenerator(settings, model, symbolProvider, serviceWriter, shape, integrations, - runtimePlugins).run(); + runtimePlugins, applicationProtocol).run(); // Generate each operation for the service. We do this here instead of via the operation visitor method to // limit it to the operations bound to the service. @@ -227,7 +227,7 @@ public Void serviceShape(ServiceShape shape) { Symbol operationSymbol = symbolProvider.toSymbol(operation); writers.useShapeWriter(operation, operationWriter -> new OperationGenerator( settings, model, symbolProvider, operationWriter, service, operation, - operationSymbol).run()); + operationSymbol, applicationProtocol).run()); } }); return null; diff --git a/codegen/smithy-go-codegen/src/main/java/software/amazon/smithy/go/codegen/GoDependency.java b/codegen/smithy-go-codegen/src/main/java/software/amazon/smithy/go/codegen/GoDependency.java index 1f58febf6..89ea1e174 100644 --- a/codegen/smithy-go-codegen/src/main/java/software/amazon/smithy/go/codegen/GoDependency.java +++ b/codegen/smithy-go-codegen/src/main/java/software/amazon/smithy/go/codegen/GoDependency.java @@ -31,6 +31,7 @@ public enum GoDependency implements SymbolDependencyContainer { TIME("stdlib", "", "time", null, "1.14"), FMT("stdlib", "", "fmt", null, "1.14"), CONTEXT("stdlib", "", "context", null, "1.14"), + HTTP("stdlib", "", "net/http", null, "1.14"), SMITHY("dependency", "github.com/awslabs/smithy-go", "github.com/awslabs/smithy-go", "smithy", "v0.0.1"), diff --git a/codegen/smithy-go-codegen/src/main/java/software/amazon/smithy/go/codegen/OperationGenerator.java b/codegen/smithy-go-codegen/src/main/java/software/amazon/smithy/go/codegen/OperationGenerator.java index 0145ea2f2..0cca503eb 100644 --- a/codegen/smithy-go-codegen/src/main/java/software/amazon/smithy/go/codegen/OperationGenerator.java +++ b/codegen/smithy-go-codegen/src/main/java/software/amazon/smithy/go/codegen/OperationGenerator.java @@ -36,6 +36,7 @@ final class OperationGenerator implements Runnable { private final ServiceShape service; private final OperationShape operation; private final Symbol operationSymbol; + private final ApplicationProtocol applicationProtocol; OperationGenerator( GoSettings settings, @@ -44,7 +45,8 @@ final class OperationGenerator implements Runnable { GoWriter writer, ServiceShape service, OperationShape operation, - Symbol operationSymbol + Symbol operationSymbol, + ApplicationProtocol applicationProtocol ) { this.settings = settings; this.model = model; @@ -53,6 +55,7 @@ final class OperationGenerator implements Runnable { this.service = service; this.operation = operation; this.operationSymbol = operationSymbol; + this.applicationProtocol = applicationProtocol; } @Override @@ -79,7 +82,8 @@ public void run() { Symbol contextSymbol = SymbolUtils.createValueSymbolBuilder("Context", GoDependency.CONTEXT).build(); writer.openBlock("func (c $P) $T(ctx $T, params $P, opts ...func(*Options)) ($P, error) {", "}", serviceSymbol, operationSymbol, contextSymbol, inputSymbol, outputSymbol, () -> { - // TODO: create middleware stack + constructStack(); + writer.write("options := c.options.Copy()"); writer.openBlock("for _, fn := range optFns {", "}", () -> { writer.write("fn(&options)"); @@ -87,8 +91,10 @@ public void run() { writer.openBlock("for _, fn := range options.APIOptions {", "}", () -> { writer.write("if err := fn(stack); err != nil { return nil, err }"); }); - // TODO: resolve middleware stack - writer.write("return nil, nil"); + + writer.write("result, err := handler.Handle(ctx, params)"); + writer.write("if err != nil { return nil, err }"); + writer.write("return result.($P), nil", outputSymbol); }).write(""); // Write out the input and output structures. These are written out here to prevent naming conflicts with other @@ -104,4 +110,14 @@ public void run() { writer.write("ResultMetadata $T", metadataSymbol); }); } + + private void constructStack() { + if (!applicationProtocol.isHttpProtocol()) { + throw new UnsupportedOperationException( + "Protocols other than HTTP are not yet implemented: " + applicationProtocol); + } + writer.addUseImports(GoDependency.SMITHY_MIDDLEWARE); + writer.addUseImports(GoDependency.SMITHY_HTTP_TRANSPORT); + writer.write("stack := middleware.NewStack($S, smithyhttp.NewStackRequest)", operationSymbol.getName()); + } } diff --git a/codegen/smithy-go-codegen/src/main/java/software/amazon/smithy/go/codegen/ServiceGenerator.java b/codegen/smithy-go-codegen/src/main/java/software/amazon/smithy/go/codegen/ServiceGenerator.java index 094db6f8f..0071a3c71 100644 --- a/codegen/smithy-go-codegen/src/main/java/software/amazon/smithy/go/codegen/ServiceGenerator.java +++ b/codegen/smithy-go-codegen/src/main/java/software/amazon/smithy/go/codegen/ServiceGenerator.java @@ -40,6 +40,7 @@ final class ServiceGenerator implements Runnable { private final ServiceShape service; private final List integrations; private final List runtimePlugins; + private final ApplicationProtocol applicationProtocol; ServiceGenerator( GoSettings settings, @@ -48,7 +49,8 @@ final class ServiceGenerator implements Runnable { GoWriter writer, ServiceShape service, List integrations, - List runtimePlugins + List runtimePlugins, + ApplicationProtocol applicationProtocol ) { this.settings = settings; this.model = model; @@ -57,6 +59,7 @@ final class ServiceGenerator implements Runnable { this.service = service; this.integrations = integrations; this.runtimePlugins = runtimePlugins; + this.applicationProtocol = applicationProtocol; } @Override @@ -127,9 +130,11 @@ private void generateConfig() { integration.addConfigFields(settings, model, symbolProvider, writer); } - // TODO: add application protocol defaults + generateApplicationProtocolConfig(); }).write(""); + generateApplicationProtocolTypes(); + writer.writeDocs("Copy creates a clone where the APIOptions list is deep copied."); writer.openBlock("func (o $L) Copy() $L {", "}", CONFIG_NAME, CONFIG_NAME, () -> { writer.write("to := o"); @@ -138,4 +143,26 @@ private void generateConfig() { writer.write("return to"); }); } + + private void generateApplicationProtocolConfig() { + ensureSupportedProtocol(); + writer.writeDocs( + "The HTTP client to invoke API calls with. Defaults to client's default HTTP implementation if nil."); + writer.write("HTTPClient HTTPClient").write(""); + } + + private void generateApplicationProtocolTypes() { + ensureSupportedProtocol(); + writer.openBlock("type HTTPClient interface {", "}", () -> { + writer.write("Do($P) ($P, error)", applicationProtocol.getRequestType(), + applicationProtocol.getResponseType()); + }).write(""); + } + + private void ensureSupportedProtocol() { + if (!applicationProtocol.isHttpProtocol()) { + throw new UnsupportedOperationException( + "Protocols other than HTTP are not yet implemented: " + applicationProtocol); + } + } }