Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 17 additions & 1 deletion packages/core/src/submodules/protocols/HttpBindingProtocol.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,12 @@ import { collectBody } from "./collect-stream-body";
import { extendedEncodeURIComponent } from "./extended-encode-uri-component";
import { HttpProtocol } from "./HttpProtocol";

/**
* Cache key for the body-only schema view that excludes HTTP-bound members.
* @internal
*/
const HTTP_BODY_MEMBERS = Symbol.for("@smithy/http-body-members");

/**
* Base for HTTP-binding protocols. Downstream examples
* include AWS REST JSON and AWS REST XML.
Expand Down Expand Up @@ -152,7 +158,17 @@ export abstract class HttpBindingProtocol extends HttpProtocol {
}

if (hasNonHttpBindingMember && input) {
serializer.write(schema, input);
const bodyNs = ns.filterMembers(HTTP_BODY_MEMBERS, (_name, memberNs) => {
const traits = memberNs.getMergedTraits();
return !(
traits.httpHeader ||
traits.httpLabel ||
traits.httpQuery ||
traits.httpPayload ||
traits.httpPrefixHeaders
);
});
serializer.write(bodyNs, input);
payload = serializer.flush() as Uint8Array;

// Due to Smithy validation, we can assume that the members with no HTTP
Expand Down
37 changes: 37 additions & 0 deletions packages/core/src/submodules/schema/schemas/NormalizedSchema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -413,6 +413,43 @@ export class NormalizedSchema implements INormalizedSchema {
return "";
}

/**
* Returns a view of this schema whose structIterator only yields members
* matching the given predicate.
*
* The returned object delegates all other NormalizedSchema methods to this instance.
* This is useful when a caller needs to pass a subset of struct members to a
* generic serializer without copying the underlying schema arrays.
*
* Results are cached on the underlying struct schema keyed by the provided symbol,
* so the predicate only runs once per schema regardless of how many requests use it.
*/
public filterMembers(
cacheKey: symbol,
predicate: (name: string, memberNs: NormalizedSchema) => boolean
): NormalizedSchema {
const struct = this.getSchema() as StaticStructureSchema & {
[key: symbol]: NormalizedSchema;
};
if (struct[cacheKey]) {
return struct[cacheKey];
}

const entries: Array<[string, NormalizedSchema]> = [];
for (const [name, memberNs] of this.structIterator()) {
if (predicate(name, memberNs)) {
entries.push([name, memberNs]);
}
}

const view = Object.create(this) as NormalizedSchema;
(view as any).structIterator = function* (): Generator<[string, NormalizedSchema], undefined, undefined> {
yield* entries;
};
struct[cacheKey] = view;
return view;
}

/**
* Allows iteration over members of a structure schema.
* Each yield is a pair of the member name and member schema.
Expand Down
1 change: 1 addition & 0 deletions packages/types/src/schema/schema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -180,6 +180,7 @@ export interface NormalizedSchema {
*/
getMemberSchema(member: string): NormalizedSchema | undefined;
structIterator(): Generator<[string, NormalizedSchema], undefined, undefined>;
filterMembers(cacheKey: symbol, predicate: (name: string, memberNs: NormalizedSchema) => boolean): NormalizedSchema;
}

/**
Expand Down