Skip to content

Commit bfc9257

Browse files
authored
feat(codegen): http checksum dependency integration (#3346)
1 parent 42d433b commit bfc9257

File tree

3 files changed

+195
-2
lines changed

3 files changed

+195
-2
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,190 @@
1+
/*
2+
* Copyright 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License").
5+
* You may not use this file except in compliance with the License.
6+
* A copy of the License is located at
7+
*
8+
* http://aws.amazon.com/apache2.0
9+
*
10+
* or in the "license" file accompanying this file. This file is distributed
11+
* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
12+
* express or implied. See the License for the specific language governing
13+
* permissions and limitations under the License.
14+
*/
15+
16+
package software.amazon.smithy.aws.typescript.codegen;
17+
18+
import static software.amazon.smithy.typescript.codegen.integration.RuntimeClientPlugin.Convention.HAS_MIDDLEWARE;
19+
20+
import java.util.Collections;
21+
import java.util.List;
22+
import java.util.Map;
23+
import java.util.Set;
24+
import java.util.TreeMap;
25+
import java.util.function.Consumer;
26+
import software.amazon.smithy.aws.traits.HttpChecksumTrait;
27+
import software.amazon.smithy.codegen.core.Symbol;
28+
import software.amazon.smithy.codegen.core.SymbolProvider;
29+
import software.amazon.smithy.model.Model;
30+
import software.amazon.smithy.model.knowledge.TopDownIndex;
31+
import software.amazon.smithy.model.shapes.OperationShape;
32+
import software.amazon.smithy.model.shapes.ServiceShape;
33+
import software.amazon.smithy.typescript.codegen.LanguageTarget;
34+
import software.amazon.smithy.typescript.codegen.TypeScriptDependency;
35+
import software.amazon.smithy.typescript.codegen.TypeScriptSettings;
36+
import software.amazon.smithy.typescript.codegen.TypeScriptWriter;
37+
import software.amazon.smithy.typescript.codegen.integration.RuntimeClientPlugin;
38+
import software.amazon.smithy.typescript.codegen.integration.TypeScriptIntegration;
39+
import software.amazon.smithy.utils.ListUtils;
40+
import software.amazon.smithy.utils.MapUtils;
41+
import software.amazon.smithy.utils.SmithyInternalApi;
42+
43+
/**
44+
* Adds checksum dependencies if needed.
45+
*/
46+
@SmithyInternalApi
47+
public class AddHttpChecksumDependency implements TypeScriptIntegration {
48+
49+
@Override
50+
public void addConfigInterfaceFields(
51+
TypeScriptSettings settings,
52+
Model model,
53+
SymbolProvider symbolProvider,
54+
TypeScriptWriter writer
55+
) {
56+
if (!hasHttpChecksumTrait(model, settings.getService(model))) {
57+
return;
58+
}
59+
60+
writer.addImport("Readable", "Readable", "stream");
61+
writer.addImport("StreamHasher", "__StreamHasher", "@aws-sdk/types");
62+
writer.writeDocs("A function that, given a hash constructor and a stream, calculates the \n"
63+
+ "hash of the streamed value.\n"
64+
+ "@internal");
65+
writer.write("streamHasher?: __StreamHasher<Readable> | __StreamHasher<Blob>;\n");
66+
67+
writer.addImport("Hash", "__Hash", "@aws-sdk/types");
68+
writer.addImport("HashConstructor", "__HashConstructor", "@aws-sdk/types");
69+
70+
writer.writeDocs("A constructor for a class implementing the {@link __Hash} interface \n"
71+
+ "that computes MD5 hashes.\n"
72+
+ "@internal");
73+
writer.write("md5?: __HashConstructor;\n");
74+
75+
writer.writeDocs("A constructor for a class implementing the {@link __Hash} interface \n"
76+
+ "that computes SHA1 hashes.\n"
77+
+ "@internal");
78+
writer.write("sha1?: __HashConstructor;\n");
79+
}
80+
81+
@Override
82+
public Map<String, Consumer<TypeScriptWriter>> getRuntimeConfigWriters(
83+
TypeScriptSettings settings,
84+
Model model,
85+
SymbolProvider symbolProvider,
86+
LanguageTarget target
87+
) {
88+
if (!hasHttpChecksumTrait(model, settings.getService(model))) {
89+
return Collections.emptyMap();
90+
}
91+
92+
switch (target) {
93+
case NODE:
94+
return MapUtils.of(
95+
"streamHasher", writer -> {
96+
writer.addDependency(TypeScriptDependency.STREAM_HASHER_NODE);
97+
writer.addImport("readableStreamHasher", "streamHasher",
98+
TypeScriptDependency.STREAM_HASHER_NODE.packageName);
99+
writer.write("streamHasher");
100+
},
101+
"md5", writer -> {
102+
writer.addDependency(TypeScriptDependency.AWS_SDK_TYPES);
103+
writer.addImport("HashConstructor", "__HashConstructor",
104+
TypeScriptDependency.AWS_SDK_TYPES.packageName);
105+
writer.write("Hash.bind(null, \"md5\")");
106+
},
107+
"sha1", writer -> {
108+
writer.addDependency(TypeScriptDependency.AWS_SDK_TYPES);
109+
writer.addImport("HashConstructor", "__HashConstructor",
110+
TypeScriptDependency.AWS_SDK_TYPES.packageName);
111+
writer.write("Hash.bind(null, \"sha1\")");
112+
}
113+
);
114+
case BROWSER:
115+
return MapUtils.of(
116+
"streamHasher", writer -> {
117+
writer.addDependency(TypeScriptDependency.STREAM_HASHER_BROWSER);
118+
writer.addImport("blobHasher", "streamHasher",
119+
TypeScriptDependency.STREAM_HASHER_BROWSER.packageName);
120+
writer.write("streamHasher");
121+
},
122+
"md5", writer -> {
123+
writer.addDependency(TypeScriptDependency.MD5_BROWSER);
124+
writer.addImport("Md5", "Md5", TypeScriptDependency.MD5_BROWSER.packageName);
125+
writer.write("Md5");
126+
},
127+
"sha1", writer -> {
128+
writer.addDependency(AwsDependency.AWS_CRYPTO_SHA1_BROWSER);
129+
writer.addImport("Sha1",
130+
"Sha1", AwsDependency.AWS_CRYPTO_SHA1_BROWSER.packageName);
131+
writer.write("Sha1");
132+
}
133+
);
134+
default:
135+
return Collections.emptyMap();
136+
}
137+
}
138+
139+
@Override
140+
public List<RuntimeClientPlugin> getClientPlugins() {
141+
return ListUtils.of(
142+
RuntimeClientPlugin.builder()
143+
.withConventions(AwsDependency.FLEXIBLE_CHECKSUMS_MIDDLEWARE.dependency, "FlexibleChecksums",
144+
HAS_MIDDLEWARE)
145+
.additionalPluginFunctionParamsSupplier((m, s, o) -> getPluginFunctionParams(m, s, o))
146+
.operationPredicate((m, s, o) -> hasHttpChecksumTrait(o))
147+
.build()
148+
);
149+
}
150+
151+
private static Map<String, Object> getPluginFunctionParams(
152+
Model model,
153+
ServiceShape service,
154+
OperationShape operation
155+
) {
156+
Map<String, Object> params = new TreeMap<String, Object>();
157+
params.put("input", Symbol.builder().name("this.input").build());
158+
159+
HttpChecksumTrait httpChecksumTrait = operation.expectTrait(HttpChecksumTrait.class);
160+
params.put("requestChecksumRequired", httpChecksumTrait.isRequestChecksumRequired());
161+
httpChecksumTrait.getRequestAlgorithmMember().ifPresent(requestAlgorithmMember -> {
162+
params.put("requestAlgorithmMember", requestAlgorithmMember);
163+
});
164+
httpChecksumTrait.getRequestValidationModeMember().ifPresent(requestValidationModeMember -> {
165+
params.put("requestValidationModeMember", requestValidationModeMember);
166+
params.put("responseAlgorithms", httpChecksumTrait.getResponseAlgorithms());
167+
});
168+
169+
return params;
170+
}
171+
172+
// return true if operation shape is decorated with `httpChecksum` trait.
173+
private static boolean hasHttpChecksumTrait(OperationShape operation) {
174+
return operation.hasTrait(HttpChecksumTrait.class);
175+
}
176+
177+
private static boolean hasHttpChecksumTrait(
178+
Model model,
179+
ServiceShape service
180+
) {
181+
TopDownIndex topDownIndex = TopDownIndex.of(model);
182+
Set<OperationShape> operations = topDownIndex.getContainedOperations(service);
183+
for (OperationShape operation : operations) {
184+
if (hasHttpChecksumTrait(operation)) {
185+
return true;
186+
}
187+
}
188+
return false;
189+
}
190+
}

codegen/smithy-aws-typescript-codegen/src/main/java/software/amazon/smithy/aws/typescript/codegen/AwsDependency.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,9 @@ public enum AwsDependency implements SymbolDependencyContainer {
7070
MIDDLEWARE_USER_AGENT("dependencies", "@aws-sdk/middleware-user-agent"),
7171
AWS_SDK_UTIL_USER_AGENT_BROWSER(NORMAL_DEPENDENCY, "@aws-sdk/util-user-agent-browser"),
7272
AWS_SDK_UTIL_USER_AGENT_NODE(NORMAL_DEPENDENCY, "@aws-sdk/util-user-agent-node"),
73-
MIDDLEWARE_ENDPOINT_DISCOVERY(NORMAL_DEPENDENCY, "@aws-sdk/middleware-endpoint-discovery");
73+
MIDDLEWARE_ENDPOINT_DISCOVERY(NORMAL_DEPENDENCY, "@aws-sdk/middleware-endpoint-discovery"),
74+
AWS_CRYPTO_SHA1_BROWSER(NORMAL_DEPENDENCY, "@aws-crypto/sha1-browser", "2.0.0"),
75+
FLEXIBLE_CHECKSUMS_MIDDLEWARE(NORMAL_DEPENDENCY, "@aws-sdk/middleware-flexible-checksums");
7476

7577
public final String packageName;
7678
public final String version;

codegen/smithy-aws-typescript-codegen/src/main/resources/META-INF/services/software.amazon.smithy.typescript.codegen.integration.TypeScriptIntegration

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,4 +20,5 @@ software.amazon.smithy.aws.typescript.codegen.AddOmitRetryHeadersDependency
2020
software.amazon.smithy.aws.typescript.codegen.StripNewEnumNames
2121
software.amazon.smithy.aws.typescript.codegen.AddCrossRegionCopyingPlugin
2222
software.amazon.smithy.aws.typescript.codegen.AddDocumentClientPlugin
23-
software.amazon.smithy.aws.typescript.codegen.AddEndpointDiscoveryPlugin
23+
software.amazon.smithy.aws.typescript.codegen.AddEndpointDiscoveryPlugin
24+
software.amazon.smithy.aws.typescript.codegen.AddHttpChecksumDependency

0 commit comments

Comments
 (0)