Skip to content

Commit 471194e

Browse files
committed
Fix query literal serialization
This commit updates path and query serialization to properly handle serializing HTTP uri query literals. It also cleans up path serialization and return types for request component methods. It also includes a minor reordering of request parameter building for ease of reading.
1 parent 15133ec commit 471194e

File tree

1 file changed

+32
-18
lines changed

1 file changed

+32
-18
lines changed

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

Lines changed: 32 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -19,12 +19,14 @@
1919

2020
import java.util.Comparator;
2121
import java.util.List;
22+
import java.util.Map;
2223
import java.util.Optional;
2324
import java.util.Set;
2425
import java.util.TreeMap;
2526
import java.util.TreeSet;
2627
import java.util.logging.Logger;
2728

29+
import java.util.stream.Collectors;
2830
import software.amazon.smithy.codegen.core.CodegenException;
2931
import software.amazon.smithy.codegen.core.Symbol;
3032
import software.amazon.smithy.codegen.core.SymbolProvider;
@@ -34,6 +36,7 @@
3436
import software.amazon.smithy.model.knowledge.HttpBindingIndex;
3537
import software.amazon.smithy.model.knowledge.OperationIndex;
3638
import software.amazon.smithy.model.knowledge.TopDownIndex;
39+
import software.amazon.smithy.model.pattern.Pattern.Segment;
3740
import software.amazon.smithy.model.shapes.BlobShape;
3841
import software.amazon.smithy.model.shapes.BooleanShape;
3942
import software.amazon.smithy.model.shapes.CollectionShape;
@@ -185,21 +188,20 @@ private void generateOperationSerializer(
185188
+ " input: $T,\n"
186189
+ " context: __SerdeContext\n"
187190
+ "): Promise<$T> {", "}", methodName, inputType, requestType, () -> {
188-
List<HttpBinding> labelBindings = writeRequestLabels(context, operation, bindingIndex, trait);
189-
List<HttpBinding> queryBindings = writeRequestQueryString(context, operation, bindingIndex);
190191
writeHeaders(context, operation, bindingIndex);
192+
writeResolvedPath(context, operation, bindingIndex, trait);
193+
boolean hasQueryComponents = writeRequestQueryString(context, operation, bindingIndex, trait);
191194
List<HttpBinding> documentBindings = writeRequestBody(context, operation, bindingIndex);
192195

193196
writer.openBlock("return new $T({", "});", requestType, () -> {
194197
writer.write("...context.endpoint,");
195198
writer.write("protocol: \"https\",");
196199
writer.write("method: $S,", trait.getMethod());
197-
if (labelBindings.isEmpty()) {
198-
writer.write("path: $S,", trait.getUri());
199-
} else {
200-
writer.write("path: resolvedPath,");
201-
}
202200
writer.write("headers: headers,");
201+
writer.write("path: resolvedPath,");
202+
if (hasQueryComponents) {
203+
writer.write("query: query,");
204+
}
203205
if (!documentBindings.isEmpty()) {
204206
// Track all shapes bound to the document so their serializers may be generated.
205207
documentBindings.stream()
@@ -208,16 +210,13 @@ private void generateOperationSerializer(
208210
.forEach(serializingDocumentShapes::add);
209211
writer.write("body: body,");
210212
}
211-
if (!queryBindings.isEmpty()) {
212-
writer.write("query: query,");
213-
}
214213
});
215214
});
216215

217216
writer.write("");
218217
}
219218

220-
private List<HttpBinding> writeRequestLabels(
219+
private void writeResolvedPath(
221220
GenerationContext context,
222221
OperationShape operation,
223222
HttpBindingIndex bindingIndex,
@@ -227,9 +226,14 @@ private List<HttpBinding> writeRequestLabels(
227226
SymbolProvider symbolProvider = context.getSymbolProvider();
228227
List<HttpBinding> labelBindings = bindingIndex.getRequestBindings(operation, Location.LABEL);
229228

229+
// Always write the bound path, but only the actual segments.
230+
writer.write("let resolvedPath = $S;", "/" + trait.getUri().getSegments().stream()
231+
.map(Segment::toString)
232+
.collect(Collectors.joining("/")));
233+
234+
// Handle any label bindings.
230235
if (!labelBindings.isEmpty()) {
231236
Model model = context.getModel();
232-
writer.write("let resolvedPath = $S;", trait.getUri());
233237
for (HttpBinding binding : labelBindings) {
234238
String memberName = symbolProvider.toMemberName(binding.getMember());
235239
Shape target = model.expectShape(binding.getMember().getTarget());
@@ -248,22 +252,31 @@ private List<HttpBinding> writeRequestLabels(
248252
.write("}");
249253
}
250254
}
251-
252-
return labelBindings;
253255
}
254256

255-
private List<HttpBinding> writeRequestQueryString(
257+
private boolean writeRequestQueryString(
256258
GenerationContext context,
257259
OperationShape operation,
258-
HttpBindingIndex bindingIndex
260+
HttpBindingIndex bindingIndex,
261+
HttpTrait trait
259262
) {
260263
TypeScriptWriter writer = context.getWriter();
261264
SymbolProvider symbolProvider = context.getSymbolProvider();
262265
List<HttpBinding> queryBindings = bindingIndex.getRequestBindings(operation, Location.QUERY);
263266

267+
// Build the initial query bag.
268+
Map<String, String> queryLiterals = trait.getUri().getQueryLiterals();
269+
if (!queryLiterals.isEmpty()) {
270+
// Write any query literals present in the uri.
271+
writer.openBlock("const query: any = {", "};",
272+
() -> queryLiterals.forEach((k, v) -> writer.write("$S: $S,", k, v)));
273+
} else if (!queryBindings.isEmpty()) {
274+
writer.write("const query: any = {};");
275+
}
276+
277+
// Handle any additional query bindings.
264278
if (!queryBindings.isEmpty()) {
265279
Model model = context.getModel();
266-
writer.write("const query: any = {};");
267280
for (HttpBinding binding : queryBindings) {
268281
String memberName = symbolProvider.toMemberName(binding.getMember());
269282
writer.openBlock("if (input.$L !== undefined) {", "}", memberName, () -> {
@@ -275,7 +288,8 @@ private List<HttpBinding> writeRequestQueryString(
275288
}
276289
}
277290

278-
return queryBindings;
291+
// Any binding or literal means we generated a query bag.
292+
return !queryBindings.isEmpty() || !queryLiterals.isEmpty();
279293
}
280294

281295
private void writeHeaders(

0 commit comments

Comments
 (0)