From de87cc5076349c89463a80a182f8de78c11e76c0 Mon Sep 17 00:00:00 2001 From: fossand Date: Wed, 29 Mar 2023 09:29:59 -0700 Subject: [PATCH] Update HttpRpcProtocolGenerator to allow request header code generation customization --- .../integration/HttpRpcProtocolGenerator.java | 100 +++++++++++++----- 1 file changed, 71 insertions(+), 29 deletions(-) diff --git a/smithy-typescript-codegen/src/main/java/software/amazon/smithy/typescript/codegen/integration/HttpRpcProtocolGenerator.java b/smithy-typescript-codegen/src/main/java/software/amazon/smithy/typescript/codegen/integration/HttpRpcProtocolGenerator.java index 865349a4e5d..733f87109ad 100644 --- a/smithy-typescript-codegen/src/main/java/software/amazon/smithy/typescript/codegen/integration/HttpRpcProtocolGenerator.java +++ b/smithy-typescript-codegen/src/main/java/software/amazon/smithy/typescript/codegen/integration/HttpRpcProtocolGenerator.java @@ -160,6 +160,10 @@ public void generateSharedComponents(GenerationContext context) { }); writer.write("return new $T(contents);", requestType); }); + + // Write common request header to be shared by all requests + writeSharedRequestHeaders(context); + writer.write(""); } @@ -247,17 +251,76 @@ private void generateOperationSerializer(GenerationContext context, OperationSha writer.write(""); } - private void writeRequestHeaders(GenerationContext context, OperationShape operation) { + /** + * Writes HTTP request headers required by the protocol implementation. + * + *

By default, headers are configured to use {@code SHARED_HEADERS}. See {@link #writeSharedRequestHeaders} + * + *

{@code
+     *   const headers: __HeaderBag = SHARED_HEADERS;
+     * }
+ * + *

This method can be overridden to customize headers generation. For example: + * + *

{@code
+     *   const headers: __HeaderBag = {
+     *     "foo": "This is a custom header",
+     *     ...SHARED_HEADERS
+     *   };
+     * }
+ * + * @param context The generation context. + * @param operation The operation being generated. + */ + protected void writeRequestHeaders(GenerationContext context, OperationShape operation) { TypeScriptWriter writer = context.getWriter(); + writer.addImport("HeaderBag", "__HeaderBag", "@aws-sdk/types"); + writer.openBlock("const headers: __HeaderBag = SHARED_HEADERS;"); + } - // The Content-Type header is always present. + + /** + * Writes headers to be shared for all HTTP requests by the protocol implementation. + * + *

To reduce generated code size, we should put all common headers into single location. + *

For example, most request headers contain {@code content-type}. + * + *

{@code
+     * const SHARED_HEADERS: __HeaderBag = {
+     *   "content-type": "application/x-www-form-urlencoded",
+     * };
+     * }
+ * + *

{@code SHARED_HEADERS} can then be used as follows: + * + *

{@code
+     * const headers: __HeaderBag = {
+     *   "foo": "This is a custom header",
+     *   ...SHARED_HEADERS
+     * };
+     * }
+ * + *

This method can be overridden for customization. For example: + * + *

{@code
+     * function sharedHeaders(operationName): __HeaderBag = {
+     *   "custom-header": "xyz-service:${operationName}",
+     * };
+     *
+     * const headers: __HeaderBag = {
+     *   "foo": "This is a custom header",
+     *   ...sharedHeaders(operationName)
+     * };
+     * }
+ * + * @param context The generation context. + */ + protected void writeSharedRequestHeaders(GenerationContext context) { + TypeScriptWriter writer = context.getWriter(); writer.addImport("HeaderBag", "__HeaderBag", "@aws-sdk/types"); - writer.openBlock("const headers: __HeaderBag = {", "};", - () -> { - writer.write("'content-type': $S,", getDocumentContentType()); - writeDefaultHeaders(context, operation); - } - ); + writer.openBlock("const SHARED_HEADERS: __HeaderBag = {", "};", () -> { + writer.write("'content-type': $S,", getDocumentContentType()); + }); } private boolean writeRequestBody(GenerationContext context, OperationShape operation) { @@ -296,27 +359,6 @@ private boolean writeRequestBody(GenerationContext context, OperationShape opera */ protected abstract String getOperationPath(GenerationContext context, OperationShape operation); - /** - * Writes any additional HTTP headers required by the protocol implementation. - * - *

Two parameters will be available in scope: - *

- * - *

For example: - * - *

{@code
-     *   "foo": "This is a custom header",
-     * }
- * - * @param context The generation context. - * @param operation The operation being generated. - */ - protected void writeDefaultHeaders(GenerationContext context, OperationShape operation) { - } - /** * Writes the code needed to serialize the input document of a request. *