Skip to content

Commit e2e28cf

Browse files
committed
handle unset unions
1 parent 38d7253 commit e2e28cf

File tree

6 files changed

+50
-5
lines changed

6 files changed

+50
-5
lines changed

.changeset/witty-rings-do.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"@smithy/smithy-client": minor
3+
---
4+
5+
add quoteHeader function

packages/smithy-client/src/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ export * from "./lazy-json";
1818
export * from "./NoOpLogger";
1919
export * from "./object-mapping";
2020
export * from "./parse-utils";
21+
export * from "./quote-header";
2122
export * from "./resolve-path";
2223
export * from "./ser-utils";
2324
export * from "./serde-json";
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
import { quoteHeader } from "./quote-header";
2+
3+
describe(quoteHeader.name, () => {
4+
it("should wrap header elements that include the delimiter", () => {
5+
expect(quoteHeader("b,c")).toBe('"b,c"');
6+
});
7+
8+
it("should not wrap header elements that don't include the delimiter", () => {
9+
expect(quoteHeader("bc")).toBe("bc");
10+
});
11+
});
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
/**
2+
* @public
3+
* @param part - header list element
4+
* @returns quoted string if part contains delimiter.
5+
*/
6+
export function quoteHeader(part: string) {
7+
return part.includes(",") ? `"${part}"` : part;
8+
}

smithy-typescript-codegen/src/main/java/software/amazon/smithy/typescript/codegen/HttpProtocolTestGenerator.java

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -471,7 +471,7 @@ private void writeHttpResponseAssertions(HttpMalformedResponseDefinition respons
471471
responseDefinition.getHeaders().forEach((header, value) -> {
472472
header = header.toLowerCase();
473473
writer.write("expect(r.headers[$S]).toBeDefined();", header);
474-
writer.write("expect(r.headers[$S]).toBe($S);", header, value);
474+
writer.write("expect(r.headers[$S]).toBe($S);", header, value.replaceAll("\\\\", "\\"));
475475
});
476476
writer.write("");
477477
responseDefinition.getBody().ifPresent(body -> {
@@ -545,9 +545,11 @@ private void writeHttpHostAssertion(HttpRequestTestCase testCase) {
545545
}
546546

547547
private void writeHttpBodyAssertions(String body, String mediaType, boolean isClientTest) {
548-
// If we expect an empty body, expect it to be falsy.
549548
if (body.isEmpty()) {
550-
writer.write("expect(r.body).toBeFalsy();");
549+
// If we expect an empty body, expect it to be falsy.
550+
// Or, for JSON an empty object represents an empty body.
551+
// mediaType is often UNKNOWN here.
552+
writer.write("expect(!r.body || r.body === `{}`).toBeTruthy();");
551553
return;
552554
}
553555

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

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1385,6 +1385,11 @@ private String getCollectionInputParam(
13851385

13861386
switch (bindingType) {
13871387
case HEADER:
1388+
if (collectionTarget.isStringShape()) {
1389+
context.getWriter().addImport(
1390+
"quoteHeader", "__quoteHeader", TypeScriptDependency.AWS_SMITHY_CLIENT);
1391+
return iteratedParam + ".map(__quoteHeader).join(', ')";
1392+
}
13881393
return iteratedParam + ".join(', ')";
13891394
case QUERY:
13901395
case QUERY_PARAMS:
@@ -2466,16 +2471,29 @@ private HttpBinding readPayload(
24662471
// If payload is a Union, then we need to parse the string into JavaScript object.
24672472
importUnionDeserializer(writer);
24682473
writer.write("const data: Record<string, any> | undefined "
2469-
+ "= __expectUnion(await parseBody(output.body, context));");
2474+
+ "= await parseBody(output.body, context);");
24702475
} else if (target instanceof StringShape || target instanceof DocumentShape) {
24712476
// If payload is String or Document, we need to collect body and convert binary to string.
24722477
writer.write("const data: any = await collectBodyString(output.body, context);");
24732478
} else {
24742479
throw new CodegenException(String.format("Unexpected shape type bound to payload: `%s`",
24752480
target.getType()));
24762481
}
2477-
writer.write("contents.$L = $L;", binding.getMemberName(), getOutputValue(context,
2482+
2483+
if (target instanceof UnionShape) {
2484+
writer.openBlock(
2485+
"if (Object.keys(data ?? {}).length) {",
2486+
"}",
2487+
() -> {
2488+
writer.write("contents.$L = __expectUnion($L);", binding.getMemberName(), getOutputValue(context,
2489+
Location.PAYLOAD, "data", binding.getMember(), target));
2490+
}
2491+
);
2492+
} else {
2493+
writer.write("contents.$L = $L;", binding.getMemberName(), getOutputValue(context,
24782494
Location.PAYLOAD, "data", binding.getMember(), target));
2495+
}
2496+
24792497
return binding;
24802498
}
24812499

0 commit comments

Comments
 (0)