19
19
20
20
import java .util .Comparator ;
21
21
import java .util .List ;
22
+ import java .util .Map ;
22
23
import java .util .Optional ;
23
24
import java .util .Set ;
24
25
import java .util .TreeMap ;
25
26
import java .util .TreeSet ;
26
27
import java .util .logging .Logger ;
27
28
29
+ import java .util .stream .Collectors ;
28
30
import software .amazon .smithy .codegen .core .CodegenException ;
29
31
import software .amazon .smithy .codegen .core .Symbol ;
30
32
import software .amazon .smithy .codegen .core .SymbolProvider ;
34
36
import software .amazon .smithy .model .knowledge .HttpBindingIndex ;
35
37
import software .amazon .smithy .model .knowledge .OperationIndex ;
36
38
import software .amazon .smithy .model .knowledge .TopDownIndex ;
39
+ import software .amazon .smithy .model .pattern .Pattern .Segment ;
37
40
import software .amazon .smithy .model .shapes .BlobShape ;
38
41
import software .amazon .smithy .model .shapes .BooleanShape ;
39
42
import software .amazon .smithy .model .shapes .CollectionShape ;
@@ -185,21 +188,20 @@ private void generateOperationSerializer(
185
188
+ " input: $T,\n "
186
189
+ " context: __SerdeContext\n "
187
190
+ "): Promise<$T> {" , "}" , methodName , inputType , requestType , () -> {
188
- List <HttpBinding > labelBindings = writeRequestLabels (context , operation , bindingIndex , trait );
189
- List <HttpBinding > queryBindings = writeRequestQueryString (context , operation , bindingIndex );
190
191
writeHeaders (context , operation , bindingIndex );
192
+ writeResolvedPath (context , operation , bindingIndex , trait );
193
+ boolean hasQueryComponents = writeRequestQueryString (context , operation , bindingIndex , trait );
191
194
List <HttpBinding > documentBindings = writeRequestBody (context , operation , bindingIndex );
192
195
193
196
writer .openBlock ("return new $T({" , "});" , requestType , () -> {
194
197
writer .write ("...context.endpoint," );
195
198
writer .write ("protocol: \" https\" ," );
196
199
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
- }
202
200
writer .write ("headers: headers," );
201
+ writer .write ("path: resolvedPath," );
202
+ if (hasQueryComponents ) {
203
+ writer .write ("query: query," );
204
+ }
203
205
if (!documentBindings .isEmpty ()) {
204
206
// Track all shapes bound to the document so their serializers may be generated.
205
207
documentBindings .stream ()
@@ -208,16 +210,13 @@ private void generateOperationSerializer(
208
210
.forEach (serializingDocumentShapes ::add );
209
211
writer .write ("body: body," );
210
212
}
211
- if (!queryBindings .isEmpty ()) {
212
- writer .write ("query: query," );
213
- }
214
213
});
215
214
});
216
215
217
216
writer .write ("" );
218
217
}
219
218
220
- private List < HttpBinding > writeRequestLabels (
219
+ private void writeResolvedPath (
221
220
GenerationContext context ,
222
221
OperationShape operation ,
223
222
HttpBindingIndex bindingIndex ,
@@ -227,9 +226,14 @@ private List<HttpBinding> writeRequestLabels(
227
226
SymbolProvider symbolProvider = context .getSymbolProvider ();
228
227
List <HttpBinding > labelBindings = bindingIndex .getRequestBindings (operation , Location .LABEL );
229
228
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.
230
235
if (!labelBindings .isEmpty ()) {
231
236
Model model = context .getModel ();
232
- writer .write ("let resolvedPath = $S;" , trait .getUri ());
233
237
for (HttpBinding binding : labelBindings ) {
234
238
String memberName = symbolProvider .toMemberName (binding .getMember ());
235
239
Shape target = model .expectShape (binding .getMember ().getTarget ());
@@ -248,22 +252,31 @@ private List<HttpBinding> writeRequestLabels(
248
252
.write ("}" );
249
253
}
250
254
}
251
-
252
- return labelBindings ;
253
255
}
254
256
255
- private List < HttpBinding > writeRequestQueryString (
257
+ private boolean writeRequestQueryString (
256
258
GenerationContext context ,
257
259
OperationShape operation ,
258
- HttpBindingIndex bindingIndex
260
+ HttpBindingIndex bindingIndex ,
261
+ HttpTrait trait
259
262
) {
260
263
TypeScriptWriter writer = context .getWriter ();
261
264
SymbolProvider symbolProvider = context .getSymbolProvider ();
262
265
List <HttpBinding > queryBindings = bindingIndex .getRequestBindings (operation , Location .QUERY );
263
266
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.
264
278
if (!queryBindings .isEmpty ()) {
265
279
Model model = context .getModel ();
266
- writer .write ("const query: any = {};" );
267
280
for (HttpBinding binding : queryBindings ) {
268
281
String memberName = symbolProvider .toMemberName (binding .getMember ());
269
282
writer .openBlock ("if (input.$L !== undefined) {" , "}" , memberName , () -> {
@@ -275,7 +288,8 @@ private List<HttpBinding> writeRequestQueryString(
275
288
}
276
289
}
277
290
278
- return queryBindings ;
291
+ // Any binding or literal means we generated a query bag.
292
+ return !queryBindings .isEmpty () || !queryLiterals .isEmpty ();
279
293
}
280
294
281
295
private void writeHeaders (
0 commit comments