Skip to content

Commit 3b265b5

Browse files
Update serde interfaces to differentiate in/out
This updates the interfaces for rest services to differentiate when an operation's input vs output vs error is being serialized / deserialized. This is necessary because there can be subtly different rules in each case.
1 parent c84ebeb commit 3b265b5

File tree

1 file changed

+37
-51
lines changed

1 file changed

+37
-51
lines changed

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

Lines changed: 37 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -125,7 +125,7 @@ public ApplicationProtocol getApplicationProtocol() {
125125
/**
126126
* Generates serialization functions for shapes in the passed set. These functions
127127
* should return a value that can then be serialized by the implementation of
128-
* {@code serializeInputDocument}. The {@link DocumentShapeSerVisitor} and {@link DocumentMemberSerVisitor}
128+
* {@code serializeDocument}. The {@link DocumentShapeSerVisitor} and {@link DocumentMemberSerVisitor}
129129
* are provided to reduce the effort of this implementation.
130130
*
131131
* @param context The generation context.
@@ -136,7 +136,7 @@ public ApplicationProtocol getApplicationProtocol() {
136136
/**
137137
* Generates deserialization functions for shapes in the passed set. These functions
138138
* should return a value that can then be deserialized by the implementation of
139-
* {@code deserializeOutputDocument}. The {@link DocumentShapeDeserVisitor} and
139+
* {@code deserializeDocument}. The {@link DocumentShapeDeserVisitor} and
140140
* {@link DocumentMemberDeserVisitor} are provided to reduce the effort of this implementation.
141141
*
142142
* @param context The generation context.
@@ -429,7 +429,8 @@ private void generateOperationResponseSerializer(
429429
+ "): Promise<$T> => {", "}", methodName, outputType, responseType, () -> {
430430
writeEmptyEndpoint(context);
431431
writeOperationStatusCode(context, operation, bindingIndex, trait);
432-
writeResponseHeaders(context, operation, bindingIndex, () -> writeDefaultHeaders(context, operation));
432+
writeResponseHeaders(context, operation, bindingIndex,
433+
() -> writeDefaultHeaders(context, operation, false));
433434

434435
List<HttpBinding> bodyBindings = writeResponseBody(context, operation, bindingIndex);
435436
if (!bodyBindings.isEmpty()) {
@@ -480,7 +481,7 @@ private void generateErrorSerializationImplementation(GenerationContext context,
480481
HttpBindingIndex bindingIndex) {
481482
TypeScriptWriter writer = context.getWriter();
482483
writeErrorStatusCode(context, error);
483-
writeResponseHeaders(context, error, bindingIndex, () -> writeDefaultErrorHeaders(context, error));
484+
writeResponseHeaders(context, error, bindingIndex, () -> writeDefaultHeaders(context, error, false));
484485

485486
List<HttpBinding> bodyBindings = writeResponseBody(context, error, bindingIndex);
486487
if (!bodyBindings.isEmpty()) {
@@ -722,7 +723,7 @@ private void writeRequestHeaders(
722723
// Only set the content type if one can be determined.
723724
bindingIndex.determineRequestContentType(operation, getDocumentContentType()).ifPresent(contentType ->
724725
writer.write("'content-type': $S,", contentType));
725-
writeDefaultHeaders(context, operation);
726+
writeDefaultHeaders(context, operation, true);
726727

727728
operation.getInput().ifPresent(outputId -> {
728729
for (HttpBinding binding : bindingIndex.getRequestBindings(operation, Location.HEADER)) {
@@ -803,7 +804,7 @@ private List<HttpBinding> writeRequestBody(
803804
List<HttpBinding> payloadBindings = bindingIndex.getRequestBindings(operation, Location.PAYLOAD);
804805
List<HttpBinding> documentBindings = bindingIndex.getRequestBindings(operation, Location.DOCUMENT);
805806
boolean shouldWriteDefaultBody = bindingIndex.getRequestBindings(operation).isEmpty();
806-
return writeBody(context, operation, payloadBindings, documentBindings, shouldWriteDefaultBody);
807+
return writeBody(context, operation, payloadBindings, documentBindings, shouldWriteDefaultBody, true);
807808
}
808809

809810
private List<HttpBinding> writeResponseBody(
@@ -817,15 +818,16 @@ private List<HttpBinding> writeResponseBody(
817818
List<HttpBinding> payloadBindings = bindingIndex.getResponseBindings(operationOrError, Location.PAYLOAD);
818819
List<HttpBinding> documentBindings = bindingIndex.getResponseBindings(operationOrError, Location.DOCUMENT);
819820
boolean shouldWriteDefaultBody = bindingIndex.getResponseBindings(operationOrError).isEmpty();
820-
return writeBody(context, operation, payloadBindings, documentBindings, shouldWriteDefaultBody);
821+
return writeBody(context, operation, payloadBindings, documentBindings, shouldWriteDefaultBody, false);
821822
}
822823

823824
private List<HttpBinding> writeBody(
824825
GenerationContext context,
825826
OperationShape operation,
826827
List<HttpBinding> payloadBindings,
827828
List<HttpBinding> documentBindings,
828-
boolean shouldWriteDefaultBody
829+
boolean shouldWriteDefaultBody,
830+
boolean isInput
829831
) {
830832
TypeScriptWriter writer = context.getWriter();
831833
// Write the default `body` property.
@@ -835,7 +837,7 @@ private List<HttpBinding> writeBody(
835837
if (!payloadBindings.isEmpty()) {
836838
// There can only be one payload binding.
837839
HttpBinding payloadBinding = payloadBindings.get(0);
838-
serializeInputPayload(context, operation, payloadBinding);
840+
serializePayload(context, operation, payloadBinding, true);
839841
return payloadBindings;
840842
}
841843

@@ -844,7 +846,7 @@ private List<HttpBinding> writeBody(
844846
if (!documentBindings.isEmpty() || shouldWriteDefaultBody) {
845847
documentBindings.sort(Comparator.comparing(HttpBinding::getMemberName));
846848

847-
serializeInputDocument(context, operation, documentBindings);
849+
serializeDocumentBody(context, operation, documentBindings, isInput);
848850
return documentBindings;
849851
}
850852

@@ -1110,34 +1112,14 @@ private String getTimestampInputParam(
11101112
* }</pre>
11111113
*
11121114
* @param context The generation context.
1113-
* @param operation The operation being generated.
1115+
* @param operationOrError The operation or error being generated.
1116+
* @param isInput Whether the headers for an input or output/error are being generated.
11141117
*/
1115-
protected void writeDefaultHeaders(GenerationContext context, OperationShape operation) {
1118+
protected void writeDefaultHeaders(GenerationContext context, Shape operationOrError, boolean isInput) {
11161119
}
11171120

11181121
/**
1119-
* Writes any additional HTTP headers required by the protocol implementation for errors.
1120-
*
1121-
* <p>Two parameters will be available in scope:
1122-
* <ul>
1123-
* <li>{@code input: <T>}: the type generated for the operation's error.</li>
1124-
* <li>{@code context: SerdeContext}: a TypeScript type containing context and tools for type serde.</li>
1125-
* </ul>
1126-
*
1127-
* <p>For example:
1128-
*
1129-
* <pre>{@code
1130-
* "foo": "This is a custom header",
1131-
* }</pre>
1132-
*
1133-
* @param context The generation context.
1134-
* @param error The error being generated.
1135-
*/
1136-
protected void writeDefaultErrorHeaders(GenerationContext context, StructureShape error) {
1137-
}
1138-
1139-
/**
1140-
* Writes the code needed to serialize the input document of a request.
1122+
* Writes the code needed to serialize a protocol document.
11411123
*
11421124
* <p>Implementations of this method are expected to set a value to the
11431125
* {@code body} variable that will be serialized as the request body.
@@ -1155,15 +1137,16 @@ protected void writeDefaultErrorHeaders(GenerationContext context, StructureShap
11551137
* }
11561138
* body = JSON.stringify(bodyParams);
11571139
* }</pre>
1158-
*
1159-
* @param context The generation context.
1140+
* @param context The generation context.
11601141
* @param operation The operation being generated.
11611142
* @param documentBindings The bindings to place in the document.
1143+
* @param isInput Whether the input or output/error of the operation is being serialized.
11621144
*/
1163-
protected abstract void serializeInputDocument(
1145+
protected abstract void serializeDocumentBody(
11641146
GenerationContext context,
11651147
OperationShape operation,
1166-
List<HttpBinding> documentBindings
1148+
List<HttpBinding> documentBindings,
1149+
boolean isInput
11671150
);
11681151

11691152
/**
@@ -1180,15 +1163,16 @@ protected abstract void serializeInputDocument(
11801163
* body = context.base64Encoder(input.body);
11811164
* }
11821165
* }</pre>
1183-
*
1184-
* @param context The generation context.
1166+
* @param context The generation context.
11851167
* @param operation The operation being generated.
11861168
* @param payloadBinding The payload binding to serialize.
1169+
* @param isInput Whether the input or output/error of the operation is being serialized.
11871170
*/
1188-
protected void serializeInputPayload(
1171+
protected void serializePayload(
11891172
GenerationContext context,
11901173
OperationShape operation,
1191-
HttpBinding payloadBinding
1174+
HttpBinding payloadBinding,
1175+
boolean isInput
11921176
) {
11931177
TypeScriptWriter writer = context.getWriter();
11941178
SymbolProvider symbolProvider = context.getSymbolProvider();
@@ -1627,7 +1611,7 @@ private List<HttpBinding> readErrorResponseBody(
16271611
writer.write("const data: any = $L;", getErrorBodyLocation(context, "parsedOutput.body"));
16281612
List<HttpBinding> responseBindings = bindingIndex.getResponseBindings(error, Location.DOCUMENT);
16291613
responseBindings.sort(Comparator.comparing(HttpBinding::getMemberName));
1630-
deserializeOutputDocument(context, error, responseBindings);
1614+
deserializeDocumentBody(context, error, responseBindings, false);
16311615
return responseBindings;
16321616
} else {
16331617
// Deserialize response body just like in a normal response.
@@ -1741,7 +1725,7 @@ private List<HttpBinding> readRequestBody(
17411725
List<HttpBinding> documentBindings = bindingIndex.getRequestBindings(operation, Location.DOCUMENT);
17421726
documentBindings.sort(Comparator.comparing(HttpBinding::getMemberName));
17431727
List<HttpBinding> payloadBindings = bindingIndex.getRequestBindings(operation, Location.PAYLOAD);
1744-
return readBody(context, operation, documentBindings, payloadBindings, Collections.emptyList());
1728+
return readBody(context, operation, documentBindings, payloadBindings, Collections.emptyList(), false);
17451729
}
17461730

17471731
private List<HttpBinding> readResponseBody(
@@ -1754,15 +1738,16 @@ private List<HttpBinding> readResponseBody(
17541738
List<HttpBinding> payloadBindings = bindingIndex.getResponseBindings(operationOrError, Location.PAYLOAD);
17551739
List<HttpBinding> responseCodeBindings = bindingIndex.getResponseBindings(
17561740
operationOrError, Location.RESPONSE_CODE);
1757-
return readBody(context, operationOrError, documentBindings, payloadBindings, responseCodeBindings);
1741+
return readBody(context, operationOrError, documentBindings, payloadBindings, responseCodeBindings, true);
17581742
}
17591743

17601744
private List<HttpBinding> readBody(
17611745
GenerationContext context,
17621746
Shape operationOrError,
17631747
List<HttpBinding> documentBindings,
17641748
List<HttpBinding> payloadBindings,
1765-
List<HttpBinding> responseCodeBindings
1749+
List<HttpBinding> responseCodeBindings,
1750+
boolean isInput
17661751
) {
17671752
TypeScriptWriter writer = context.getWriter();
17681753
SymbolProvider symbolProvider = context.getSymbolProvider();
@@ -1776,7 +1761,7 @@ private List<HttpBinding> readBody(
17761761
}
17771762
writer.write("const data: any = $L;", bodyLocation);
17781763

1779-
deserializeOutputDocument(context, operationOrError, documentBindings);
1764+
deserializeDocumentBody(context, operationOrError, documentBindings, isInput);
17801765
}
17811766
if (!payloadBindings.isEmpty()) {
17821767
HttpBinding payloadBinding = readResponsePayload(context, payloadBindings.get(0));
@@ -2325,7 +2310,7 @@ protected String getErrorBodyLocation(GenerationContext context, String outputLo
23252310
}
23262311

23272312
/**
2328-
* Writes the code needed to deserialize the output document of a response.
2313+
* Writes the code needed to deserialize a protocol document.
23292314
*
23302315
* <p>Implementations of this method are expected to set members in the
23312316
* {@code contents} variable that represents the type generated for the
@@ -2340,14 +2325,15 @@ protected String getErrorBodyLocation(GenerationContext context, String outputLo
23402325
* contents.fieldList = deserializeAws_restJson1_1FieldList(data.fieldList, context);
23412326
* }
23422327
* }</pre>
2343-
*
23442328
* @param context The generation context.
23452329
* @param operationOrError The operation or error with a document being deserialized.
23462330
* @param documentBindings The bindings to read from the document.
2331+
* @param isInput Whether the input or output/error of the operation is being deserialized.
23472332
*/
2348-
protected abstract void deserializeOutputDocument(
2333+
protected abstract void deserializeDocumentBody(
23492334
GenerationContext context,
23502335
Shape operationOrError,
2351-
List<HttpBinding> documentBindings
2336+
List<HttpBinding> documentBindings,
2337+
boolean isInput
23522338
);
23532339
}

0 commit comments

Comments
 (0)