From caee754470531ca600c04f4ccaa3b89b0b3c4043 Mon Sep 17 00:00:00 2001 From: Chase Coalwell <782571+srchase@users.noreply.github.com> Date: Tue, 31 Jan 2023 10:06:12 -0700 Subject: [PATCH] chore(clients): upgrade to smithy 1.27.2 (#4387) --- codegen/gradle.properties | 2 +- private/aws-protocoltests-ec2/README.md | 14 +- .../aws-protocoltests-ec2/src/EC2Protocol.ts | 34 + .../src/EC2ProtocolClient.ts | 3 + .../src/commands/DatetimeOffsetsCommand.ts | 76 ++ .../src/commands/index.ts | 1 + .../src/models/models_0.ts | 11 + .../src/protocols/Aws_ec2.ts | 61 ++ .../test/functional/ec2query.spec.ts | 85 ++ private/aws-protocoltests-json/README.md | 14 +- .../src/JsonProtocol.ts | 34 + .../src/JsonProtocolClient.ts | 3 + .../src/commands/DatetimeOffsetsCommand.ts | 79 ++ .../src/commands/index.ts | 1 + .../src/models/models_0.ts | 11 + .../src/protocols/Aws_json1_1.ts | 55 + .../test/functional/awsjson1_1.spec.ts | 83 ++ private/aws-protocoltests-query/README.md | 14 +- .../src/QueryProtocol.ts | 34 + .../src/QueryProtocolClient.ts | 3 + .../src/commands/DatetimeOffsetsCommand.ts | 79 ++ .../src/commands/index.ts | 1 + .../src/models/models_0.ts | 11 + .../src/protocols/Aws_query.ts | 61 ++ .../test/functional/awsquery.spec.ts | 87 ++ .../src/RestJsonProtocol.ts | 34 + .../src/RestJsonProtocolClient.ts | 3 + .../src/commands/DatetimeOffsetsCommand.ts | 79 ++ .../src/commands/index.ts | 1 + .../src/models/models_0.ts | 11 + .../src/protocols/Aws_restJson1.ts | 58 + .../test/functional/restjson1.spec.ts | 125 +++ .../src/RestXmlProtocol.ts | 34 + .../src/RestXmlProtocolClient.ts | 3 + .../src/commands/DatetimeOffsetsCommand.ts | 79 ++ .../src/commands/index.ts | 1 + .../src/models/models_0.ts | 11 + .../src/protocols/Aws_restXml.ts | 58 + .../test/functional/restxml.spec.ts | 83 ++ .../src/models/models_0.ts | 233 +++-- .../src/protocols/Aws_restJson1.ts | 65 ++ .../src/server/RestJsonService.ts | 23 + .../src/server/operations/DatetimeOffsets.ts | 185 ++++ .../src/server/operations/index.ts | 1 + .../test/functional/restjson1.spec.ts | 46 + .../src/models/models_0.ts | 160 ++- .../src/protocols/Aws_restJson1.ts | 57 + .../test/functional/restjson1.spec.ts | 990 +++++++++++++++++- 48 files changed, 3020 insertions(+), 177 deletions(-) create mode 100644 private/aws-protocoltests-ec2/src/commands/DatetimeOffsetsCommand.ts create mode 100644 private/aws-protocoltests-json/src/commands/DatetimeOffsetsCommand.ts create mode 100644 private/aws-protocoltests-query/src/commands/DatetimeOffsetsCommand.ts create mode 100644 private/aws-protocoltests-restjson/src/commands/DatetimeOffsetsCommand.ts create mode 100644 private/aws-protocoltests-restxml/src/commands/DatetimeOffsetsCommand.ts create mode 100644 private/aws-restjson-server/src/server/operations/DatetimeOffsets.ts diff --git a/codegen/gradle.properties b/codegen/gradle.properties index 19912740b5f2b..b0efe6922f7e8 100644 --- a/codegen/gradle.properties +++ b/codegen/gradle.properties @@ -1,2 +1,2 @@ -smithyVersion=1.26.4 +smithyVersion=1.27.2 smithyGradleVersion=0.6.0 \ No newline at end of file diff --git a/private/aws-protocoltests-ec2/README.md b/private/aws-protocoltests-ec2/README.md index 14ce3fbec99af..723db5749b464 100644 --- a/private/aws-protocoltests-ec2/README.md +++ b/private/aws-protocoltests-ec2/README.md @@ -26,16 +26,16 @@ using your favorite package manager: The AWS SDK is modulized by clients and commands. To send a request, you only need to import the `EC2ProtocolClient` and -the commands you need, for example `EmptyInputAndEmptyOutputCommand`: +the commands you need, for example `DatetimeOffsetsCommand`: ```js // ES5 example -const { EC2ProtocolClient, EmptyInputAndEmptyOutputCommand } = require("@aws-sdk/aws-protocoltests-ec2"); +const { EC2ProtocolClient, DatetimeOffsetsCommand } = require("@aws-sdk/aws-protocoltests-ec2"); ``` ```ts // ES6+ example -import { EC2ProtocolClient, EmptyInputAndEmptyOutputCommand } from "@aws-sdk/aws-protocoltests-ec2"; +import { EC2ProtocolClient, DatetimeOffsetsCommand } from "@aws-sdk/aws-protocoltests-ec2"; ``` ### Usage @@ -54,7 +54,7 @@ const client = new EC2ProtocolClient({ region: "REGION" }); const params = { /** input parameters */ }; -const command = new EmptyInputAndEmptyOutputCommand(params); +const command = new DatetimeOffsetsCommand(params); ``` #### Async/await @@ -133,7 +133,7 @@ const client = new AWS.EC2Protocol({ region: "REGION" }); // async/await. try { - const data = await client.emptyInputAndEmptyOutput(params); + const data = await client.datetimeOffsets(params); // process data. } catch (error) { // error handling. @@ -141,7 +141,7 @@ try { // Promises. client - .emptyInputAndEmptyOutput(params) + .datetimeOffsets(params) .then((data) => { // process data. }) @@ -150,7 +150,7 @@ client }); // callbacks. -client.emptyInputAndEmptyOutput(params, (err, data) => { +client.datetimeOffsets(params, (err, data) => { // process err and data. }); ``` diff --git a/private/aws-protocoltests-ec2/src/EC2Protocol.ts b/private/aws-protocoltests-ec2/src/EC2Protocol.ts index 0ca231089946f..6582d4e5e392d 100644 --- a/private/aws-protocoltests-ec2/src/EC2Protocol.ts +++ b/private/aws-protocoltests-ec2/src/EC2Protocol.ts @@ -1,6 +1,11 @@ // smithy-typescript generated code import { HttpHandlerOptions as __HttpHandlerOptions } from "@aws-sdk/types"; +import { + DatetimeOffsetsCommand, + DatetimeOffsetsCommandInput, + DatetimeOffsetsCommandOutput, +} from "./commands/DatetimeOffsetsCommand"; import { EmptyInputAndEmptyOutputCommand, EmptyInputAndEmptyOutputCommandInput, @@ -97,6 +102,35 @@ import { EC2ProtocolClient } from "./EC2ProtocolClient"; * An EC2 query service that sends query requests and XML responses. */ export class EC2Protocol extends EC2ProtocolClient { + public datetimeOffsets( + args: DatetimeOffsetsCommandInput, + options?: __HttpHandlerOptions + ): Promise; + public datetimeOffsets( + args: DatetimeOffsetsCommandInput, + cb: (err: any, data?: DatetimeOffsetsCommandOutput) => void + ): void; + public datetimeOffsets( + args: DatetimeOffsetsCommandInput, + options: __HttpHandlerOptions, + cb: (err: any, data?: DatetimeOffsetsCommandOutput) => void + ): void; + public datetimeOffsets( + args: DatetimeOffsetsCommandInput, + optionsOrCb?: __HttpHandlerOptions | ((err: any, data?: DatetimeOffsetsCommandOutput) => void), + cb?: (err: any, data?: DatetimeOffsetsCommandOutput) => void + ): Promise | void { + const command = new DatetimeOffsetsCommand(args); + if (typeof optionsOrCb === "function") { + this.send(command, optionsOrCb); + } else if (typeof cb === "function") { + if (typeof optionsOrCb !== "object") throw new Error(`Expect http options but get ${typeof optionsOrCb}`); + this.send(command, optionsOrCb || {}, cb); + } else { + return this.send(command, optionsOrCb); + } + } + /** * The example tests how requests and responses are serialized when there's * no request or response members. diff --git a/private/aws-protocoltests-ec2/src/EC2ProtocolClient.ts b/private/aws-protocoltests-ec2/src/EC2ProtocolClient.ts index 20d1382b5ba3f..3c0c60c8ca99d 100644 --- a/private/aws-protocoltests-ec2/src/EC2ProtocolClient.ts +++ b/private/aws-protocoltests-ec2/src/EC2ProtocolClient.ts @@ -48,6 +48,7 @@ import { UserAgent as __UserAgent, } from "@aws-sdk/types"; +import { DatetimeOffsetsCommandInput, DatetimeOffsetsCommandOutput } from "./commands/DatetimeOffsetsCommand"; import { EmptyInputAndEmptyOutputCommandInput, EmptyInputAndEmptyOutputCommandOutput, @@ -91,6 +92,7 @@ import { XmlTimestampsCommandInput, XmlTimestampsCommandOutput } from "./command import { getRuntimeConfig as __getRuntimeConfig } from "./runtimeConfig"; export type ServiceInputTypes = + | DatetimeOffsetsCommandInput | EmptyInputAndEmptyOutputCommandInput | EndpointOperationCommandInput | EndpointWithHostLabelOperationCommandInput @@ -115,6 +117,7 @@ export type ServiceInputTypes = | XmlTimestampsCommandInput; export type ServiceOutputTypes = + | DatetimeOffsetsCommandOutput | EmptyInputAndEmptyOutputCommandOutput | EndpointOperationCommandOutput | EndpointWithHostLabelOperationCommandOutput diff --git a/private/aws-protocoltests-ec2/src/commands/DatetimeOffsetsCommand.ts b/private/aws-protocoltests-ec2/src/commands/DatetimeOffsetsCommand.ts new file mode 100644 index 0000000000000..f5cba98e27f30 --- /dev/null +++ b/private/aws-protocoltests-ec2/src/commands/DatetimeOffsetsCommand.ts @@ -0,0 +1,76 @@ +// smithy-typescript generated code +import { getSerdePlugin } from "@aws-sdk/middleware-serde"; +import { HttpRequest as __HttpRequest, HttpResponse as __HttpResponse } from "@aws-sdk/protocol-http"; +import { Command as $Command } from "@aws-sdk/smithy-client"; +import { + FinalizeHandlerArguments, + Handler, + HandlerExecutionContext, + HttpHandlerOptions as __HttpHandlerOptions, + MetadataBearer as __MetadataBearer, + MiddlewareStack, + SerdeContext as __SerdeContext, +} from "@aws-sdk/types"; + +import { EC2ProtocolClientResolvedConfig, ServiceInputTypes, ServiceOutputTypes } from "../EC2ProtocolClient"; +import { DatetimeOffsetsOutput, DatetimeOffsetsOutputFilterSensitiveLog } from "../models/models_0"; +import { deserializeAws_ec2DatetimeOffsetsCommand, serializeAws_ec2DatetimeOffsetsCommand } from "../protocols/Aws_ec2"; + +export interface DatetimeOffsetsCommandInput {} +export interface DatetimeOffsetsCommandOutput extends DatetimeOffsetsOutput, __MetadataBearer {} + +export class DatetimeOffsetsCommand extends $Command< + DatetimeOffsetsCommandInput, + DatetimeOffsetsCommandOutput, + EC2ProtocolClientResolvedConfig +> { + // Start section: command_properties + // End section: command_properties + + constructor(readonly input: DatetimeOffsetsCommandInput) { + // Start section: command_constructor + super(); + // End section: command_constructor + } + + /** + * @internal + */ + resolveMiddleware( + clientStack: MiddlewareStack, + configuration: EC2ProtocolClientResolvedConfig, + options?: __HttpHandlerOptions + ): Handler { + this.middlewareStack.use(getSerdePlugin(configuration, this.serialize, this.deserialize)); + + const stack = clientStack.concat(this.middlewareStack); + + const { logger } = configuration; + const clientName = "EC2ProtocolClient"; + const commandName = "DatetimeOffsetsCommand"; + const handlerExecutionContext: HandlerExecutionContext = { + logger, + clientName, + commandName, + inputFilterSensitiveLog: (input: any) => input, + outputFilterSensitiveLog: DatetimeOffsetsOutputFilterSensitiveLog, + }; + const { requestHandler } = configuration; + return stack.resolve( + (request: FinalizeHandlerArguments) => + requestHandler.handle(request.request as __HttpRequest, options || {}), + handlerExecutionContext + ); + } + + private serialize(input: DatetimeOffsetsCommandInput, context: __SerdeContext): Promise<__HttpRequest> { + return serializeAws_ec2DatetimeOffsetsCommand(input, context); + } + + private deserialize(output: __HttpResponse, context: __SerdeContext): Promise { + return deserializeAws_ec2DatetimeOffsetsCommand(output, context); + } + + // Start section: command_body_extra + // End section: command_body_extra +} diff --git a/private/aws-protocoltests-ec2/src/commands/index.ts b/private/aws-protocoltests-ec2/src/commands/index.ts index 811a34415d67c..ffec6e91494d4 100644 --- a/private/aws-protocoltests-ec2/src/commands/index.ts +++ b/private/aws-protocoltests-ec2/src/commands/index.ts @@ -1,4 +1,5 @@ // smithy-typescript generated code +export * from "./DatetimeOffsetsCommand"; export * from "./EmptyInputAndEmptyOutputCommand"; export * from "./EndpointOperationCommand"; export * from "./EndpointWithHostLabelOperationCommand"; diff --git a/private/aws-protocoltests-ec2/src/models/models_0.ts b/private/aws-protocoltests-ec2/src/models/models_0.ts index 7189d36554afe..e16aaafdf1cc0 100644 --- a/private/aws-protocoltests-ec2/src/models/models_0.ts +++ b/private/aws-protocoltests-ec2/src/models/models_0.ts @@ -3,6 +3,17 @@ import { ExceptionOptionType as __ExceptionOptionType } from "@aws-sdk/smithy-cl import { EC2ProtocolServiceException as __BaseException } from "./EC2ProtocolServiceException"; +export interface DatetimeOffsetsOutput { + datetime?: Date; +} + +/** + * @internal + */ +export const DatetimeOffsetsOutputFilterSensitiveLog = (obj: DatetimeOffsetsOutput): any => ({ + ...obj, +}); + export interface EmptyInputAndEmptyOutputInput {} /** diff --git a/private/aws-protocoltests-ec2/src/protocols/Aws_ec2.ts b/private/aws-protocoltests-ec2/src/protocols/Aws_ec2.ts index af47de72018e6..42b5644f4ddc4 100644 --- a/private/aws-protocoltests-ec2/src/protocols/Aws_ec2.ts +++ b/private/aws-protocoltests-ec2/src/protocols/Aws_ec2.ts @@ -32,6 +32,7 @@ import { import { XMLParser } from "fast-xml-parser"; import { v4 as generateIdempotencyToken } from "uuid"; +import { DatetimeOffsetsCommandInput, DatetimeOffsetsCommandOutput } from "../commands/DatetimeOffsetsCommand"; import { EmptyInputAndEmptyOutputCommandInput, EmptyInputAndEmptyOutputCommandOutput, @@ -76,6 +77,7 @@ import { EC2ProtocolServiceException as __BaseException } from "../models/EC2Pro import { ComplexError, ComplexNestedErrorData, + DatetimeOffsetsOutput, EmptyInputAndEmptyOutputInput, EmptyInputAndEmptyOutputOutput, FooEnum, @@ -107,6 +109,20 @@ import { XmlTimestampsOutput, } from "../models/models_0"; +export const serializeAws_ec2DatetimeOffsetsCommand = async ( + input: DatetimeOffsetsCommandInput, + context: __SerdeContext +): Promise<__HttpRequest> => { + const headers: __HeaderBag = { + "content-type": "application/x-www-form-urlencoded", + }; + const body = buildFormUrlencodedString({ + Action: "DatetimeOffsets", + Version: "2020-01-08", + }); + return buildHttpRpcRequest(context, headers, "/", undefined, body); +}; + export const serializeAws_ec2EmptyInputAndEmptyOutputCommand = async ( input: EmptyInputAndEmptyOutputCommandInput, context: __SerdeContext @@ -447,6 +463,41 @@ export const serializeAws_ec2XmlTimestampsCommand = async ( return buildHttpRpcRequest(context, headers, "/", undefined, body); }; +export const deserializeAws_ec2DatetimeOffsetsCommand = async ( + output: __HttpResponse, + context: __SerdeContext +): Promise => { + if (output.statusCode >= 300) { + return deserializeAws_ec2DatetimeOffsetsCommandError(output, context); + } + const data: any = await parseBody(output.body, context); + let contents: any = {}; + contents = deserializeAws_ec2DatetimeOffsetsOutput(data, context); + const response: DatetimeOffsetsCommandOutput = { + $metadata: deserializeMetadata(output), + ...contents, + }; + return Promise.resolve(response); +}; + +const deserializeAws_ec2DatetimeOffsetsCommandError = async ( + output: __HttpResponse, + context: __SerdeContext +): Promise => { + const parsedOutput: any = { + ...output, + body: await parseErrorBody(output.body, context), + }; + const errorCode = loadEc2ErrorCode(output, parsedOutput.body); + const parsedBody = parsedOutput.body; + throwDefaultError({ + output, + parsedBody: parsedBody.Errors.Error, + exceptionCtor: __BaseException, + errorCode, + }); +}; + export const deserializeAws_ec2EmptyInputAndEmptyOutputCommand = async ( output: __HttpResponse, context: __SerdeContext @@ -1481,6 +1532,16 @@ const deserializeAws_ec2ComplexNestedErrorData = (output: any, context: __SerdeC return contents; }; +const deserializeAws_ec2DatetimeOffsetsOutput = (output: any, context: __SerdeContext): DatetimeOffsetsOutput => { + const contents: any = { + datetime: undefined, + }; + if (output["datetime"] !== undefined) { + contents.datetime = __expectNonNull(__parseRfc3339DateTimeWithOffset(output["datetime"])); + } + return contents; +}; + const deserializeAws_ec2EmptyInputAndEmptyOutputOutput = ( output: any, context: __SerdeContext diff --git a/private/aws-protocoltests-ec2/test/functional/ec2query.spec.ts b/private/aws-protocoltests-ec2/test/functional/ec2query.spec.ts index efa5174e4d1ef..81f9d285205c2 100644 --- a/private/aws-protocoltests-ec2/test/functional/ec2query.spec.ts +++ b/private/aws-protocoltests-ec2/test/functional/ec2query.spec.ts @@ -4,6 +4,7 @@ import { Encoder as __Encoder } from "@aws-sdk/types"; import { HeaderBag, HttpHandlerOptions } from "@aws-sdk/types"; import { Readable } from "stream"; +import { DatetimeOffsetsCommand } from "../../src/commands/DatetimeOffsetsCommand"; import { EmptyInputAndEmptyOutputCommand } from "../../src/commands/EmptyInputAndEmptyOutputCommand"; import { EndpointOperationCommand } from "../../src/commands/EndpointOperationCommand"; import { EndpointWithHostLabelOperationCommand } from "../../src/commands/EndpointWithHostLabelOperationCommand"; @@ -163,6 +164,90 @@ const fail = (error?: any): never => { throw new Error(error); }; +/** + * Ensures that clients can correctly parse datetime (timestamps) with offsets + */ +it("Ec2QueryDateTimeWithNegativeOffset:Response", async () => { + const client = new EC2ProtocolClient({ + ...clientParams, + requestHandler: new ResponseDeserializationTestHandler( + true, + 200, + { + "content-type": "text/xml;charset=UTF-8", + }, + ` + 2019-12-16T22:48:18-01:00 + requestid + + ` + ), + }); + + const params: any = {}; + const command = new DatetimeOffsetsCommand(params); + + let r: any; + try { + r = await client.send(command); + } catch (err) { + fail("Expected a valid response to be returned, got " + err); + return; + } + expect(r["$metadata"].httpStatusCode).toBe(200); + const paramsToValidate: any = [ + { + datetime: new Date(1576540098000), + }, + ][0]; + Object.keys(paramsToValidate).forEach((param) => { + expect(r[param]).toBeDefined(); + expect(equivalentContents(r[param], paramsToValidate[param])).toBe(true); + }); +}); + +/** + * Ensures that clients can correctly parse datetime (timestamps) with offsets + */ +it("Ec2QueryDateTimeWithPositiveOffset:Response", async () => { + const client = new EC2ProtocolClient({ + ...clientParams, + requestHandler: new ResponseDeserializationTestHandler( + true, + 200, + { + "content-type": "text/xml;charset=UTF-8", + }, + ` + 2019-12-17T00:48:18+01:00 + requestid + + ` + ), + }); + + const params: any = {}; + const command = new DatetimeOffsetsCommand(params); + + let r: any; + try { + r = await client.send(command); + } catch (err) { + fail("Expected a valid response to be returned, got " + err); + return; + } + expect(r["$metadata"].httpStatusCode).toBe(200); + const paramsToValidate: any = [ + { + datetime: new Date(1576540098000), + }, + ][0]; + Object.keys(paramsToValidate).forEach((param) => { + expect(r[param]).toBeDefined(); + expect(equivalentContents(r[param], paramsToValidate[param])).toBe(true); + }); +}); + /** * Empty input serializes no extra query params */ diff --git a/private/aws-protocoltests-json/README.md b/private/aws-protocoltests-json/README.md index a65952abfd043..3436c6f46a905 100644 --- a/private/aws-protocoltests-json/README.md +++ b/private/aws-protocoltests-json/README.md @@ -24,16 +24,16 @@ using your favorite package manager: The AWS SDK is modulized by clients and commands. To send a request, you only need to import the `JsonProtocolClient` and -the commands you need, for example `EmptyOperationCommand`: +the commands you need, for example `DatetimeOffsetsCommand`: ```js // ES5 example -const { JsonProtocolClient, EmptyOperationCommand } = require("@aws-sdk/aws-protocoltests-json"); +const { JsonProtocolClient, DatetimeOffsetsCommand } = require("@aws-sdk/aws-protocoltests-json"); ``` ```ts // ES6+ example -import { JsonProtocolClient, EmptyOperationCommand } from "@aws-sdk/aws-protocoltests-json"; +import { JsonProtocolClient, DatetimeOffsetsCommand } from "@aws-sdk/aws-protocoltests-json"; ``` ### Usage @@ -52,7 +52,7 @@ const client = new JsonProtocolClient({ region: "REGION" }); const params = { /** input parameters */ }; -const command = new EmptyOperationCommand(params); +const command = new DatetimeOffsetsCommand(params); ``` #### Async/await @@ -131,7 +131,7 @@ const client = new AWS.JsonProtocol({ region: "REGION" }); // async/await. try { - const data = await client.emptyOperation(params); + const data = await client.datetimeOffsets(params); // process data. } catch (error) { // error handling. @@ -139,7 +139,7 @@ try { // Promises. client - .emptyOperation(params) + .datetimeOffsets(params) .then((data) => { // process data. }) @@ -148,7 +148,7 @@ client }); // callbacks. -client.emptyOperation(params, (err, data) => { +client.datetimeOffsets(params, (err, data) => { // process err and data. }); ``` diff --git a/private/aws-protocoltests-json/src/JsonProtocol.ts b/private/aws-protocoltests-json/src/JsonProtocol.ts index 5f4f1b167b441..e06fc1cdcae2b 100644 --- a/private/aws-protocoltests-json/src/JsonProtocol.ts +++ b/private/aws-protocoltests-json/src/JsonProtocol.ts @@ -1,6 +1,11 @@ // smithy-typescript generated code import { HttpHandlerOptions as __HttpHandlerOptions } from "@aws-sdk/types"; +import { + DatetimeOffsetsCommand, + DatetimeOffsetsCommandInput, + DatetimeOffsetsCommandOutput, +} from "./commands/DatetimeOffsetsCommand"; import { EmptyOperationCommand, EmptyOperationCommandInput, @@ -56,6 +61,35 @@ import { import { JsonProtocolClient } from "./JsonProtocolClient"; export class JsonProtocol extends JsonProtocolClient { + public datetimeOffsets( + args: DatetimeOffsetsCommandInput, + options?: __HttpHandlerOptions + ): Promise; + public datetimeOffsets( + args: DatetimeOffsetsCommandInput, + cb: (err: any, data?: DatetimeOffsetsCommandOutput) => void + ): void; + public datetimeOffsets( + args: DatetimeOffsetsCommandInput, + options: __HttpHandlerOptions, + cb: (err: any, data?: DatetimeOffsetsCommandOutput) => void + ): void; + public datetimeOffsets( + args: DatetimeOffsetsCommandInput, + optionsOrCb?: __HttpHandlerOptions | ((err: any, data?: DatetimeOffsetsCommandOutput) => void), + cb?: (err: any, data?: DatetimeOffsetsCommandOutput) => void + ): Promise | void { + const command = new DatetimeOffsetsCommand(args); + if (typeof optionsOrCb === "function") { + this.send(command, optionsOrCb); + } else if (typeof cb === "function") { + if (typeof optionsOrCb !== "object") throw new Error(`Expect http options but get ${typeof optionsOrCb}`); + this.send(command, optionsOrCb || {}, cb); + } else { + return this.send(command, optionsOrCb); + } + } + public emptyOperation( args: EmptyOperationCommandInput, options?: __HttpHandlerOptions diff --git a/private/aws-protocoltests-json/src/JsonProtocolClient.ts b/private/aws-protocoltests-json/src/JsonProtocolClient.ts index 0c70f9b95be8c..1610251441824 100644 --- a/private/aws-protocoltests-json/src/JsonProtocolClient.ts +++ b/private/aws-protocoltests-json/src/JsonProtocolClient.ts @@ -55,6 +55,7 @@ import { UserAgent as __UserAgent, } from "@aws-sdk/types"; +import { DatetimeOffsetsCommandInput, DatetimeOffsetsCommandOutput } from "./commands/DatetimeOffsetsCommand"; import { EmptyOperationCommandInput, EmptyOperationCommandOutput } from "./commands/EmptyOperationCommand"; import { EndpointOperationCommandInput, EndpointOperationCommandOutput } from "./commands/EndpointOperationCommand"; import { @@ -88,6 +89,7 @@ import { import { getRuntimeConfig as __getRuntimeConfig } from "./runtimeConfig"; export type ServiceInputTypes = + | DatetimeOffsetsCommandInput | EmptyOperationCommandInput | EndpointOperationCommandInput | EndpointWithHostLabelOperationCommandInput @@ -102,6 +104,7 @@ export type ServiceInputTypes = | SimpleScalarPropertiesCommandInput; export type ServiceOutputTypes = + | DatetimeOffsetsCommandOutput | EmptyOperationCommandOutput | EndpointOperationCommandOutput | EndpointWithHostLabelOperationCommandOutput diff --git a/private/aws-protocoltests-json/src/commands/DatetimeOffsetsCommand.ts b/private/aws-protocoltests-json/src/commands/DatetimeOffsetsCommand.ts new file mode 100644 index 0000000000000..a5028a2d1e257 --- /dev/null +++ b/private/aws-protocoltests-json/src/commands/DatetimeOffsetsCommand.ts @@ -0,0 +1,79 @@ +// smithy-typescript generated code +import { getSerdePlugin } from "@aws-sdk/middleware-serde"; +import { HttpRequest as __HttpRequest, HttpResponse as __HttpResponse } from "@aws-sdk/protocol-http"; +import { Command as $Command } from "@aws-sdk/smithy-client"; +import { + FinalizeHandlerArguments, + Handler, + HandlerExecutionContext, + HttpHandlerOptions as __HttpHandlerOptions, + MetadataBearer as __MetadataBearer, + MiddlewareStack, + SerdeContext as __SerdeContext, +} from "@aws-sdk/types"; + +import { JsonProtocolClientResolvedConfig, ServiceInputTypes, ServiceOutputTypes } from "../JsonProtocolClient"; +import { DatetimeOffsetsOutput, DatetimeOffsetsOutputFilterSensitiveLog } from "../models/models_0"; +import { + deserializeAws_json1_1DatetimeOffsetsCommand, + serializeAws_json1_1DatetimeOffsetsCommand, +} from "../protocols/Aws_json1_1"; + +export interface DatetimeOffsetsCommandInput {} +export interface DatetimeOffsetsCommandOutput extends DatetimeOffsetsOutput, __MetadataBearer {} + +export class DatetimeOffsetsCommand extends $Command< + DatetimeOffsetsCommandInput, + DatetimeOffsetsCommandOutput, + JsonProtocolClientResolvedConfig +> { + // Start section: command_properties + // End section: command_properties + + constructor(readonly input: DatetimeOffsetsCommandInput) { + // Start section: command_constructor + super(); + // End section: command_constructor + } + + /** + * @internal + */ + resolveMiddleware( + clientStack: MiddlewareStack, + configuration: JsonProtocolClientResolvedConfig, + options?: __HttpHandlerOptions + ): Handler { + this.middlewareStack.use(getSerdePlugin(configuration, this.serialize, this.deserialize)); + + const stack = clientStack.concat(this.middlewareStack); + + const { logger } = configuration; + const clientName = "JsonProtocolClient"; + const commandName = "DatetimeOffsetsCommand"; + const handlerExecutionContext: HandlerExecutionContext = { + logger, + clientName, + commandName, + inputFilterSensitiveLog: (input: any) => input, + outputFilterSensitiveLog: DatetimeOffsetsOutputFilterSensitiveLog, + }; + const { requestHandler } = configuration; + return stack.resolve( + (request: FinalizeHandlerArguments) => + requestHandler.handle(request.request as __HttpRequest, options || {}), + handlerExecutionContext + ); + } + + private serialize(input: DatetimeOffsetsCommandInput, context: __SerdeContext): Promise<__HttpRequest> { + return serializeAws_json1_1DatetimeOffsetsCommand(input, context); + } + + private deserialize(output: __HttpResponse, context: __SerdeContext): Promise { + return deserializeAws_json1_1DatetimeOffsetsCommand(output, context); + } + + // Start section: command_body_extra + // End section: command_body_extra +} diff --git a/private/aws-protocoltests-json/src/commands/index.ts b/private/aws-protocoltests-json/src/commands/index.ts index 24beacc1228d3..a042200adb0dc 100644 --- a/private/aws-protocoltests-json/src/commands/index.ts +++ b/private/aws-protocoltests-json/src/commands/index.ts @@ -1,4 +1,5 @@ // smithy-typescript generated code +export * from "./DatetimeOffsetsCommand"; export * from "./EmptyOperationCommand"; export * from "./EndpointOperationCommand"; export * from "./EndpointWithHostLabelOperationCommand"; diff --git a/private/aws-protocoltests-json/src/models/models_0.ts b/private/aws-protocoltests-json/src/models/models_0.ts index cbb5aafcee461..981586507e741 100644 --- a/private/aws-protocoltests-json/src/models/models_0.ts +++ b/private/aws-protocoltests-json/src/models/models_0.ts @@ -60,6 +60,17 @@ export class ComplexError extends __BaseException { } } +export interface DatetimeOffsetsOutput { + datetime?: Date; +} + +/** + * @internal + */ +export const DatetimeOffsetsOutputFilterSensitiveLog = (obj: DatetimeOffsetsOutput): any => ({ + ...obj, +}); + export interface EmptyStruct {} /** diff --git a/private/aws-protocoltests-json/src/protocols/Aws_json1_1.ts b/private/aws-protocoltests-json/src/protocols/Aws_json1_1.ts index 2b587361299d0..fbfbdd56f9b0f 100644 --- a/private/aws-protocoltests-json/src/protocols/Aws_json1_1.ts +++ b/private/aws-protocoltests-json/src/protocols/Aws_json1_1.ts @@ -32,6 +32,7 @@ import { } from "@aws-sdk/types"; import { v4 as generateIdempotencyToken } from "uuid"; +import { DatetimeOffsetsCommandInput, DatetimeOffsetsCommandOutput } from "../commands/DatetimeOffsetsCommand"; import { EmptyOperationCommandInput, EmptyOperationCommandOutput } from "../commands/EmptyOperationCommand"; import { EndpointOperationCommandInput, EndpointOperationCommandOutput } from "../commands/EndpointOperationCommand"; import { @@ -66,6 +67,7 @@ import { JsonProtocolServiceException as __BaseException } from "../models/JsonP import { ComplexError, ComplexNestedErrorData, + DatetimeOffsetsOutput, EmptyStruct, ErrorWithMembers, ErrorWithoutMembers, @@ -88,6 +90,18 @@ import { UnionInputOutput, } from "../models/models_0"; +export const serializeAws_json1_1DatetimeOffsetsCommand = async ( + input: DatetimeOffsetsCommandInput, + context: __SerdeContext +): Promise<__HttpRequest> => { + const headers: __HeaderBag = { + "content-type": "application/x-amz-json-1.1", + "x-amz-target": "JsonProtocol.DatetimeOffsets", + }; + const body = "{}"; + return buildHttpRpcRequest(context, headers, "/", undefined, body); +}; + export const serializeAws_json1_1EmptyOperationCommand = async ( input: EmptyOperationCommandInput, context: __SerdeContext @@ -258,6 +272,41 @@ export const serializeAws_json1_1SimpleScalarPropertiesCommand = async ( return buildHttpRpcRequest(context, headers, "/", undefined, body); }; +export const deserializeAws_json1_1DatetimeOffsetsCommand = async ( + output: __HttpResponse, + context: __SerdeContext +): Promise => { + if (output.statusCode >= 300) { + return deserializeAws_json1_1DatetimeOffsetsCommandError(output, context); + } + const data: any = await parseBody(output.body, context); + let contents: any = {}; + contents = deserializeAws_json1_1DatetimeOffsetsOutput(data, context); + const response: DatetimeOffsetsCommandOutput = { + $metadata: deserializeMetadata(output), + ...contents, + }; + return Promise.resolve(response); +}; + +const deserializeAws_json1_1DatetimeOffsetsCommandError = async ( + output: __HttpResponse, + context: __SerdeContext +): Promise => { + const parsedOutput: any = { + ...output, + body: await parseErrorBody(output.body, context), + }; + const errorCode = loadRestJsonErrorCode(output, parsedOutput.body); + const parsedBody = parsedOutput.body; + throwDefaultError({ + output, + parsedBody, + exceptionCtor: __BaseException, + errorCode, + }); +}; + export const deserializeAws_json1_1EmptyOperationCommand = async ( output: __HttpResponse, context: __SerdeContext @@ -1082,6 +1131,12 @@ const deserializeAws_json1_1ComplexNestedErrorData = (output: any, context: __Se } as any; }; +const deserializeAws_json1_1DatetimeOffsetsOutput = (output: any, context: __SerdeContext): DatetimeOffsetsOutput => { + return { + datetime: output.datetime != null ? __expectNonNull(__parseRfc3339DateTimeWithOffset(output.datetime)) : undefined, + } as any; +}; + const deserializeAws_json1_1Document = (output: any, context: __SerdeContext): __DocumentType => { return output; }; diff --git a/private/aws-protocoltests-json/test/functional/awsjson1_1.spec.ts b/private/aws-protocoltests-json/test/functional/awsjson1_1.spec.ts index 5f1bc6fcd248f..0e299b6495dbe 100644 --- a/private/aws-protocoltests-json/test/functional/awsjson1_1.spec.ts +++ b/private/aws-protocoltests-json/test/functional/awsjson1_1.spec.ts @@ -4,6 +4,7 @@ import { Encoder as __Encoder } from "@aws-sdk/types"; import { HeaderBag, HttpHandlerOptions } from "@aws-sdk/types"; import { Readable } from "stream"; +import { DatetimeOffsetsCommand } from "../../src/commands/DatetimeOffsetsCommand"; import { EmptyOperationCommand } from "../../src/commands/EmptyOperationCommand"; import { EndpointOperationCommand } from "../../src/commands/EndpointOperationCommand"; import { EndpointWithHostLabelOperationCommand } from "../../src/commands/EndpointWithHostLabelOperationCommand"; @@ -153,6 +154,88 @@ const fail = (error?: any): never => { throw new Error(error); }; +/** + * Ensures that clients can correctly parse datetime (timestamps) with offsets + */ +it("AwsJson11DateTimeWithNegativeOffset:Response", async () => { + const client = new JsonProtocolClient({ + ...clientParams, + requestHandler: new ResponseDeserializationTestHandler( + true, + 200, + { + "content-type": "application/x-amz-json-1.1", + }, + ` { + "datetime": "2019-12-16T22:48:18-01:00" + } + ` + ), + }); + + const params: any = {}; + const command = new DatetimeOffsetsCommand(params); + + let r: any; + try { + r = await client.send(command); + } catch (err) { + fail("Expected a valid response to be returned, got " + err); + return; + } + expect(r["$metadata"].httpStatusCode).toBe(200); + const paramsToValidate: any = [ + { + datetime: new Date(1576540098000), + }, + ][0]; + Object.keys(paramsToValidate).forEach((param) => { + expect(r[param]).toBeDefined(); + expect(equivalentContents(r[param], paramsToValidate[param])).toBe(true); + }); +}); + +/** + * Ensures that clients can correctly parse datetime (timestamps) with offsets + */ +it("AwsJson11DateTimeWithPositiveOffset:Response", async () => { + const client = new JsonProtocolClient({ + ...clientParams, + requestHandler: new ResponseDeserializationTestHandler( + true, + 200, + { + "content-type": "application/x-amz-json-1.1", + }, + ` { + "datetime": "2019-12-17T00:48:18+01:00" + } + ` + ), + }); + + const params: any = {}; + const command = new DatetimeOffsetsCommand(params); + + let r: any; + try { + r = await client.send(command); + } catch (err) { + fail("Expected a valid response to be returned, got " + err); + return; + } + expect(r["$metadata"].httpStatusCode).toBe(200); + const paramsToValidate: any = [ + { + datetime: new Date(1576540098000), + }, + ][0]; + Object.keys(paramsToValidate).forEach((param) => { + expect(r[param]).toBeDefined(); + expect(equivalentContents(r[param], paramsToValidate[param])).toBe(true); + }); +}); + /** * Sends requests to / */ diff --git a/private/aws-protocoltests-query/README.md b/private/aws-protocoltests-query/README.md index e1a05acc0283c..7b29875a7f6c0 100644 --- a/private/aws-protocoltests-query/README.md +++ b/private/aws-protocoltests-query/README.md @@ -26,16 +26,16 @@ using your favorite package manager: The AWS SDK is modulized by clients and commands. To send a request, you only need to import the `QueryProtocolClient` and -the commands you need, for example `EmptyInputAndEmptyOutputCommand`: +the commands you need, for example `DatetimeOffsetsCommand`: ```js // ES5 example -const { QueryProtocolClient, EmptyInputAndEmptyOutputCommand } = require("@aws-sdk/aws-protocoltests-query"); +const { QueryProtocolClient, DatetimeOffsetsCommand } = require("@aws-sdk/aws-protocoltests-query"); ``` ```ts // ES6+ example -import { QueryProtocolClient, EmptyInputAndEmptyOutputCommand } from "@aws-sdk/aws-protocoltests-query"; +import { QueryProtocolClient, DatetimeOffsetsCommand } from "@aws-sdk/aws-protocoltests-query"; ``` ### Usage @@ -54,7 +54,7 @@ const client = new QueryProtocolClient({ region: "REGION" }); const params = { /** input parameters */ }; -const command = new EmptyInputAndEmptyOutputCommand(params); +const command = new DatetimeOffsetsCommand(params); ``` #### Async/await @@ -133,7 +133,7 @@ const client = new AWS.QueryProtocol({ region: "REGION" }); // async/await. try { - const data = await client.emptyInputAndEmptyOutput(params); + const data = await client.datetimeOffsets(params); // process data. } catch (error) { // error handling. @@ -141,7 +141,7 @@ try { // Promises. client - .emptyInputAndEmptyOutput(params) + .datetimeOffsets(params) .then((data) => { // process data. }) @@ -150,7 +150,7 @@ client }); // callbacks. -client.emptyInputAndEmptyOutput(params, (err, data) => { +client.datetimeOffsets(params, (err, data) => { // process err and data. }); ``` diff --git a/private/aws-protocoltests-query/src/QueryProtocol.ts b/private/aws-protocoltests-query/src/QueryProtocol.ts index 165c9c09761dd..309742010c54c 100644 --- a/private/aws-protocoltests-query/src/QueryProtocol.ts +++ b/private/aws-protocoltests-query/src/QueryProtocol.ts @@ -1,6 +1,11 @@ // smithy-typescript generated code import { HttpHandlerOptions as __HttpHandlerOptions } from "@aws-sdk/types"; +import { + DatetimeOffsetsCommand, + DatetimeOffsetsCommandInput, + DatetimeOffsetsCommandOutput, +} from "./commands/DatetimeOffsetsCommand"; import { EmptyInputAndEmptyOutputCommand, EmptyInputAndEmptyOutputCommandInput, @@ -129,6 +134,35 @@ import { QueryProtocolClient } from "./QueryProtocolClient"; * A query service that sends query requests and XML responses. */ export class QueryProtocol extends QueryProtocolClient { + public datetimeOffsets( + args: DatetimeOffsetsCommandInput, + options?: __HttpHandlerOptions + ): Promise; + public datetimeOffsets( + args: DatetimeOffsetsCommandInput, + cb: (err: any, data?: DatetimeOffsetsCommandOutput) => void + ): void; + public datetimeOffsets( + args: DatetimeOffsetsCommandInput, + options: __HttpHandlerOptions, + cb: (err: any, data?: DatetimeOffsetsCommandOutput) => void + ): void; + public datetimeOffsets( + args: DatetimeOffsetsCommandInput, + optionsOrCb?: __HttpHandlerOptions | ((err: any, data?: DatetimeOffsetsCommandOutput) => void), + cb?: (err: any, data?: DatetimeOffsetsCommandOutput) => void + ): Promise | void { + const command = new DatetimeOffsetsCommand(args); + if (typeof optionsOrCb === "function") { + this.send(command, optionsOrCb); + } else if (typeof cb === "function") { + if (typeof optionsOrCb !== "object") throw new Error(`Expect http options but get ${typeof optionsOrCb}`); + this.send(command, optionsOrCb || {}, cb); + } else { + return this.send(command, optionsOrCb); + } + } + /** * The example tests how requests and responses are serialized when there's * no request or response members. diff --git a/private/aws-protocoltests-query/src/QueryProtocolClient.ts b/private/aws-protocoltests-query/src/QueryProtocolClient.ts index 8d2d798185803..389449fd5a0f6 100644 --- a/private/aws-protocoltests-query/src/QueryProtocolClient.ts +++ b/private/aws-protocoltests-query/src/QueryProtocolClient.ts @@ -48,6 +48,7 @@ import { UserAgent as __UserAgent, } from "@aws-sdk/types"; +import { DatetimeOffsetsCommandInput, DatetimeOffsetsCommandOutput } from "./commands/DatetimeOffsetsCommand"; import { EmptyInputAndEmptyOutputCommandInput, EmptyInputAndEmptyOutputCommandOutput, @@ -105,6 +106,7 @@ import { XmlTimestampsCommandInput, XmlTimestampsCommandOutput } from "./command import { getRuntimeConfig as __getRuntimeConfig } from "./runtimeConfig"; export type ServiceInputTypes = + | DatetimeOffsetsCommandInput | EmptyInputAndEmptyOutputCommandInput | EndpointOperationCommandInput | EndpointWithHostLabelOperationCommandInput @@ -137,6 +139,7 @@ export type ServiceInputTypes = | XmlTimestampsCommandInput; export type ServiceOutputTypes = + | DatetimeOffsetsCommandOutput | EmptyInputAndEmptyOutputCommandOutput | EndpointOperationCommandOutput | EndpointWithHostLabelOperationCommandOutput diff --git a/private/aws-protocoltests-query/src/commands/DatetimeOffsetsCommand.ts b/private/aws-protocoltests-query/src/commands/DatetimeOffsetsCommand.ts new file mode 100644 index 0000000000000..bde5150e45e18 --- /dev/null +++ b/private/aws-protocoltests-query/src/commands/DatetimeOffsetsCommand.ts @@ -0,0 +1,79 @@ +// smithy-typescript generated code +import { getSerdePlugin } from "@aws-sdk/middleware-serde"; +import { HttpRequest as __HttpRequest, HttpResponse as __HttpResponse } from "@aws-sdk/protocol-http"; +import { Command as $Command } from "@aws-sdk/smithy-client"; +import { + FinalizeHandlerArguments, + Handler, + HandlerExecutionContext, + HttpHandlerOptions as __HttpHandlerOptions, + MetadataBearer as __MetadataBearer, + MiddlewareStack, + SerdeContext as __SerdeContext, +} from "@aws-sdk/types"; + +import { DatetimeOffsetsOutput, DatetimeOffsetsOutputFilterSensitiveLog } from "../models/models_0"; +import { + deserializeAws_queryDatetimeOffsetsCommand, + serializeAws_queryDatetimeOffsetsCommand, +} from "../protocols/Aws_query"; +import { QueryProtocolClientResolvedConfig, ServiceInputTypes, ServiceOutputTypes } from "../QueryProtocolClient"; + +export interface DatetimeOffsetsCommandInput {} +export interface DatetimeOffsetsCommandOutput extends DatetimeOffsetsOutput, __MetadataBearer {} + +export class DatetimeOffsetsCommand extends $Command< + DatetimeOffsetsCommandInput, + DatetimeOffsetsCommandOutput, + QueryProtocolClientResolvedConfig +> { + // Start section: command_properties + // End section: command_properties + + constructor(readonly input: DatetimeOffsetsCommandInput) { + // Start section: command_constructor + super(); + // End section: command_constructor + } + + /** + * @internal + */ + resolveMiddleware( + clientStack: MiddlewareStack, + configuration: QueryProtocolClientResolvedConfig, + options?: __HttpHandlerOptions + ): Handler { + this.middlewareStack.use(getSerdePlugin(configuration, this.serialize, this.deserialize)); + + const stack = clientStack.concat(this.middlewareStack); + + const { logger } = configuration; + const clientName = "QueryProtocolClient"; + const commandName = "DatetimeOffsetsCommand"; + const handlerExecutionContext: HandlerExecutionContext = { + logger, + clientName, + commandName, + inputFilterSensitiveLog: (input: any) => input, + outputFilterSensitiveLog: DatetimeOffsetsOutputFilterSensitiveLog, + }; + const { requestHandler } = configuration; + return stack.resolve( + (request: FinalizeHandlerArguments) => + requestHandler.handle(request.request as __HttpRequest, options || {}), + handlerExecutionContext + ); + } + + private serialize(input: DatetimeOffsetsCommandInput, context: __SerdeContext): Promise<__HttpRequest> { + return serializeAws_queryDatetimeOffsetsCommand(input, context); + } + + private deserialize(output: __HttpResponse, context: __SerdeContext): Promise { + return deserializeAws_queryDatetimeOffsetsCommand(output, context); + } + + // Start section: command_body_extra + // End section: command_body_extra +} diff --git a/private/aws-protocoltests-query/src/commands/index.ts b/private/aws-protocoltests-query/src/commands/index.ts index 9d0b00dfd0d4f..b30f5dfec1585 100644 --- a/private/aws-protocoltests-query/src/commands/index.ts +++ b/private/aws-protocoltests-query/src/commands/index.ts @@ -1,4 +1,5 @@ // smithy-typescript generated code +export * from "./DatetimeOffsetsCommand"; export * from "./EmptyInputAndEmptyOutputCommand"; export * from "./EndpointOperationCommand"; export * from "./EndpointWithHostLabelOperationCommand"; diff --git a/private/aws-protocoltests-query/src/models/models_0.ts b/private/aws-protocoltests-query/src/models/models_0.ts index fbb99ea895f7a..8118726830937 100644 --- a/private/aws-protocoltests-query/src/models/models_0.ts +++ b/private/aws-protocoltests-query/src/models/models_0.ts @@ -28,6 +28,17 @@ export enum IntegerEnum { C = 3, } +export interface DatetimeOffsetsOutput { + datetime?: Date; +} + +/** + * @internal + */ +export const DatetimeOffsetsOutputFilterSensitiveLog = (obj: DatetimeOffsetsOutput): any => ({ + ...obj, +}); + export interface EmptyInputAndEmptyOutputInput {} /** diff --git a/private/aws-protocoltests-query/src/protocols/Aws_query.ts b/private/aws-protocoltests-query/src/protocols/Aws_query.ts index 7f64909496c50..6276df676b458 100644 --- a/private/aws-protocoltests-query/src/protocols/Aws_query.ts +++ b/private/aws-protocoltests-query/src/protocols/Aws_query.ts @@ -32,6 +32,7 @@ import { import { XMLParser } from "fast-xml-parser"; import { v4 as generateIdempotencyToken } from "uuid"; +import { DatetimeOffsetsCommandInput, DatetimeOffsetsCommandOutput } from "../commands/DatetimeOffsetsCommand"; import { EmptyInputAndEmptyOutputCommandInput, EmptyInputAndEmptyOutputCommandOutput, @@ -90,6 +91,7 @@ import { ComplexError, ComplexNestedErrorData, CustomCodeError, + DatetimeOffsetsOutput, EmptyInputAndEmptyOutputInput, EmptyInputAndEmptyOutputOutput, FlattenedXmlMapOutput, @@ -130,6 +132,20 @@ import { } from "../models/models_0"; import { QueryProtocolServiceException as __BaseException } from "../models/QueryProtocolServiceException"; +export const serializeAws_queryDatetimeOffsetsCommand = async ( + input: DatetimeOffsetsCommandInput, + context: __SerdeContext +): Promise<__HttpRequest> => { + const headers: __HeaderBag = { + "content-type": "application/x-www-form-urlencoded", + }; + const body = buildFormUrlencodedString({ + Action: "DatetimeOffsets", + Version: "2020-01-08", + }); + return buildHttpRpcRequest(context, headers, "/", undefined, body); +}; + export const serializeAws_queryEmptyInputAndEmptyOutputCommand = async ( input: EmptyInputAndEmptyOutputCommandInput, context: __SerdeContext @@ -586,6 +602,41 @@ export const serializeAws_queryXmlTimestampsCommand = async ( return buildHttpRpcRequest(context, headers, "/", undefined, body); }; +export const deserializeAws_queryDatetimeOffsetsCommand = async ( + output: __HttpResponse, + context: __SerdeContext +): Promise => { + if (output.statusCode >= 300) { + return deserializeAws_queryDatetimeOffsetsCommandError(output, context); + } + const data: any = await parseBody(output.body, context); + let contents: any = {}; + contents = deserializeAws_queryDatetimeOffsetsOutput(data.DatetimeOffsetsResult, context); + const response: DatetimeOffsetsCommandOutput = { + $metadata: deserializeMetadata(output), + ...contents, + }; + return Promise.resolve(response); +}; + +const deserializeAws_queryDatetimeOffsetsCommandError = async ( + output: __HttpResponse, + context: __SerdeContext +): Promise => { + const parsedOutput: any = { + ...output, + body: await parseErrorBody(output.body, context), + }; + const errorCode = loadQueryErrorCode(output, parsedOutput.body); + const parsedBody = parsedOutput.body; + throwDefaultError({ + output, + parsedBody: parsedBody.Error, + exceptionCtor: __BaseException, + errorCode, + }); +}; + export const deserializeAws_queryEmptyInputAndEmptyOutputCommand = async ( output: __HttpResponse, context: __SerdeContext @@ -2063,6 +2114,16 @@ const deserializeAws_queryCustomCodeError = (output: any, context: __SerdeContex return contents; }; +const deserializeAws_queryDatetimeOffsetsOutput = (output: any, context: __SerdeContext): DatetimeOffsetsOutput => { + const contents: any = { + datetime: undefined, + }; + if (output["datetime"] !== undefined) { + contents.datetime = __expectNonNull(__parseRfc3339DateTimeWithOffset(output["datetime"])); + } + return contents; +}; + const deserializeAws_queryEmptyInputAndEmptyOutputOutput = ( output: any, context: __SerdeContext diff --git a/private/aws-protocoltests-query/test/functional/awsquery.spec.ts b/private/aws-protocoltests-query/test/functional/awsquery.spec.ts index 74bc67bdd4e68..e3098ab6e62bb 100644 --- a/private/aws-protocoltests-query/test/functional/awsquery.spec.ts +++ b/private/aws-protocoltests-query/test/functional/awsquery.spec.ts @@ -4,6 +4,7 @@ import { Encoder as __Encoder } from "@aws-sdk/types"; import { HeaderBag, HttpHandlerOptions } from "@aws-sdk/types"; import { Readable } from "stream"; +import { DatetimeOffsetsCommand } from "../../src/commands/DatetimeOffsetsCommand"; import { EmptyInputAndEmptyOutputCommand } from "../../src/commands/EmptyInputAndEmptyOutputCommand"; import { EndpointOperationCommand } from "../../src/commands/EndpointOperationCommand"; import { EndpointWithHostLabelOperationCommand } from "../../src/commands/EndpointWithHostLabelOperationCommand"; @@ -171,6 +172,92 @@ const fail = (error?: any): never => { throw new Error(error); }; +/** + * Ensures that clients can correctly parse datetime (timestamps) with offsets + */ +it("AwsQueryDateTimeWithNegativeOffset:Response", async () => { + const client = new QueryProtocolClient({ + ...clientParams, + requestHandler: new ResponseDeserializationTestHandler( + true, + 200, + { + "content-type": "text/xml", + }, + ` + + 2019-12-16T22:48:18-01:00 + + + ` + ), + }); + + const params: any = {}; + const command = new DatetimeOffsetsCommand(params); + + let r: any; + try { + r = await client.send(command); + } catch (err) { + fail("Expected a valid response to be returned, got " + err); + return; + } + expect(r["$metadata"].httpStatusCode).toBe(200); + const paramsToValidate: any = [ + { + datetime: new Date(1576540098000), + }, + ][0]; + Object.keys(paramsToValidate).forEach((param) => { + expect(r[param]).toBeDefined(); + expect(equivalentContents(r[param], paramsToValidate[param])).toBe(true); + }); +}); + +/** + * Ensures that clients can correctly parse datetime (timestamps) with offsets + */ +it("AwsQueryDateTimeWithPositiveOffset:Response", async () => { + const client = new QueryProtocolClient({ + ...clientParams, + requestHandler: new ResponseDeserializationTestHandler( + true, + 200, + { + "content-type": "text/xml", + }, + ` + + 2019-12-17T00:48:18+01:00 + + + ` + ), + }); + + const params: any = {}; + const command = new DatetimeOffsetsCommand(params); + + let r: any; + try { + r = await client.send(command); + } catch (err) { + fail("Expected a valid response to be returned, got " + err); + return; + } + expect(r["$metadata"].httpStatusCode).toBe(200); + const paramsToValidate: any = [ + { + datetime: new Date(1576540098000), + }, + ][0]; + Object.keys(paramsToValidate).forEach((param) => { + expect(r[param]).toBeDefined(); + expect(equivalentContents(r[param], paramsToValidate[param])).toBe(true); + }); +}); + /** * Empty input serializes no extra query params */ diff --git a/private/aws-protocoltests-restjson/src/RestJsonProtocol.ts b/private/aws-protocoltests-restjson/src/RestJsonProtocol.ts index ecfe821ccd3dd..2985a3286a9c2 100644 --- a/private/aws-protocoltests-restjson/src/RestJsonProtocol.ts +++ b/private/aws-protocoltests-restjson/src/RestJsonProtocol.ts @@ -16,6 +16,11 @@ import { ConstantQueryStringCommandInput, ConstantQueryStringCommandOutput, } from "./commands/ConstantQueryStringCommand"; +import { + DatetimeOffsetsCommand, + DatetimeOffsetsCommandInput, + DatetimeOffsetsCommandOutput, +} from "./commands/DatetimeOffsetsCommand"; import { DocumentTypeAsPayloadCommand, DocumentTypeAsPayloadCommandInput, @@ -523,6 +528,35 @@ export class RestJsonProtocol extends RestJsonProtocolClient { } } + public datetimeOffsets( + args: DatetimeOffsetsCommandInput, + options?: __HttpHandlerOptions + ): Promise; + public datetimeOffsets( + args: DatetimeOffsetsCommandInput, + cb: (err: any, data?: DatetimeOffsetsCommandOutput) => void + ): void; + public datetimeOffsets( + args: DatetimeOffsetsCommandInput, + options: __HttpHandlerOptions, + cb: (err: any, data?: DatetimeOffsetsCommandOutput) => void + ): void; + public datetimeOffsets( + args: DatetimeOffsetsCommandInput, + optionsOrCb?: __HttpHandlerOptions | ((err: any, data?: DatetimeOffsetsCommandOutput) => void), + cb?: (err: any, data?: DatetimeOffsetsCommandOutput) => void + ): Promise | void { + const command = new DatetimeOffsetsCommand(args); + if (typeof optionsOrCb === "function") { + this.send(command, optionsOrCb); + } else if (typeof cb === "function") { + if (typeof optionsOrCb !== "object") throw new Error(`Expect http options but get ${typeof optionsOrCb}`); + this.send(command, optionsOrCb || {}, cb); + } else { + return this.send(command, optionsOrCb); + } + } + /** * This example serializes a document as part of the payload. */ diff --git a/private/aws-protocoltests-restjson/src/RestJsonProtocolClient.ts b/private/aws-protocoltests-restjson/src/RestJsonProtocolClient.ts index 440fb153962be..a504e1d825675 100644 --- a/private/aws-protocoltests-restjson/src/RestJsonProtocolClient.ts +++ b/private/aws-protocoltests-restjson/src/RestJsonProtocolClient.ts @@ -63,6 +63,7 @@ import { ConstantQueryStringCommandInput, ConstantQueryStringCommandOutput, } from "./commands/ConstantQueryStringCommand"; +import { DatetimeOffsetsCommandInput, DatetimeOffsetsCommandOutput } from "./commands/DatetimeOffsetsCommand"; import { DocumentTypeAsPayloadCommandInput, DocumentTypeAsPayloadCommandOutput, @@ -291,6 +292,7 @@ export type ServiceInputTypes = | AllQueryStringTypesCommandInput | ConstantAndVariableQueryStringCommandInput | ConstantQueryStringCommandInput + | DatetimeOffsetsCommandInput | DocumentTypeAsPayloadCommandInput | DocumentTypeCommandInput | EmptyInputAndEmptyOutputCommandInput @@ -380,6 +382,7 @@ export type ServiceOutputTypes = | AllQueryStringTypesCommandOutput | ConstantAndVariableQueryStringCommandOutput | ConstantQueryStringCommandOutput + | DatetimeOffsetsCommandOutput | DocumentTypeAsPayloadCommandOutput | DocumentTypeCommandOutput | EmptyInputAndEmptyOutputCommandOutput diff --git a/private/aws-protocoltests-restjson/src/commands/DatetimeOffsetsCommand.ts b/private/aws-protocoltests-restjson/src/commands/DatetimeOffsetsCommand.ts new file mode 100644 index 0000000000000..8a465fd71b4eb --- /dev/null +++ b/private/aws-protocoltests-restjson/src/commands/DatetimeOffsetsCommand.ts @@ -0,0 +1,79 @@ +// smithy-typescript generated code +import { getSerdePlugin } from "@aws-sdk/middleware-serde"; +import { HttpRequest as __HttpRequest, HttpResponse as __HttpResponse } from "@aws-sdk/protocol-http"; +import { Command as $Command } from "@aws-sdk/smithy-client"; +import { + FinalizeHandlerArguments, + Handler, + HandlerExecutionContext, + HttpHandlerOptions as __HttpHandlerOptions, + MetadataBearer as __MetadataBearer, + MiddlewareStack, + SerdeContext as __SerdeContext, +} from "@aws-sdk/types"; + +import { DatetimeOffsetsOutput, DatetimeOffsetsOutputFilterSensitiveLog } from "../models/models_0"; +import { + deserializeAws_restJson1DatetimeOffsetsCommand, + serializeAws_restJson1DatetimeOffsetsCommand, +} from "../protocols/Aws_restJson1"; +import { RestJsonProtocolClientResolvedConfig, ServiceInputTypes, ServiceOutputTypes } from "../RestJsonProtocolClient"; + +export interface DatetimeOffsetsCommandInput {} +export interface DatetimeOffsetsCommandOutput extends DatetimeOffsetsOutput, __MetadataBearer {} + +export class DatetimeOffsetsCommand extends $Command< + DatetimeOffsetsCommandInput, + DatetimeOffsetsCommandOutput, + RestJsonProtocolClientResolvedConfig +> { + // Start section: command_properties + // End section: command_properties + + constructor(readonly input: DatetimeOffsetsCommandInput) { + // Start section: command_constructor + super(); + // End section: command_constructor + } + + /** + * @internal + */ + resolveMiddleware( + clientStack: MiddlewareStack, + configuration: RestJsonProtocolClientResolvedConfig, + options?: __HttpHandlerOptions + ): Handler { + this.middlewareStack.use(getSerdePlugin(configuration, this.serialize, this.deserialize)); + + const stack = clientStack.concat(this.middlewareStack); + + const { logger } = configuration; + const clientName = "RestJsonProtocolClient"; + const commandName = "DatetimeOffsetsCommand"; + const handlerExecutionContext: HandlerExecutionContext = { + logger, + clientName, + commandName, + inputFilterSensitiveLog: (input: any) => input, + outputFilterSensitiveLog: DatetimeOffsetsOutputFilterSensitiveLog, + }; + const { requestHandler } = configuration; + return stack.resolve( + (request: FinalizeHandlerArguments) => + requestHandler.handle(request.request as __HttpRequest, options || {}), + handlerExecutionContext + ); + } + + private serialize(input: DatetimeOffsetsCommandInput, context: __SerdeContext): Promise<__HttpRequest> { + return serializeAws_restJson1DatetimeOffsetsCommand(input, context); + } + + private deserialize(output: __HttpResponse, context: __SerdeContext): Promise { + return deserializeAws_restJson1DatetimeOffsetsCommand(output, context); + } + + // Start section: command_body_extra + // End section: command_body_extra +} diff --git a/private/aws-protocoltests-restjson/src/commands/index.ts b/private/aws-protocoltests-restjson/src/commands/index.ts index 52a3deb1d2fec..fc59cee8ccff2 100644 --- a/private/aws-protocoltests-restjson/src/commands/index.ts +++ b/private/aws-protocoltests-restjson/src/commands/index.ts @@ -2,6 +2,7 @@ export * from "./AllQueryStringTypesCommand"; export * from "./ConstantAndVariableQueryStringCommand"; export * from "./ConstantQueryStringCommand"; +export * from "./DatetimeOffsetsCommand"; export * from "./DocumentTypeAsPayloadCommand"; export * from "./DocumentTypeCommand"; export * from "./EmptyInputAndEmptyOutputCommand"; diff --git a/private/aws-protocoltests-restjson/src/models/models_0.ts b/private/aws-protocoltests-restjson/src/models/models_0.ts index 03e22babd95c2..65a4d50562a41 100644 --- a/private/aws-protocoltests-restjson/src/models/models_0.ts +++ b/private/aws-protocoltests-restjson/src/models/models_0.ts @@ -125,6 +125,17 @@ export const ConstantQueryStringInputFilterSensitiveLog = (obj: ConstantQueryStr ...obj, }); +export interface DatetimeOffsetsOutput { + datetime?: Date; +} + +/** + * @internal + */ +export const DatetimeOffsetsOutputFilterSensitiveLog = (obj: DatetimeOffsetsOutput): any => ({ + ...obj, +}); + export interface DocumentTypeInputOutput { stringValue?: string; documentValue?: __DocumentType; diff --git a/private/aws-protocoltests-restjson/src/protocols/Aws_restJson1.ts b/private/aws-protocoltests-restjson/src/protocols/Aws_restJson1.ts index 188e5a297c50f..d8cf72f259fcd 100644 --- a/private/aws-protocoltests-restjson/src/protocols/Aws_restJson1.ts +++ b/private/aws-protocoltests-restjson/src/protocols/Aws_restJson1.ts @@ -59,6 +59,7 @@ import { ConstantQueryStringCommandInput, ConstantQueryStringCommandOutput, } from "../commands/ConstantQueryStringCommand"; +import { DatetimeOffsetsCommandInput, DatetimeOffsetsCommandOutput } from "../commands/DatetimeOffsetsCommand"; import { DocumentTypeAsPayloadCommandInput, DocumentTypeAsPayloadCommandOutput, @@ -435,6 +436,28 @@ export const serializeAws_restJson1ConstantQueryStringCommand = async ( }); }; +export const serializeAws_restJson1DatetimeOffsetsCommand = async ( + input: DatetimeOffsetsCommandInput, + context: __SerdeContext +): Promise<__HttpRequest> => { + const { hostname, protocol = "https", port, path: basePath } = await context.endpoint(); + const headers: any = { + "content-type": "application/json", + }; + const resolvedPath = `${basePath?.endsWith("/") ? basePath.slice(0, -1) : basePath || ""}` + "/DatetimeOffsets"; + let body: any; + body = ""; + return new __HttpRequest({ + protocol, + hostname, + port, + method: "POST", + headers, + path: resolvedPath, + body, + }); +}; + export const serializeAws_restJson1DocumentTypeCommand = async ( input: DocumentTypeCommandInput, context: __SerdeContext @@ -2952,6 +2975,41 @@ const deserializeAws_restJson1ConstantQueryStringCommandError = async ( }); }; +export const deserializeAws_restJson1DatetimeOffsetsCommand = async ( + output: __HttpResponse, + context: __SerdeContext +): Promise => { + if (output.statusCode !== 200 && output.statusCode >= 300) { + return deserializeAws_restJson1DatetimeOffsetsCommandError(output, context); + } + const contents: any = map({ + $metadata: deserializeMetadata(output), + }); + const data: Record = __expectNonNull(__expectObject(await parseBody(output.body, context)), "body"); + if (data.datetime != null) { + contents.datetime = __expectNonNull(__parseRfc3339DateTimeWithOffset(data.datetime)); + } + return contents; +}; + +const deserializeAws_restJson1DatetimeOffsetsCommandError = async ( + output: __HttpResponse, + context: __SerdeContext +): Promise => { + const parsedOutput: any = { + ...output, + body: await parseErrorBody(output.body, context), + }; + const errorCode = loadRestJsonErrorCode(output, parsedOutput.body); + const parsedBody = parsedOutput.body; + throwDefaultError({ + output, + parsedBody, + exceptionCtor: __BaseException, + errorCode, + }); +}; + export const deserializeAws_restJson1DocumentTypeCommand = async ( output: __HttpResponse, context: __SerdeContext diff --git a/private/aws-protocoltests-restjson/test/functional/restjson1.spec.ts b/private/aws-protocoltests-restjson/test/functional/restjson1.spec.ts index 7ac0c2179da7f..eeb821b077abc 100644 --- a/private/aws-protocoltests-restjson/test/functional/restjson1.spec.ts +++ b/private/aws-protocoltests-restjson/test/functional/restjson1.spec.ts @@ -8,6 +8,7 @@ import { Readable } from "stream"; import { AllQueryStringTypesCommand } from "../../src/commands/AllQueryStringTypesCommand"; import { ConstantAndVariableQueryStringCommand } from "../../src/commands/ConstantAndVariableQueryStringCommand"; import { ConstantQueryStringCommand } from "../../src/commands/ConstantQueryStringCommand"; +import { DatetimeOffsetsCommand } from "../../src/commands/DatetimeOffsetsCommand"; import { DocumentTypeAsPayloadCommand } from "../../src/commands/DocumentTypeAsPayloadCommand"; import { DocumentTypeCommand } from "../../src/commands/DocumentTypeCommand"; import { EmptyInputAndEmptyOutputCommand } from "../../src/commands/EmptyInputAndEmptyOutputCommand"; @@ -269,6 +270,48 @@ it("RestJsonAllQueryStringTypes:Request", async () => { 3, ], + + queryParamsMapOfStringList: { + String: ["Hello there"], + + StringList: ["a", "b", "c"], + + StringSet: ["a", "b", "c"], + + Byte: ["1"], + + Short: ["2"], + + Integer: ["3"], + + IntegerList: ["1", "2", "3"], + + IntegerSet: ["1", "2", "3"], + + Long: ["4"], + + Float: ["1.1"], + + Double: ["1.1"], + + DoubleList: ["1.1", "2.1", "3.1"], + + Boolean: ["true"], + + BooleanList: ["true", "false", "true"], + + Timestamp: ["1970-01-01T00:00:01Z"], + + TimestampList: ["1970-01-01T00:00:01Z", "1970-01-01T00:00:02Z", "1970-01-01T00:00:03Z"], + + Enum: ["Foo"], + + EnumList: ["Foo", "Baz", "Bar"], + + IntegerEnum: ["1"], + + IntegerEnumList: ["1", "2", "3"], + } as any, } as any); try { await client.send(command); @@ -375,6 +418,10 @@ it("RestJsonQueryStringEscaping:Request", async () => { const command = new AllQueryStringTypesCommand({ queryString: "%:/?#[]@!$&'()*+,;=😹", + + queryParamsMapOfStringList: { + String: ["%:/?#[]@!$&'()*+,;=😹"], + } as any, } as any); try { await client.send(command); @@ -623,6 +670,84 @@ it("RestJsonConstantQueryString:Request", async () => { } }); +/** + * Ensures that clients can correctly parse datetime (timestamps) with offsets + */ +it("RestJsonDateTimeWithNegativeOffset:Response", async () => { + const client = new RestJsonProtocolClient({ + ...clientParams, + requestHandler: new ResponseDeserializationTestHandler( + true, + 200, + undefined, + ` { + "datetime": "2019-12-16T22:48:18-01:00" + } + ` + ), + }); + + const params: any = {}; + const command = new DatetimeOffsetsCommand(params); + + let r: any; + try { + r = await client.send(command); + } catch (err) { + fail("Expected a valid response to be returned, got " + err); + return; + } + expect(r["$metadata"].httpStatusCode).toBe(200); + const paramsToValidate: any = [ + { + datetime: new Date(1576540098000), + }, + ][0]; + Object.keys(paramsToValidate).forEach((param) => { + expect(r[param]).toBeDefined(); + expect(equivalentContents(r[param], paramsToValidate[param])).toBe(true); + }); +}); + +/** + * Ensures that clients can correctly parse datetime (timestamps) with offsets + */ +it("RestJsonDateTimeWithPositiveOffset:Response", async () => { + const client = new RestJsonProtocolClient({ + ...clientParams, + requestHandler: new ResponseDeserializationTestHandler( + true, + 200, + undefined, + ` { + "datetime": "2019-12-17T00:48:18+01:00" + } + ` + ), + }); + + const params: any = {}; + const command = new DatetimeOffsetsCommand(params); + + let r: any; + try { + r = await client.send(command); + } catch (err) { + fail("Expected a valid response to be returned, got " + err); + return; + } + expect(r["$metadata"].httpStatusCode).toBe(200); + const paramsToValidate: any = [ + { + datetime: new Date(1576540098000), + }, + ][0]; + Object.keys(paramsToValidate).forEach((param) => { + expect(r[param]).toBeDefined(); + expect(equivalentContents(r[param], paramsToValidate[param])).toBe(true); + }); +}); + /** * Serializes document types as part of the JSON request payload with no escaping. */ diff --git a/private/aws-protocoltests-restxml/src/RestXmlProtocol.ts b/private/aws-protocoltests-restxml/src/RestXmlProtocol.ts index bfe22c62016f4..bdec5e9ca743d 100644 --- a/private/aws-protocoltests-restxml/src/RestXmlProtocol.ts +++ b/private/aws-protocoltests-restxml/src/RestXmlProtocol.ts @@ -21,6 +21,11 @@ import { ConstantQueryStringCommandInput, ConstantQueryStringCommandOutput, } from "./commands/ConstantQueryStringCommand"; +import { + DatetimeOffsetsCommand, + DatetimeOffsetsCommandInput, + DatetimeOffsetsCommandOutput, +} from "./commands/DatetimeOffsetsCommand"; import { EmptyInputAndEmptyOutputCommand, EmptyInputAndEmptyOutputCommandInput, @@ -387,6 +392,35 @@ export class RestXmlProtocol extends RestXmlProtocolClient { } } + public datetimeOffsets( + args: DatetimeOffsetsCommandInput, + options?: __HttpHandlerOptions + ): Promise; + public datetimeOffsets( + args: DatetimeOffsetsCommandInput, + cb: (err: any, data?: DatetimeOffsetsCommandOutput) => void + ): void; + public datetimeOffsets( + args: DatetimeOffsetsCommandInput, + options: __HttpHandlerOptions, + cb: (err: any, data?: DatetimeOffsetsCommandOutput) => void + ): void; + public datetimeOffsets( + args: DatetimeOffsetsCommandInput, + optionsOrCb?: __HttpHandlerOptions | ((err: any, data?: DatetimeOffsetsCommandOutput) => void), + cb?: (err: any, data?: DatetimeOffsetsCommandOutput) => void + ): Promise | void { + const command = new DatetimeOffsetsCommand(args); + if (typeof optionsOrCb === "function") { + this.send(command, optionsOrCb); + } else if (typeof cb === "function") { + if (typeof optionsOrCb !== "object") throw new Error(`Expect http options but get ${typeof optionsOrCb}`); + this.send(command, optionsOrCb || {}, cb); + } else { + return this.send(command, optionsOrCb); + } + } + /** * The example tests how requests and responses are serialized when there's * no request or response payload because the operation has an empty input diff --git a/private/aws-protocoltests-restxml/src/RestXmlProtocolClient.ts b/private/aws-protocoltests-restxml/src/RestXmlProtocolClient.ts index 724304dcd233b..6bef91c1a971e 100644 --- a/private/aws-protocoltests-restxml/src/RestXmlProtocolClient.ts +++ b/private/aws-protocoltests-restxml/src/RestXmlProtocolClient.ts @@ -61,6 +61,7 @@ import { ConstantQueryStringCommandInput, ConstantQueryStringCommandOutput, } from "./commands/ConstantQueryStringCommand"; +import { DatetimeOffsetsCommandInput, DatetimeOffsetsCommandOutput } from "./commands/DatetimeOffsetsCommand"; import { EmptyInputAndEmptyOutputCommandInput, EmptyInputAndEmptyOutputCommandOutput, @@ -193,6 +194,7 @@ export type ServiceInputTypes = | BodyWithXmlNameCommandInput | ConstantAndVariableQueryStringCommandInput | ConstantQueryStringCommandInput + | DatetimeOffsetsCommandInput | EmptyInputAndEmptyOutputCommandInput | EndpointOperationCommandInput | EndpointWithHostLabelHeaderOperationCommandInput @@ -249,6 +251,7 @@ export type ServiceOutputTypes = | BodyWithXmlNameCommandOutput | ConstantAndVariableQueryStringCommandOutput | ConstantQueryStringCommandOutput + | DatetimeOffsetsCommandOutput | EmptyInputAndEmptyOutputCommandOutput | EndpointOperationCommandOutput | EndpointWithHostLabelHeaderOperationCommandOutput diff --git a/private/aws-protocoltests-restxml/src/commands/DatetimeOffsetsCommand.ts b/private/aws-protocoltests-restxml/src/commands/DatetimeOffsetsCommand.ts new file mode 100644 index 0000000000000..c02157233040f --- /dev/null +++ b/private/aws-protocoltests-restxml/src/commands/DatetimeOffsetsCommand.ts @@ -0,0 +1,79 @@ +// smithy-typescript generated code +import { getSerdePlugin } from "@aws-sdk/middleware-serde"; +import { HttpRequest as __HttpRequest, HttpResponse as __HttpResponse } from "@aws-sdk/protocol-http"; +import { Command as $Command } from "@aws-sdk/smithy-client"; +import { + FinalizeHandlerArguments, + Handler, + HandlerExecutionContext, + HttpHandlerOptions as __HttpHandlerOptions, + MetadataBearer as __MetadataBearer, + MiddlewareStack, + SerdeContext as __SerdeContext, +} from "@aws-sdk/types"; + +import { DatetimeOffsetsOutput, DatetimeOffsetsOutputFilterSensitiveLog } from "../models/models_0"; +import { + deserializeAws_restXmlDatetimeOffsetsCommand, + serializeAws_restXmlDatetimeOffsetsCommand, +} from "../protocols/Aws_restXml"; +import { RestXmlProtocolClientResolvedConfig, ServiceInputTypes, ServiceOutputTypes } from "../RestXmlProtocolClient"; + +export interface DatetimeOffsetsCommandInput {} +export interface DatetimeOffsetsCommandOutput extends DatetimeOffsetsOutput, __MetadataBearer {} + +export class DatetimeOffsetsCommand extends $Command< + DatetimeOffsetsCommandInput, + DatetimeOffsetsCommandOutput, + RestXmlProtocolClientResolvedConfig +> { + // Start section: command_properties + // End section: command_properties + + constructor(readonly input: DatetimeOffsetsCommandInput) { + // Start section: command_constructor + super(); + // End section: command_constructor + } + + /** + * @internal + */ + resolveMiddleware( + clientStack: MiddlewareStack, + configuration: RestXmlProtocolClientResolvedConfig, + options?: __HttpHandlerOptions + ): Handler { + this.middlewareStack.use(getSerdePlugin(configuration, this.serialize, this.deserialize)); + + const stack = clientStack.concat(this.middlewareStack); + + const { logger } = configuration; + const clientName = "RestXmlProtocolClient"; + const commandName = "DatetimeOffsetsCommand"; + const handlerExecutionContext: HandlerExecutionContext = { + logger, + clientName, + commandName, + inputFilterSensitiveLog: (input: any) => input, + outputFilterSensitiveLog: DatetimeOffsetsOutputFilterSensitiveLog, + }; + const { requestHandler } = configuration; + return stack.resolve( + (request: FinalizeHandlerArguments) => + requestHandler.handle(request.request as __HttpRequest, options || {}), + handlerExecutionContext + ); + } + + private serialize(input: DatetimeOffsetsCommandInput, context: __SerdeContext): Promise<__HttpRequest> { + return serializeAws_restXmlDatetimeOffsetsCommand(input, context); + } + + private deserialize(output: __HttpResponse, context: __SerdeContext): Promise { + return deserializeAws_restXmlDatetimeOffsetsCommand(output, context); + } + + // Start section: command_body_extra + // End section: command_body_extra +} diff --git a/private/aws-protocoltests-restxml/src/commands/index.ts b/private/aws-protocoltests-restxml/src/commands/index.ts index 9ede05312de79..717d876947b0e 100644 --- a/private/aws-protocoltests-restxml/src/commands/index.ts +++ b/private/aws-protocoltests-restxml/src/commands/index.ts @@ -3,6 +3,7 @@ export * from "./AllQueryStringTypesCommand"; export * from "./BodyWithXmlNameCommand"; export * from "./ConstantAndVariableQueryStringCommand"; export * from "./ConstantQueryStringCommand"; +export * from "./DatetimeOffsetsCommand"; export * from "./EmptyInputAndEmptyOutputCommand"; export * from "./EndpointOperationCommand"; export * from "./EndpointWithHostLabelHeaderOperationCommand"; diff --git a/private/aws-protocoltests-restxml/src/models/models_0.ts b/private/aws-protocoltests-restxml/src/models/models_0.ts index 264ec8f519139..bdb19383655e2 100644 --- a/private/aws-protocoltests-restxml/src/models/models_0.ts +++ b/private/aws-protocoltests-restxml/src/models/models_0.ts @@ -142,6 +142,17 @@ export const ConstantQueryStringInputFilterSensitiveLog = (obj: ConstantQueryStr ...obj, }); +export interface DatetimeOffsetsOutput { + datetime?: Date; +} + +/** + * @internal + */ +export const DatetimeOffsetsOutputFilterSensitiveLog = (obj: DatetimeOffsetsOutput): any => ({ + ...obj, +}); + export interface EmptyInputAndEmptyOutputInput {} /** diff --git a/private/aws-protocoltests-restxml/src/protocols/Aws_restXml.ts b/private/aws-protocoltests-restxml/src/protocols/Aws_restXml.ts index 06f3dedeafe3f..d72524bec7520 100644 --- a/private/aws-protocoltests-restxml/src/protocols/Aws_restXml.ts +++ b/private/aws-protocoltests-restxml/src/protocols/Aws_restXml.ts @@ -52,6 +52,7 @@ import { ConstantQueryStringCommandInput, ConstantQueryStringCommandOutput, } from "../commands/ConstantQueryStringCommand"; +import { DatetimeOffsetsCommandInput, DatetimeOffsetsCommandOutput } from "../commands/DatetimeOffsetsCommand"; import { EmptyInputAndEmptyOutputCommandInput, EmptyInputAndEmptyOutputCommandOutput, @@ -357,6 +358,28 @@ export const serializeAws_restXmlConstantQueryStringCommand = async ( }); }; +export const serializeAws_restXmlDatetimeOffsetsCommand = async ( + input: DatetimeOffsetsCommandInput, + context: __SerdeContext +): Promise<__HttpRequest> => { + const { hostname, protocol = "https", port, path: basePath } = await context.endpoint(); + const headers: any = { + "content-type": "application/xml", + }; + const resolvedPath = `${basePath?.endsWith("/") ? basePath.slice(0, -1) : basePath || ""}` + "/DatetimeOffsets"; + let body: any; + body = ""; + return new __HttpRequest({ + protocol, + hostname, + port, + method: "POST", + headers, + path: resolvedPath, + body, + }); +}; + export const serializeAws_restXmlEmptyInputAndEmptyOutputCommand = async ( input: EmptyInputAndEmptyOutputCommandInput, context: __SerdeContext @@ -2385,6 +2408,41 @@ const deserializeAws_restXmlConstantQueryStringCommandError = async ( }); }; +export const deserializeAws_restXmlDatetimeOffsetsCommand = async ( + output: __HttpResponse, + context: __SerdeContext +): Promise => { + if (output.statusCode !== 200 && output.statusCode >= 300) { + return deserializeAws_restXmlDatetimeOffsetsCommandError(output, context); + } + const contents: any = map({ + $metadata: deserializeMetadata(output), + }); + const data: Record = __expectNonNull(__expectObject(await parseBody(output.body, context)), "body"); + if (data["datetime"] !== undefined) { + contents.datetime = __expectNonNull(__parseRfc3339DateTimeWithOffset(data["datetime"])); + } + return contents; +}; + +const deserializeAws_restXmlDatetimeOffsetsCommandError = async ( + output: __HttpResponse, + context: __SerdeContext +): Promise => { + const parsedOutput: any = { + ...output, + body: await parseErrorBody(output.body, context), + }; + const errorCode = loadRestXmlErrorCode(output, parsedOutput.body); + const parsedBody = parsedOutput.body; + throwDefaultError({ + output, + parsedBody: parsedBody.Error, + exceptionCtor: __BaseException, + errorCode, + }); +}; + export const deserializeAws_restXmlEmptyInputAndEmptyOutputCommand = async ( output: __HttpResponse, context: __SerdeContext diff --git a/private/aws-protocoltests-restxml/test/functional/restxml.spec.ts b/private/aws-protocoltests-restxml/test/functional/restxml.spec.ts index 9c7beae6c5237..87f8471539a9e 100644 --- a/private/aws-protocoltests-restxml/test/functional/restxml.spec.ts +++ b/private/aws-protocoltests-restxml/test/functional/restxml.spec.ts @@ -11,6 +11,7 @@ import { AllQueryStringTypesCommand } from "../../src/commands/AllQueryStringTyp import { BodyWithXmlNameCommand } from "../../src/commands/BodyWithXmlNameCommand"; import { ConstantAndVariableQueryStringCommand } from "../../src/commands/ConstantAndVariableQueryStringCommand"; import { ConstantQueryStringCommand } from "../../src/commands/ConstantQueryStringCommand"; +import { DatetimeOffsetsCommand } from "../../src/commands/DatetimeOffsetsCommand"; import { EmptyInputAndEmptyOutputCommand } from "../../src/commands/EmptyInputAndEmptyOutputCommand"; import { EndpointOperationCommand } from "../../src/commands/EndpointOperationCommand"; import { EndpointWithHostLabelHeaderOperationCommand } from "../../src/commands/EndpointWithHostLabelHeaderOperationCommand"; @@ -650,6 +651,88 @@ it("ConstantQueryString:Request", async () => { } }); +/** + * Ensures that clients can correctly parse datetime (timestamps) with offsets + */ +it("RestXmlDateTimeWithNegativeOffset:Response", async () => { + const client = new RestXmlProtocolClient({ + ...clientParams, + requestHandler: new ResponseDeserializationTestHandler( + true, + 200, + { + "content-type": "application/xml", + }, + ` + 2019-12-16T22:48:18-01:00 + + ` + ), + }); + + const params: any = {}; + const command = new DatetimeOffsetsCommand(params); + + let r: any; + try { + r = await client.send(command); + } catch (err) { + fail("Expected a valid response to be returned, got " + err); + return; + } + expect(r["$metadata"].httpStatusCode).toBe(200); + const paramsToValidate: any = [ + { + datetime: new Date(1576540098000), + }, + ][0]; + Object.keys(paramsToValidate).forEach((param) => { + expect(r[param]).toBeDefined(); + expect(equivalentContents(r[param], paramsToValidate[param])).toBe(true); + }); +}); + +/** + * Ensures that clients can correctly parse datetime (timestamps) with offsets + */ +it("RestXmlDateTimeWithPositiveOffset:Response", async () => { + const client = new RestXmlProtocolClient({ + ...clientParams, + requestHandler: new ResponseDeserializationTestHandler( + true, + 200, + { + "content-type": "application/xml", + }, + ` + 2019-12-17T00:48:18+01:00 + + ` + ), + }); + + const params: any = {}; + const command = new DatetimeOffsetsCommand(params); + + let r: any; + try { + r = await client.send(command); + } catch (err) { + fail("Expected a valid response to be returned, got " + err); + return; + } + expect(r["$metadata"].httpStatusCode).toBe(200); + const paramsToValidate: any = [ + { + datetime: new Date(1576540098000), + }, + ][0]; + Object.keys(paramsToValidate).forEach((param) => { + expect(r[param]).toBeDefined(); + expect(equivalentContents(r[param], paramsToValidate[param])).toBe(true); + }); +}); + /** * Empty input serializes no payload */ diff --git a/private/aws-restjson-server/src/models/models_0.ts b/private/aws-restjson-server/src/models/models_0.ts index 274b3d980e930..ace4e0591236e 100644 --- a/private/aws-restjson-server/src/models/models_0.ts +++ b/private/aws-restjson-server/src/models/models_0.ts @@ -40,7 +40,7 @@ export namespace GreetingStruct { export const validate = (obj: GreetingStruct, path = ""): __ValidationFailure[] => { function getMemberValidator( member: T - ): NonNullable<(typeof memberValidators)[T]> { + ): NonNullable { if (memberValidators[member] === undefined) { switch (member) { case "hi": { @@ -129,7 +129,7 @@ export namespace AllQueryStringTypesInput { export const validate = (obj: AllQueryStringTypesInput, path = ""): __ValidationFailure[] => { function getMemberValidator( member: T - ): NonNullable<(typeof memberValidators)[T]> { + ): NonNullable { if (memberValidators[member] === undefined) { switch (member) { case "queryString": { @@ -304,7 +304,7 @@ export namespace ComplexNestedErrorData { export const validate = (obj: ComplexNestedErrorData, path = ""): __ValidationFailure[] => { function getMemberValidator( member: T - ): NonNullable<(typeof memberValidators)[T]> { + ): NonNullable { if (memberValidators[member] === undefined) { switch (member) { case "Foo": { @@ -365,7 +365,7 @@ export namespace ConstantAndVariableQueryStringInput { export const validate = (obj: ConstantAndVariableQueryStringInput, path = ""): __ValidationFailure[] => { function getMemberValidator( member: T - ): NonNullable<(typeof memberValidators)[T]> { + ): NonNullable { if (memberValidators[member] === undefined) { switch (member) { case "baz": { @@ -407,7 +407,7 @@ export namespace ConstantQueryStringInput { export const validate = (obj: ConstantQueryStringInput, path = ""): __ValidationFailure[] => { function getMemberValidator( member: T - ): NonNullable<(typeof memberValidators)[T]> { + ): NonNullable { if (memberValidators[member] === undefined) { switch (member) { case "hello": { @@ -422,6 +422,41 @@ export namespace ConstantQueryStringInput { }; } +export interface DatetimeOffsetsOutput { + datetime?: Date; +} + +/** + * @internal + */ +export const DatetimeOffsetsOutputFilterSensitiveLog = (obj: DatetimeOffsetsOutput): any => ({ + ...obj, +}); +export namespace DatetimeOffsetsOutput { + const memberValidators: { + datetime?: __MultiConstraintValidator; + } = {}; + /** + * @internal + */ + export const validate = (obj: DatetimeOffsetsOutput, path = ""): __ValidationFailure[] => { + function getMemberValidator( + member: T + ): NonNullable { + if (memberValidators[member] === undefined) { + switch (member) { + case "datetime": { + memberValidators["datetime"] = new __NoOpValidator(); + break; + } + } + } + return memberValidators[member]!; + } + return [...getMemberValidator("datetime").validate(obj.datetime, `${path}/datetime`)]; + }; +} + export interface DocumentTypeInputOutput { stringValue?: string; documentValue?: __DocumentType; @@ -444,7 +479,7 @@ export namespace DocumentTypeInputOutput { export const validate = (obj: DocumentTypeInputOutput, path = ""): __ValidationFailure[] => { function getMemberValidator( member: T - ): NonNullable<(typeof memberValidators)[T]> { + ): NonNullable { if (memberValidators[member] === undefined) { switch (member) { case "stringValue": { @@ -486,7 +521,7 @@ export namespace DocumentTypeAsPayloadInputOutput { export const validate = (obj: DocumentTypeAsPayloadInputOutput, path = ""): __ValidationFailure[] => { function getMemberValidator( member: T - ): NonNullable<(typeof memberValidators)[T]> { + ): NonNullable { if (memberValidators[member] === undefined) { switch (member) { case "documentValue": { @@ -517,7 +552,7 @@ export namespace EmptyInputAndEmptyOutputInput { export const validate = (obj: EmptyInputAndEmptyOutputInput, path = ""): __ValidationFailure[] => { function getMemberValidator( member: T - ): NonNullable<(typeof memberValidators)[T]> { + ): NonNullable { if (memberValidators[member] === undefined) { switch (member) { } @@ -544,7 +579,7 @@ export namespace EmptyInputAndEmptyOutputOutput { export const validate = (obj: EmptyInputAndEmptyOutputOutput, path = ""): __ValidationFailure[] => { function getMemberValidator( member: T - ): NonNullable<(typeof memberValidators)[T]> { + ): NonNullable { if (memberValidators[member] === undefined) { switch (member) { } @@ -575,7 +610,7 @@ export namespace HostLabelInput { export const validate = (obj: HostLabelInput, path = ""): __ValidationFailure[] => { function getMemberValidator( member: T - ): NonNullable<(typeof memberValidators)[T]> { + ): NonNullable { if (memberValidators[member] === undefined) { switch (member) { case "label": { @@ -614,7 +649,7 @@ export namespace EnumPayloadInput { export const validate = (obj: EnumPayloadInput, path = ""): __ValidationFailure[] => { function getMemberValidator( member: T - ): NonNullable<(typeof memberValidators)[T]> { + ): NonNullable { if (memberValidators[member] === undefined) { switch (member) { case "payload": { @@ -666,7 +701,7 @@ export namespace GreetingWithErrorsOutput { export const validate = (obj: GreetingWithErrorsOutput, path = ""): __ValidationFailure[] => { function getMemberValidator( member: T - ): NonNullable<(typeof memberValidators)[T]> { + ): NonNullable { if (memberValidators[member] === undefined) { switch (member) { case "greeting": { @@ -719,7 +754,7 @@ export namespace HttpChecksumRequiredInputOutput { export const validate = (obj: HttpChecksumRequiredInputOutput, path = ""): __ValidationFailure[] => { function getMemberValidator( member: T - ): NonNullable<(typeof memberValidators)[T]> { + ): NonNullable { if (memberValidators[member] === undefined) { switch (member) { case "foo": { @@ -756,7 +791,7 @@ export namespace HttpPayloadTraitsInputOutput { export const validate = (obj: HttpPayloadTraitsInputOutput, path = ""): __ValidationFailure[] => { function getMemberValidator( member: T - ): NonNullable<(typeof memberValidators)[T]> { + ): NonNullable { if (memberValidators[member] === undefined) { switch (member) { case "foo": { @@ -802,7 +837,7 @@ export namespace HttpPayloadTraitsWithMediaTypeInputOutput { export const validate = (obj: HttpPayloadTraitsWithMediaTypeInputOutput, path = ""): __ValidationFailure[] => { function getMemberValidator( member: T - ): NonNullable<(typeof memberValidators)[T]> { + ): NonNullable { if (memberValidators[member] === undefined) { switch (member) { case "foo": { @@ -846,7 +881,7 @@ export namespace NestedPayload { export const validate = (obj: NestedPayload, path = ""): __ValidationFailure[] => { function getMemberValidator( member: T - ): NonNullable<(typeof memberValidators)[T]> { + ): NonNullable { if (memberValidators[member] === undefined) { switch (member) { case "greeting": { @@ -890,7 +925,7 @@ export namespace HttpPayloadWithStructureInputOutput { export const validate = (obj: HttpPayloadWithStructureInputOutput, path = ""): __ValidationFailure[] => { function getMemberValidator( member: T - ): NonNullable<(typeof memberValidators)[T]> { + ): NonNullable { if (memberValidators[member] === undefined) { switch (member) { case "nested": { @@ -930,7 +965,7 @@ export namespace HttpPrefixHeadersInput { export const validate = (obj: HttpPrefixHeadersInput, path = ""): __ValidationFailure[] => { function getMemberValidator( member: T - ): NonNullable<(typeof memberValidators)[T]> { + ): NonNullable { if (memberValidators[member] === undefined) { switch (member) { case "foo": { @@ -978,7 +1013,7 @@ export namespace HttpPrefixHeadersOutput { export const validate = (obj: HttpPrefixHeadersOutput, path = ""): __ValidationFailure[] => { function getMemberValidator( member: T - ): NonNullable<(typeof memberValidators)[T]> { + ): NonNullable { if (memberValidators[member] === undefined) { switch (member) { case "foo": { @@ -1020,7 +1055,7 @@ export namespace HttpPrefixHeadersInResponseInput { export const validate = (obj: HttpPrefixHeadersInResponseInput, path = ""): __ValidationFailure[] => { function getMemberValidator( member: T - ): NonNullable<(typeof memberValidators)[T]> { + ): NonNullable { if (memberValidators[member] === undefined) { switch (member) { } @@ -1051,7 +1086,7 @@ export namespace HttpPrefixHeadersInResponseOutput { export const validate = (obj: HttpPrefixHeadersInResponseOutput, path = ""): __ValidationFailure[] => { function getMemberValidator( member: T - ): NonNullable<(typeof memberValidators)[T]> { + ): NonNullable { if (memberValidators[member] === undefined) { switch (member) { case "prefixHeaders": { @@ -1092,7 +1127,7 @@ export namespace HttpRequestWithFloatLabelsInput { export const validate = (obj: HttpRequestWithFloatLabelsInput, path = ""): __ValidationFailure[] => { function getMemberValidator( member: T - ): NonNullable<(typeof memberValidators)[T]> { + ): NonNullable { if (memberValidators[member] === undefined) { switch (member) { case "float": { @@ -1138,7 +1173,7 @@ export namespace HttpRequestWithGreedyLabelInPathInput { export const validate = (obj: HttpRequestWithGreedyLabelInPathInput, path = ""): __ValidationFailure[] => { function getMemberValidator( member: T - ): NonNullable<(typeof memberValidators)[T]> { + ): NonNullable { if (memberValidators[member] === undefined) { switch (member) { case "foo": { @@ -1201,7 +1236,7 @@ export namespace HttpRequestWithLabelsInput { export const validate = (obj: HttpRequestWithLabelsInput, path = ""): __ValidationFailure[] => { function getMemberValidator( member: T - ): NonNullable<(typeof memberValidators)[T]> { + ): NonNullable { if (memberValidators[member] === undefined) { switch (member) { case "string": { @@ -1287,7 +1322,7 @@ export namespace HttpRequestWithLabelsAndTimestampFormatInput { export const validate = (obj: HttpRequestWithLabelsAndTimestampFormatInput, path = ""): __ValidationFailure[] => { function getMemberValidator( member: T - ): NonNullable<(typeof memberValidators)[T]> { + ): NonNullable { if (memberValidators[member] === undefined) { switch (member) { case "memberEpochSeconds": { @@ -1354,7 +1389,7 @@ export namespace HttpRequestWithRegexLiteralInput { export const validate = (obj: HttpRequestWithRegexLiteralInput, path = ""): __ValidationFailure[] => { function getMemberValidator( member: T - ): NonNullable<(typeof memberValidators)[T]> { + ): NonNullable { if (memberValidators[member] === undefined) { switch (member) { case "str": { @@ -1389,7 +1424,7 @@ export namespace HttpResponseCodeOutput { export const validate = (obj: HttpResponseCodeOutput, path = ""): __ValidationFailure[] => { function getMemberValidator( member: T - ): NonNullable<(typeof memberValidators)[T]> { + ): NonNullable { if (memberValidators[member] === undefined) { switch (member) { case "Status": { @@ -1424,7 +1459,7 @@ export namespace StringPayloadInput { export const validate = (obj: StringPayloadInput, path = ""): __ValidationFailure[] => { function getMemberValidator( member: T - ): NonNullable<(typeof memberValidators)[T]> { + ): NonNullable { if (memberValidators[member] === undefined) { switch (member) { case "payload": { @@ -1459,7 +1494,7 @@ export namespace IgnoreQueryParamsInResponseOutput { export const validate = (obj: IgnoreQueryParamsInResponseOutput, path = ""): __ValidationFailure[] => { function getMemberValidator( member: T - ): NonNullable<(typeof memberValidators)[T]> { + ): NonNullable { if (memberValidators[member] === undefined) { switch (member) { case "baz": { @@ -1528,7 +1563,7 @@ export namespace InputAndOutputWithHeadersIO { export const validate = (obj: InputAndOutputWithHeadersIO, path = ""): __ValidationFailure[] => { function getMemberValidator( member: T - ): NonNullable<(typeof memberValidators)[T]> { + ): NonNullable { if (memberValidators[member] === undefined) { switch (member) { case "headerString": { @@ -1678,7 +1713,7 @@ export namespace JsonBlobsInputOutput { export const validate = (obj: JsonBlobsInputOutput, path = ""): __ValidationFailure[] => { function getMemberValidator( member: T - ): NonNullable<(typeof memberValidators)[T]> { + ): NonNullable { if (memberValidators[member] === undefined) { switch (member) { case "data": { @@ -1723,7 +1758,7 @@ export namespace JsonEnumsInputOutput { export const validate = (obj: JsonEnumsInputOutput, path = ""): __ValidationFailure[] => { function getMemberValidator( member: T - ): NonNullable<(typeof memberValidators)[T]> { + ): NonNullable { if (memberValidators[member] === undefined) { switch (member) { case "fooEnum1": { @@ -1811,7 +1846,7 @@ export namespace JsonIntEnumsInputOutput { export const validate = (obj: JsonIntEnumsInputOutput, path = ""): __ValidationFailure[] => { function getMemberValidator( member: T - ): NonNullable<(typeof memberValidators)[T]> { + ): NonNullable { if (memberValidators[member] === undefined) { switch (member) { case "integerEnum1": { @@ -1891,7 +1926,7 @@ export namespace StructureListMember { export const validate = (obj: StructureListMember, path = ""): __ValidationFailure[] => { function getMemberValidator( member: T - ): NonNullable<(typeof memberValidators)[T]> { + ): NonNullable { if (memberValidators[member] === undefined) { switch (member) { case "a": { @@ -1955,7 +1990,7 @@ export namespace JsonListsInputOutput { export const validate = (obj: JsonListsInputOutput, path = ""): __ValidationFailure[] => { function getMemberValidator( member: T - ): NonNullable<(typeof memberValidators)[T]> { + ): NonNullable { if (memberValidators[member] === undefined) { switch (member) { case "stringList": { @@ -2088,7 +2123,7 @@ export namespace JsonMapsInputOutput { export const validate = (obj: JsonMapsInputOutput, path = ""): __ValidationFailure[] => { function getMemberValidator( member: T - ): NonNullable<(typeof memberValidators)[T]> { + ): NonNullable { if (memberValidators[member] === undefined) { switch (member) { case "denseStructMap": { @@ -2228,7 +2263,7 @@ export namespace JsonTimestampsInputOutput { export const validate = (obj: JsonTimestampsInputOutput, path = ""): __ValidationFailure[] => { function getMemberValidator( member: T - ): NonNullable<(typeof memberValidators)[T]> { + ): NonNullable { if (memberValidators[member] === undefined) { switch (member) { case "normal": { @@ -2295,7 +2330,7 @@ export namespace RenamedGreeting { export const validate = (obj: RenamedGreeting, path = ""): __ValidationFailure[] => { function getMemberValidator( member: T - ): NonNullable<(typeof memberValidators)[T]> { + ): NonNullable { if (memberValidators[member] === undefined) { switch (member) { case "salutation": { @@ -2527,7 +2562,7 @@ export namespace MyUnion { export const validate = (obj: MyUnion, path = ""): __ValidationFailure[] => { function getMemberValidator( member: T - ): NonNullable<(typeof memberValidators)[T]> { + ): NonNullable { if (memberValidators[member] === undefined) { switch (member) { case "stringValue": { @@ -2651,7 +2686,7 @@ export namespace UnionInputOutput { export const validate = (obj: UnionInputOutput, path = ""): __ValidationFailure[] => { function getMemberValidator( member: T - ): NonNullable<(typeof memberValidators)[T]> { + ): NonNullable { if (memberValidators[member] === undefined) { switch (member) { case "contents": { @@ -2691,7 +2726,7 @@ export namespace MalformedAcceptWithGenericStringOutput { export const validate = (obj: MalformedAcceptWithGenericStringOutput, path = ""): __ValidationFailure[] => { function getMemberValidator( member: T - ): NonNullable<(typeof memberValidators)[T]> { + ): NonNullable { if (memberValidators[member] === undefined) { switch (member) { case "payload": { @@ -2726,7 +2761,7 @@ export namespace MalformedAcceptWithPayloadOutput { export const validate = (obj: MalformedAcceptWithPayloadOutput, path = ""): __ValidationFailure[] => { function getMemberValidator( member: T - ): NonNullable<(typeof memberValidators)[T]> { + ): NonNullable { if (memberValidators[member] === undefined) { switch (member) { case "payload": { @@ -2761,7 +2796,7 @@ export namespace MalformedBlobInput { export const validate = (obj: MalformedBlobInput, path = ""): __ValidationFailure[] => { function getMemberValidator( member: T - ): NonNullable<(typeof memberValidators)[T]> { + ): NonNullable { if (memberValidators[member] === undefined) { switch (member) { case "blob": { @@ -2802,7 +2837,7 @@ export namespace MalformedBooleanInput { export const validate = (obj: MalformedBooleanInput, path = ""): __ValidationFailure[] => { function getMemberValidator( member: T - ): NonNullable<(typeof memberValidators)[T]> { + ): NonNullable { if (memberValidators[member] === undefined) { switch (member) { case "booleanInBody": { @@ -2860,7 +2895,7 @@ export namespace MalformedByteInput { export const validate = (obj: MalformedByteInput, path = ""): __ValidationFailure[] => { function getMemberValidator( member: T - ): NonNullable<(typeof memberValidators)[T]> { + ): NonNullable { if (memberValidators[member] === undefined) { switch (member) { case "byteInBody": { @@ -2914,7 +2949,7 @@ export namespace MalformedContentTypeWithGenericStringInput { export const validate = (obj: MalformedContentTypeWithGenericStringInput, path = ""): __ValidationFailure[] => { function getMemberValidator( member: T - ): NonNullable<(typeof memberValidators)[T]> { + ): NonNullable { if (memberValidators[member] === undefined) { switch (member) { case "payload": { @@ -2951,7 +2986,7 @@ export namespace MalformedContentTypeWithPayloadInput { export const validate = (obj: MalformedContentTypeWithPayloadInput, path = ""): __ValidationFailure[] => { function getMemberValidator( member: T - ): NonNullable<(typeof memberValidators)[T]> { + ): NonNullable { if (memberValidators[member] === undefined) { switch (member) { case "payload": { @@ -2992,7 +3027,7 @@ export namespace MalformedDoubleInput { export const validate = (obj: MalformedDoubleInput, path = ""): __ValidationFailure[] => { function getMemberValidator( member: T - ): NonNullable<(typeof memberValidators)[T]> { + ): NonNullable { if (memberValidators[member] === undefined) { switch (member) { case "doubleInBody": { @@ -3050,7 +3085,7 @@ export namespace MalformedFloatInput { export const validate = (obj: MalformedFloatInput, path = ""): __ValidationFailure[] => { function getMemberValidator( member: T - ): NonNullable<(typeof memberValidators)[T]> { + ): NonNullable { if (memberValidators[member] === undefined) { switch (member) { case "floatInBody": { @@ -3108,7 +3143,7 @@ export namespace MalformedIntegerInput { export const validate = (obj: MalformedIntegerInput, path = ""): __ValidationFailure[] => { function getMemberValidator( member: T - ): NonNullable<(typeof memberValidators)[T]> { + ): NonNullable { if (memberValidators[member] === undefined) { switch (member) { case "integerInBody": { @@ -3160,7 +3195,7 @@ export namespace MalformedListInput { export const validate = (obj: MalformedListInput, path = ""): __ValidationFailure[] => { function getMemberValidator( member: T - ): NonNullable<(typeof memberValidators)[T]> { + ): NonNullable { if (memberValidators[member] === undefined) { switch (member) { case "bodyList": { @@ -3204,7 +3239,7 @@ export namespace MalformedLongInput { export const validate = (obj: MalformedLongInput, path = ""): __ValidationFailure[] => { function getMemberValidator( member: T - ): NonNullable<(typeof memberValidators)[T]> { + ): NonNullable { if (memberValidators[member] === undefined) { switch (member) { case "longInBody": { @@ -3256,7 +3291,7 @@ export namespace MalformedMapInput { export const validate = (obj: MalformedMapInput, path = ""): __ValidationFailure[] => { function getMemberValidator( member: T - ): NonNullable<(typeof memberValidators)[T]> { + ): NonNullable { if (memberValidators[member] === undefined) { switch (member) { case "bodyMap": { @@ -3297,7 +3332,7 @@ export namespace MalformedRequestBodyInput { export const validate = (obj: MalformedRequestBodyInput, path = ""): __ValidationFailure[] => { function getMemberValidator( member: T - ): NonNullable<(typeof memberValidators)[T]> { + ): NonNullable { if (memberValidators[member] === undefined) { switch (member) { case "int": { @@ -3345,7 +3380,7 @@ export namespace MalformedShortInput { export const validate = (obj: MalformedShortInput, path = ""): __ValidationFailure[] => { function getMemberValidator( member: T - ): NonNullable<(typeof memberValidators)[T]> { + ): NonNullable { if (memberValidators[member] === undefined) { switch (member) { case "shortInBody": { @@ -3397,7 +3432,7 @@ export namespace MalformedStringInput { export const validate = (obj: MalformedStringInput, path = ""): __ValidationFailure[] => { function getMemberValidator( member: T - ): NonNullable<(typeof memberValidators)[T]> { + ): NonNullable { if (memberValidators[member] === undefined) { switch (member) { case "blob": { @@ -3434,7 +3469,7 @@ export namespace MalformedTimestampBodyDateTimeInput { export const validate = (obj: MalformedTimestampBodyDateTimeInput, path = ""): __ValidationFailure[] => { function getMemberValidator( member: T - ): NonNullable<(typeof memberValidators)[T]> { + ): NonNullable { if (memberValidators[member] === undefined) { switch (member) { case "timestamp": { @@ -3469,7 +3504,7 @@ export namespace MalformedTimestampBodyDefaultInput { export const validate = (obj: MalformedTimestampBodyDefaultInput, path = ""): __ValidationFailure[] => { function getMemberValidator( member: T - ): NonNullable<(typeof memberValidators)[T]> { + ): NonNullable { if (memberValidators[member] === undefined) { switch (member) { case "timestamp": { @@ -3506,7 +3541,7 @@ export namespace MalformedTimestampBodyHttpDateInput { export const validate = (obj: MalformedTimestampBodyHttpDateInput, path = ""): __ValidationFailure[] => { function getMemberValidator( member: T - ): NonNullable<(typeof memberValidators)[T]> { + ): NonNullable { if (memberValidators[member] === undefined) { switch (member) { case "timestamp": { @@ -3543,7 +3578,7 @@ export namespace MalformedTimestampHeaderDateTimeInput { export const validate = (obj: MalformedTimestampHeaderDateTimeInput, path = ""): __ValidationFailure[] => { function getMemberValidator( member: T - ): NonNullable<(typeof memberValidators)[T]> { + ): NonNullable { if (memberValidators[member] === undefined) { switch (member) { case "timestamp": { @@ -3580,7 +3615,7 @@ export namespace MalformedTimestampHeaderDefaultInput { export const validate = (obj: MalformedTimestampHeaderDefaultInput, path = ""): __ValidationFailure[] => { function getMemberValidator( member: T - ): NonNullable<(typeof memberValidators)[T]> { + ): NonNullable { if (memberValidators[member] === undefined) { switch (member) { case "timestamp": { @@ -3615,7 +3650,7 @@ export namespace MalformedTimestampHeaderEpochInput { export const validate = (obj: MalformedTimestampHeaderEpochInput, path = ""): __ValidationFailure[] => { function getMemberValidator( member: T - ): NonNullable<(typeof memberValidators)[T]> { + ): NonNullable { if (memberValidators[member] === undefined) { switch (member) { case "timestamp": { @@ -3650,7 +3685,7 @@ export namespace MalformedTimestampPathDefaultInput { export const validate = (obj: MalformedTimestampPathDefaultInput, path = ""): __ValidationFailure[] => { function getMemberValidator( member: T - ): NonNullable<(typeof memberValidators)[T]> { + ): NonNullable { if (memberValidators[member] === undefined) { switch (member) { case "timestamp": { @@ -3685,7 +3720,7 @@ export namespace MalformedTimestampPathEpochInput { export const validate = (obj: MalformedTimestampPathEpochInput, path = ""): __ValidationFailure[] => { function getMemberValidator( member: T - ): NonNullable<(typeof memberValidators)[T]> { + ): NonNullable { if (memberValidators[member] === undefined) { switch (member) { case "timestamp": { @@ -3722,7 +3757,7 @@ export namespace MalformedTimestampPathHttpDateInput { export const validate = (obj: MalformedTimestampPathHttpDateInput, path = ""): __ValidationFailure[] => { function getMemberValidator( member: T - ): NonNullable<(typeof memberValidators)[T]> { + ): NonNullable { if (memberValidators[member] === undefined) { switch (member) { case "timestamp": { @@ -3759,7 +3794,7 @@ export namespace MalformedTimestampQueryDefaultInput { export const validate = (obj: MalformedTimestampQueryDefaultInput, path = ""): __ValidationFailure[] => { function getMemberValidator( member: T - ): NonNullable<(typeof memberValidators)[T]> { + ): NonNullable { if (memberValidators[member] === undefined) { switch (member) { case "timestamp": { @@ -3794,7 +3829,7 @@ export namespace MalformedTimestampQueryEpochInput { export const validate = (obj: MalformedTimestampQueryEpochInput, path = ""): __ValidationFailure[] => { function getMemberValidator( member: T - ): NonNullable<(typeof memberValidators)[T]> { + ): NonNullable { if (memberValidators[member] === undefined) { switch (member) { case "timestamp": { @@ -3831,7 +3866,7 @@ export namespace MalformedTimestampQueryHttpDateInput { export const validate = (obj: MalformedTimestampQueryHttpDateInput, path = ""): __ValidationFailure[] => { function getMemberValidator( member: T - ): NonNullable<(typeof memberValidators)[T]> { + ): NonNullable { if (memberValidators[member] === undefined) { switch (member) { case "timestamp": { @@ -3889,7 +3924,7 @@ export namespace SimpleUnion { export const validate = (obj: SimpleUnion, path = ""): __ValidationFailure[] => { function getMemberValidator( member: T - ): NonNullable<(typeof memberValidators)[T]> { + ): NonNullable { if (memberValidators[member] === undefined) { switch (member) { case "int": { @@ -3940,7 +3975,7 @@ export namespace MalformedUnionInput { export const validate = (obj: MalformedUnionInput, path = ""): __ValidationFailure[] => { function getMemberValidator( member: T - ): NonNullable<(typeof memberValidators)[T]> { + ): NonNullable { if (memberValidators[member] === undefined) { switch (member) { case "union": { @@ -3978,7 +4013,7 @@ export namespace MediaTypeHeaderInput { export const validate = (obj: MediaTypeHeaderInput, path = ""): __ValidationFailure[] => { function getMemberValidator( member: T - ): NonNullable<(typeof memberValidators)[T]> { + ): NonNullable { if (memberValidators[member] === undefined) { switch (member) { case "json": { @@ -4013,7 +4048,7 @@ export namespace MediaTypeHeaderOutput { export const validate = (obj: MediaTypeHeaderOutput, path = ""): __ValidationFailure[] => { function getMemberValidator( member: T - ): NonNullable<(typeof memberValidators)[T]> { + ): NonNullable { if (memberValidators[member] === undefined) { switch (member) { case "json": { @@ -4044,7 +4079,7 @@ export namespace NoInputAndOutputOutput { export const validate = (obj: NoInputAndOutputOutput, path = ""): __ValidationFailure[] => { function getMemberValidator( member: T - ): NonNullable<(typeof memberValidators)[T]> { + ): NonNullable { if (memberValidators[member] === undefined) { switch (member) { } @@ -4079,7 +4114,7 @@ export namespace NullAndEmptyHeadersIO { export const validate = (obj: NullAndEmptyHeadersIO, path = ""): __ValidationFailure[] => { function getMemberValidator( member: T - ): NonNullable<(typeof memberValidators)[T]> { + ): NonNullable { if (memberValidators[member] === undefined) { switch (member) { case "a": { @@ -4133,7 +4168,7 @@ export namespace OmitsNullSerializesEmptyStringInput { export const validate = (obj: OmitsNullSerializesEmptyStringInput, path = ""): __ValidationFailure[] => { function getMemberValidator( member: T - ): NonNullable<(typeof memberValidators)[T]> { + ): NonNullable { if (memberValidators[member] === undefined) { switch (member) { case "nullValue": { @@ -4175,7 +4210,7 @@ export namespace PayloadConfig { export const validate = (obj: PayloadConfig, path = ""): __ValidationFailure[] => { function getMemberValidator( member: T - ): NonNullable<(typeof memberValidators)[T]> { + ): NonNullable { if (memberValidators[member] === undefined) { switch (member) { case "data": { @@ -4206,7 +4241,7 @@ export namespace Unit { export const validate = (obj: Unit, path = ""): __ValidationFailure[] => { function getMemberValidator( member: T - ): NonNullable<(typeof memberValidators)[T]> { + ): NonNullable { if (memberValidators[member] === undefined) { switch (member) { } @@ -4252,7 +4287,7 @@ export namespace PlayerAction { export const validate = (obj: PlayerAction, path = ""): __ValidationFailure[] => { function getMemberValidator( member: T - ): NonNullable<(typeof memberValidators)[T]> { + ): NonNullable { if (memberValidators[member] === undefined) { switch (member) { case "quit": { @@ -4295,7 +4330,7 @@ export namespace PostPlayerActionInput { export const validate = (obj: PostPlayerActionInput, path = ""): __ValidationFailure[] => { function getMemberValidator( member: T - ): NonNullable<(typeof memberValidators)[T]> { + ): NonNullable { if (memberValidators[member] === undefined) { switch (member) { case "action": { @@ -4334,7 +4369,7 @@ export namespace PostPlayerActionOutput { export const validate = (obj: PostPlayerActionOutput, path = ""): __ValidationFailure[] => { function getMemberValidator( member: T - ): NonNullable<(typeof memberValidators)[T]> { + ): NonNullable { if (memberValidators[member] === undefined) { switch (member) { case "action": { @@ -4412,7 +4447,7 @@ export namespace UnionWithJsonName { export const validate = (obj: UnionWithJsonName, path = ""): __ValidationFailure[] => { function getMemberValidator( member: T - ): NonNullable<(typeof memberValidators)[T]> { + ): NonNullable { if (memberValidators[member] === undefined) { switch (member) { case "foo": { @@ -4469,7 +4504,7 @@ export namespace PostUnionWithJsonNameInput { export const validate = (obj: PostUnionWithJsonNameInput, path = ""): __ValidationFailure[] => { function getMemberValidator( member: T - ): NonNullable<(typeof memberValidators)[T]> { + ): NonNullable { if (memberValidators[member] === undefined) { switch (member) { case "value": { @@ -4508,7 +4543,7 @@ export namespace PostUnionWithJsonNameOutput { export const validate = (obj: PostUnionWithJsonNameOutput, path = ""): __ValidationFailure[] => { function getMemberValidator( member: T - ): NonNullable<(typeof memberValidators)[T]> { + ): NonNullable { if (memberValidators[member] === undefined) { switch (member) { case "value": { @@ -4546,7 +4581,7 @@ export namespace QueryIdempotencyTokenAutoFillInput { export const validate = (obj: QueryIdempotencyTokenAutoFillInput, path = ""): __ValidationFailure[] => { function getMemberValidator( member: T - ): NonNullable<(typeof memberValidators)[T]> { + ): NonNullable { if (memberValidators[member] === undefined) { switch (member) { case "token": { @@ -4583,7 +4618,7 @@ export namespace QueryParamsAsStringListMapInput { export const validate = (obj: QueryParamsAsStringListMapInput, path = ""): __ValidationFailure[] => { function getMemberValidator( member: T - ): NonNullable<(typeof memberValidators)[T]> { + ): NonNullable { if (memberValidators[member] === undefined) { switch (member) { case "qux": { @@ -4631,7 +4666,7 @@ export namespace QueryPrecedenceInput { export const validate = (obj: QueryPrecedenceInput, path = ""): __ValidationFailure[] => { function getMemberValidator( member: T - ): NonNullable<(typeof memberValidators)[T]> { + ): NonNullable { if (memberValidators[member] === undefined) { switch (member) { case "foo": { @@ -4695,7 +4730,7 @@ export namespace SimpleScalarPropertiesInputOutput { export const validate = (obj: SimpleScalarPropertiesInputOutput, path = ""): __ValidationFailure[] => { function getMemberValidator( member: T - ): NonNullable<(typeof memberValidators)[T]> { + ): NonNullable { if (memberValidators[member] === undefined) { switch (member) { case "foo": { @@ -4784,7 +4819,7 @@ export namespace StreamingTraitsInputOutput { ): __ValidationFailure[] => { function getMemberValidator( member: T - ): NonNullable<(typeof memberValidators)[T]> { + ): NonNullable { if (memberValidators[member] === undefined) { switch (member) { case "foo": { @@ -4833,7 +4868,7 @@ export namespace StreamingTraitsRequireLengthInput { ): __ValidationFailure[] => { function getMemberValidator( member: T - ): NonNullable<(typeof memberValidators)[T]> { + ): NonNullable { if (memberValidators[member] === undefined) { switch (member) { case "foo": { @@ -4884,7 +4919,7 @@ export namespace StreamingTraitsWithMediaTypeInputOutput { ): __ValidationFailure[] => { function getMemberValidator( member: T - ): NonNullable<(typeof memberValidators)[T]> { + ): NonNullable { if (memberValidators[member] === undefined) { switch (member) { case "foo": { @@ -4926,7 +4961,7 @@ export namespace TestConfig { export const validate = (obj: TestConfig, path = ""): __ValidationFailure[] => { function getMemberValidator( member: T - ): NonNullable<(typeof memberValidators)[T]> { + ): NonNullable { if (memberValidators[member] === undefined) { switch (member) { case "timeout": { @@ -4963,7 +4998,7 @@ export namespace TestBodyStructureInputOutput { export const validate = (obj: TestBodyStructureInputOutput, path = ""): __ValidationFailure[] => { function getMemberValidator( member: T - ): NonNullable<(typeof memberValidators)[T]> { + ): NonNullable { if (memberValidators[member] === undefined) { switch (member) { case "testId": { @@ -5008,7 +5043,7 @@ export namespace TestNoPayloadInputOutput { export const validate = (obj: TestNoPayloadInputOutput, path = ""): __ValidationFailure[] => { function getMemberValidator( member: T - ): NonNullable<(typeof memberValidators)[T]> { + ): NonNullable { if (memberValidators[member] === undefined) { switch (member) { case "testId": { @@ -5045,7 +5080,7 @@ export namespace TestPayloadBlobInputOutput { export const validate = (obj: TestPayloadBlobInputOutput, path = ""): __ValidationFailure[] => { function getMemberValidator( member: T - ): NonNullable<(typeof memberValidators)[T]> { + ): NonNullable { if (memberValidators[member] === undefined) { switch (member) { case "contentType": { @@ -5089,7 +5124,7 @@ export namespace TestPayloadStructureInputOutput { export const validate = (obj: TestPayloadStructureInputOutput, path = ""): __ValidationFailure[] => { function getMemberValidator( member: T - ): NonNullable<(typeof memberValidators)[T]> { + ): NonNullable { if (memberValidators[member] === undefined) { switch (member) { case "testId": { @@ -5146,7 +5181,7 @@ export namespace TimestampFormatHeadersIO { export const validate = (obj: TimestampFormatHeadersIO, path = ""): __ValidationFailure[] => { function getMemberValidator( member: T - ): NonNullable<(typeof memberValidators)[T]> { + ): NonNullable { if (memberValidators[member] === undefined) { switch (member) { case "memberEpochSeconds": { @@ -5215,7 +5250,7 @@ export namespace RecursiveShapesInputOutputNested1 { export const validate = (obj: RecursiveShapesInputOutputNested1, path = ""): __ValidationFailure[] => { function getMemberValidator( member: T - ): NonNullable<(typeof memberValidators)[T]> { + ): NonNullable { if (memberValidators[member] === undefined) { switch (member) { case "foo": { @@ -5262,7 +5297,7 @@ export namespace RecursiveShapesInputOutputNested2 { export const validate = (obj: RecursiveShapesInputOutputNested2, path = ""): __ValidationFailure[] => { function getMemberValidator( member: T - ): NonNullable<(typeof memberValidators)[T]> { + ): NonNullable { if (memberValidators[member] === undefined) { switch (member) { case "bar": { @@ -5307,7 +5342,7 @@ export namespace RecursiveShapesInputOutput { export const validate = (obj: RecursiveShapesInputOutput, path = ""): __ValidationFailure[] => { function getMemberValidator( member: T - ): NonNullable<(typeof memberValidators)[T]> { + ): NonNullable { if (memberValidators[member] === undefined) { switch (member) { case "nested": { diff --git a/private/aws-restjson-server/src/protocols/Aws_restJson1.ts b/private/aws-restjson-server/src/protocols/Aws_restJson1.ts index 2ac3e4cd0f564..3e1664d033d31 100644 --- a/private/aws-restjson-server/src/protocols/Aws_restJson1.ts +++ b/private/aws-restjson-server/src/protocols/Aws_restJson1.ts @@ -79,6 +79,7 @@ import { ConstantQueryStringServerInput, ConstantQueryStringServerOutput, } from "../server/operations/ConstantQueryString"; +import { DatetimeOffsetsServerInput, DatetimeOffsetsServerOutput } from "../server/operations/DatetimeOffsets"; import { DocumentTypeServerInput, DocumentTypeServerOutput } from "../server/operations/DocumentType"; import { DocumentTypeAsPayloadServerInput, @@ -620,6 +621,31 @@ export const deserializeConstantQueryStringRequest = async ( return contents; }; +export const deserializeDatetimeOffsetsRequest = async ( + output: __HttpRequest, + context: __SerdeContext +): Promise => { + const contentTypeHeaderKey: string | undefined = Object.keys(output.headers).find( + (key) => key.toLowerCase() === "content-type" + ); + if (contentTypeHeaderKey != null) { + const contentType = output.headers[contentTypeHeaderKey]; + if (contentType !== undefined) { + throw new __UnsupportedMediaTypeException(); + } + } + const acceptHeaderKey: string | undefined = Object.keys(output.headers).find((key) => key.toLowerCase() === "accept"); + if (acceptHeaderKey != null) { + const accept = output.headers[acceptHeaderKey]; + if (!__acceptMatches(accept, "application/json")) { + throw new __NotAcceptableException(); + } + } + const contents: any = map({}); + await collectBody(output.body, context); + return contents; +}; + export const deserializeDocumentTypeRequest = async ( output: __HttpRequest, context: __SerdeContext @@ -3569,6 +3595,45 @@ export const serializeConstantQueryStringResponse = async ( }); }; +export const serializeDatetimeOffsetsResponse = async ( + input: DatetimeOffsetsServerOutput, + ctx: ServerSerdeContext +): Promise<__HttpResponse> => { + const context: __SerdeContext = { + ...ctx, + endpoint: () => + Promise.resolve({ + protocol: "", + hostname: "", + path: "", + }), + }; + const statusCode = 200; + let headers: any = map({}, isSerializableHeaderValue, { + "content-type": "application/json", + }); + let body: any; + body = JSON.stringify({ + ...(input.datetime != null && { datetime: input.datetime.toISOString().split(".")[0] + "Z" }), + }); + if ( + body && + Object.keys(headers) + .map((str) => str.toLowerCase()) + .indexOf("content-length") === -1 + ) { + const length = calculateBodyLength(body); + if (length !== undefined) { + headers = { ...headers, "content-length": String(length) }; + } + } + return new __HttpResponse({ + headers, + body, + statusCode, + }); +}; + export const serializeDocumentTypeResponse = async ( input: DocumentTypeServerOutput, ctx: ServerSerdeContext diff --git a/private/aws-restjson-server/src/server/RestJsonService.ts b/private/aws-restjson-server/src/server/RestJsonService.ts index 62719f15d7851..b735f299774b3 100644 --- a/private/aws-restjson-server/src/server/RestJsonService.ts +++ b/private/aws-restjson-server/src/server/RestJsonService.ts @@ -38,6 +38,7 @@ import { ConstantQueryStringSerializer, ConstantQueryStringServerInput, } from "./operations/ConstantQueryString"; +import { DatetimeOffsets, DatetimeOffsetsSerializer, DatetimeOffsetsServerInput } from "./operations/DatetimeOffsets"; import { DocumentType, DocumentTypeSerializer, DocumentTypeServerInput } from "./operations/DocumentType"; import { DocumentTypeAsPayload, @@ -363,6 +364,7 @@ export type RestJsonServiceOperations = | "AllQueryStringTypes" | "ConstantAndVariableQueryString" | "ConstantQueryString" + | "DatetimeOffsets" | "DocumentType" | "DocumentTypeAsPayload" | "EmptyInputAndEmptyOutput" @@ -451,6 +453,7 @@ export interface RestJsonService { AllQueryStringTypes: AllQueryStringTypes; ConstantAndVariableQueryString: ConstantAndVariableQueryString; ConstantQueryString: ConstantQueryString; + DatetimeOffsets: DatetimeOffsets; DocumentType: DocumentType; DocumentTypeAsPayload: DocumentTypeAsPayload; EmptyInputAndEmptyOutput: EmptyInputAndEmptyOutput; @@ -662,6 +665,18 @@ export class RestJsonServiceHandler implements __ServiceHandler( ], { service: "RestJson", operation: "ConstantQueryString" } ), + new httpbinding.UriSpec<"RestJson", "DatetimeOffsets">( + "POST", + [{ type: "path_literal", value: "DatetimeOffsets" }], + [], + { service: "RestJson", operation: "DatetimeOffsets" } + ), new httpbinding.UriSpec<"RestJson", "DocumentType">("PUT", [{ type: "path_literal", value: "DocumentType" }], [], { service: "RestJson", operation: "DocumentType", @@ -2220,6 +2241,8 @@ export const getRestJsonServiceHandler = ( return new ConstantAndVariableQueryStringSerializer(); case "ConstantQueryString": return new ConstantQueryStringSerializer(); + case "DatetimeOffsets": + return new DatetimeOffsetsSerializer(); case "DocumentType": return new DocumentTypeSerializer(); case "DocumentTypeAsPayload": diff --git a/private/aws-restjson-server/src/server/operations/DatetimeOffsets.ts b/private/aws-restjson-server/src/server/operations/DatetimeOffsets.ts new file mode 100644 index 0000000000000..47d892d75bbee --- /dev/null +++ b/private/aws-restjson-server/src/server/operations/DatetimeOffsets.ts @@ -0,0 +1,185 @@ +// smithy-typescript generated code +import { NodeHttpHandler, streamCollector } from "@aws-sdk/node-http-handler"; +import { HttpRequest as __HttpRequest, HttpResponse as __HttpResponse } from "@aws-sdk/protocol-http"; +import { fromBase64, toBase64 } from "@aws-sdk/util-base64"; +import { fromUtf8, toUtf8 } from "@aws-sdk/util-utf8"; +import { + httpbinding, + InternalFailureException as __InternalFailureException, + isFrameworkException as __isFrameworkException, + Mux as __Mux, + Operation as __Operation, + OperationInput as __OperationInput, + OperationOutput as __OperationOutput, + OperationSerializer as __OperationSerializer, + SerializationException as __SerializationException, + ServerSerdeContext as __ServerSerdeContext, + ServerSerdeContext, + ServiceException as __ServiceException, + ServiceHandler as __ServiceHandler, + SmithyFrameworkException as __SmithyFrameworkException, + ValidationCustomizer as __ValidationCustomizer, + ValidationFailure as __ValidationFailure, +} from "@aws-smithy/server-common"; + +import { DatetimeOffsetsOutput } from "../../models/models_0"; +import { + deserializeDatetimeOffsetsRequest, + serializeDatetimeOffsetsResponse, + serializeFrameworkException, +} from "../../protocols/Aws_restJson1"; +import { RestJsonService } from "../RestJsonService"; + +export type DatetimeOffsets = __Operation; + +export interface DatetimeOffsetsServerInput {} +export namespace DatetimeOffsetsServerInput { + /** + * @internal + */ + export const validate: () => __ValidationFailure[] = () => []; +} +export interface DatetimeOffsetsServerOutput extends DatetimeOffsetsOutput {} + +export type DatetimeOffsetsErrors = never; + +export class DatetimeOffsetsSerializer + implements __OperationSerializer, "DatetimeOffsets", DatetimeOffsetsErrors> +{ + serialize = serializeDatetimeOffsetsResponse; + deserialize = deserializeDatetimeOffsetsRequest; + + isOperationError(error: any): error is DatetimeOffsetsErrors { + return false; + } + + serializeError(error: DatetimeOffsetsErrors, ctx: ServerSerdeContext): Promise<__HttpResponse> { + throw error; + } +} + +export const getDatetimeOffsetsHandler = ( + operation: __Operation, + customizer: __ValidationCustomizer<"DatetimeOffsets"> +): __ServiceHandler => { + const mux = new httpbinding.HttpBindingMux<"RestJson", "DatetimeOffsets">([ + new httpbinding.UriSpec<"RestJson", "DatetimeOffsets">( + "POST", + [{ type: "path_literal", value: "DatetimeOffsets" }], + [], + { service: "RestJson", operation: "DatetimeOffsets" } + ), + ]); + return new DatetimeOffsetsHandler( + operation, + mux, + new DatetimeOffsetsSerializer(), + serializeFrameworkException, + customizer + ); +}; + +const serdeContextBase = { + base64Encoder: toBase64, + base64Decoder: fromBase64, + utf8Encoder: toUtf8, + utf8Decoder: fromUtf8, + streamCollector: streamCollector, + requestHandler: new NodeHttpHandler(), + disableHostPrefix: true, +}; +async function handle( + request: __HttpRequest, + context: Context, + operationName: O, + serializer: __OperationSerializer, + operation: __Operation<__OperationInput, __OperationOutput, Context>, + serializeFrameworkException: (e: __SmithyFrameworkException, ctx: __ServerSerdeContext) => Promise<__HttpResponse>, + validationFn: (input: __OperationInput) => __ValidationFailure[], + validationCustomizer: __ValidationCustomizer +): Promise<__HttpResponse> { + let input; + try { + input = await serializer.deserialize(request, { + endpoint: () => Promise.resolve(request), + ...serdeContextBase, + }); + } catch (error: unknown) { + if (__isFrameworkException(error)) { + return serializeFrameworkException(error, serdeContextBase); + } + return serializeFrameworkException(new __SerializationException(), serdeContextBase); + } + try { + const validationFailures = validationFn(input); + if (validationFailures && validationFailures.length > 0) { + const validationException = validationCustomizer({ operation: operationName }, validationFailures); + if (validationException) { + return serializer.serializeError(validationException, serdeContextBase); + } + } + const output = await operation(input, context); + return serializer.serialize(output, serdeContextBase); + } catch (error: unknown) { + if (serializer.isOperationError(error)) { + return serializer.serializeError(error, serdeContextBase); + } + console.log("Received an unexpected error", error); + return serializeFrameworkException(new __InternalFailureException(), serdeContextBase); + } +} +export class DatetimeOffsetsHandler implements __ServiceHandler { + private readonly operation: __Operation; + private readonly mux: __Mux<"RestJson", "DatetimeOffsets">; + private readonly serializer: __OperationSerializer< + RestJsonService, + "DatetimeOffsets", + DatetimeOffsetsErrors + >; + private readonly serializeFrameworkException: ( + e: __SmithyFrameworkException, + ctx: __ServerSerdeContext + ) => Promise<__HttpResponse>; + private readonly validationCustomizer: __ValidationCustomizer<"DatetimeOffsets">; + /** + * Construct a DatetimeOffsets handler. + * @param operation The {@link __Operation} implementation that supplies the business logic for DatetimeOffsets + * @param mux The {@link __Mux} that verifies which service and operation are being invoked by a given {@link __HttpRequest} + * @param serializer An {@link __OperationSerializer} for DatetimeOffsets that + * handles deserialization of requests and serialization of responses + * @param serializeFrameworkException A function that can serialize {@link __SmithyFrameworkException}s + * @param validationCustomizer A {@link __ValidationCustomizer} for turning validation failures into {@link __SmithyFrameworkException}s + */ + constructor( + operation: __Operation, + mux: __Mux<"RestJson", "DatetimeOffsets">, + serializer: __OperationSerializer, "DatetimeOffsets", DatetimeOffsetsErrors>, + serializeFrameworkException: (e: __SmithyFrameworkException, ctx: __ServerSerdeContext) => Promise<__HttpResponse>, + validationCustomizer: __ValidationCustomizer<"DatetimeOffsets"> + ) { + this.operation = operation; + this.mux = mux; + this.serializer = serializer; + this.serializeFrameworkException = serializeFrameworkException; + this.validationCustomizer = validationCustomizer; + } + async handle(request: __HttpRequest, context: Context): Promise<__HttpResponse> { + const target = this.mux.match(request); + if (target === undefined) { + console.log( + "Received a request that did not match aws.protocoltests.restjson#RestJson.DatetimeOffsets. This indicates a misconfiguration." + ); + return this.serializeFrameworkException(new __InternalFailureException(), serdeContextBase); + } + return handle( + request, + context, + "DatetimeOffsets", + this.serializer, + this.operation, + this.serializeFrameworkException, + DatetimeOffsetsServerInput.validate, + this.validationCustomizer + ); + } +} diff --git a/private/aws-restjson-server/src/server/operations/index.ts b/private/aws-restjson-server/src/server/operations/index.ts index d19a31d200fdd..c755d179c8c2f 100644 --- a/private/aws-restjson-server/src/server/operations/index.ts +++ b/private/aws-restjson-server/src/server/operations/index.ts @@ -2,6 +2,7 @@ export * from "./AllQueryStringTypes"; export * from "./ConstantAndVariableQueryString"; export * from "./ConstantQueryString"; +export * from "./DatetimeOffsets"; export * from "./DocumentType"; export * from "./DocumentTypeAsPayload"; export * from "./EmptyInputAndEmptyOutput"; diff --git a/private/aws-restjson-server/test/functional/restjson1.spec.ts b/private/aws-restjson-server/test/functional/restjson1.spec.ts index 3925bd27da28e..54e5e06857766 100644 --- a/private/aws-restjson-server/test/functional/restjson1.spec.ts +++ b/private/aws-restjson-server/test/functional/restjson1.spec.ts @@ -457,6 +457,48 @@ it("RestJsonAllQueryStringTypes:ServerRequest", async () => { 3, ], + + queryParamsMapOfStringList: { + String: ["Hello there"], + + StringList: ["a", "b", "c"], + + StringSet: ["a", "b", "c"], + + Byte: ["1"], + + Short: ["2"], + + Integer: ["3"], + + IntegerList: ["1", "2", "3"], + + IntegerSet: ["1", "2", "3"], + + Long: ["4"], + + Float: ["1.1"], + + Double: ["1.1"], + + DoubleList: ["1.1", "2.1", "3.1"], + + Boolean: ["true"], + + BooleanList: ["true", "false", "true"], + + Timestamp: ["1970-01-01T00:00:01Z"], + + TimestampList: ["1970-01-01T00:00:01Z", "1970-01-01T00:00:02Z", "1970-01-01T00:00:03Z"], + + Enum: ["Foo"], + + EnumList: ["Foo", "Baz", "Bar"], + + IntegerEnum: ["1"], + + IntegerEnumList: ["1", "2", "3"], + }, }, ][0]; Object.keys(paramsToValidate).forEach((param) => { @@ -550,6 +592,10 @@ it("RestJsonQueryStringEscaping:ServerRequest", async () => { const paramsToValidate: any = [ { queryString: "%:/?#[]@!$&'()*+,;=😹", + + queryParamsMapOfStringList: { + String: ["%:/?#[]@!$&'()*+,;=😹"], + }, }, ][0]; Object.keys(paramsToValidate).forEach((param) => { diff --git a/private/aws-restjson-validation-server/src/models/models_0.ts b/private/aws-restjson-validation-server/src/models/models_0.ts index ad2da710d4d92..1a4799a17fdf8 100644 --- a/private/aws-restjson-validation-server/src/models/models_0.ts +++ b/private/aws-restjson-validation-server/src/models/models_0.ts @@ -65,7 +65,7 @@ export namespace EnumUnion { export const validate = (obj: EnumUnion, path = ""): __ValidationFailure[] => { function getMemberValidator( member: T - ): NonNullable<(typeof memberValidators)[T]> { + ): NonNullable { if (memberValidators[member] === undefined) { switch (member) { case "first": { @@ -122,7 +122,7 @@ export namespace MalformedEnumInput { export const validate = (obj: MalformedEnumInput, path = ""): __ValidationFailure[] => { function getMemberValidator( member: T - ): NonNullable<(typeof memberValidators)[T]> { + ): NonNullable { if (memberValidators[member] === undefined) { switch (member) { case "string": { @@ -196,7 +196,7 @@ export namespace ValidationExceptionField { export const validate = (obj: ValidationExceptionField, path = ""): __ValidationFailure[] => { function getMemberValidator( member: T - ): NonNullable<(typeof memberValidators)[T]> { + ): NonNullable { if (memberValidators[member] === undefined) { switch (member) { case "path": { @@ -273,7 +273,7 @@ export namespace MalformedLengthInput { export const validate = (obj: MalformedLengthInput, path = ""): __ValidationFailure[] => { function getMemberValidator( member: T - ): NonNullable<(typeof memberValidators)[T]> { + ): NonNullable { if (memberValidators[member] === undefined) { switch (member) { case "blob": { @@ -355,7 +355,7 @@ export namespace MalformedLengthOverrideInput { export const validate = (obj: MalformedLengthOverrideInput, path = ""): __ValidationFailure[] => { function getMemberValidator( member: T - ): NonNullable<(typeof memberValidators)[T]> { + ): NonNullable { if (memberValidators[member] === undefined) { switch (member) { case "blob": { @@ -427,7 +427,7 @@ export namespace MalformedLengthQueryStringInput { export const validate = (obj: MalformedLengthQueryStringInput, path = ""): __ValidationFailure[] => { function getMemberValidator( member: T - ): NonNullable<(typeof memberValidators)[T]> { + ): NonNullable { if (memberValidators[member] === undefined) { switch (member) { case "string": { @@ -485,7 +485,7 @@ export namespace PatternUnion { export const validate = (obj: PatternUnion, path = ""): __ValidationFailure[] => { function getMemberValidator( member: T - ): NonNullable<(typeof memberValidators)[T]> { + ): NonNullable { if (memberValidators[member] === undefined) { switch (member) { case "first": { @@ -544,7 +544,7 @@ export namespace MalformedPatternInput { export const validate = (obj: MalformedPatternInput, path = ""): __ValidationFailure[] => { function getMemberValidator( member: T - ): NonNullable<(typeof memberValidators)[T]> { + ): NonNullable { if (memberValidators[member] === undefined) { switch (member) { case "string": { @@ -637,7 +637,7 @@ export namespace PatternUnionOverride { export const validate = (obj: PatternUnionOverride, path = ""): __ValidationFailure[] => { function getMemberValidator( member: T - ): NonNullable<(typeof memberValidators)[T]> { + ): NonNullable { if (memberValidators[member] === undefined) { switch (member) { case "first": { @@ -694,7 +694,7 @@ export namespace MalformedPatternOverrideInput { export const validate = (obj: MalformedPatternOverrideInput, path = ""): __ValidationFailure[] => { function getMemberValidator( member: T - ): NonNullable<(typeof memberValidators)[T]> { + ): NonNullable { if (memberValidators[member] === undefined) { switch (member) { case "string": { @@ -740,6 +740,15 @@ export interface MalformedRangeInput { byte?: number; minByte?: number; maxByte?: number; + short?: number; + minShort?: number; + maxShort?: number; + integer?: number; + minInteger?: number; + maxInteger?: number; + long?: number; + minLong?: number; + maxLong?: number; float?: number; minFloat?: number; maxFloat?: number; @@ -756,6 +765,15 @@ export namespace MalformedRangeInput { byte?: __MultiConstraintValidator; minByte?: __MultiConstraintValidator; maxByte?: __MultiConstraintValidator; + short?: __MultiConstraintValidator; + minShort?: __MultiConstraintValidator; + maxShort?: __MultiConstraintValidator; + integer?: __MultiConstraintValidator; + minInteger?: __MultiConstraintValidator; + maxInteger?: __MultiConstraintValidator; + long?: __MultiConstraintValidator; + minLong?: __MultiConstraintValidator; + maxLong?: __MultiConstraintValidator; float?: __MultiConstraintValidator; minFloat?: __MultiConstraintValidator; maxFloat?: __MultiConstraintValidator; @@ -766,7 +784,7 @@ export namespace MalformedRangeInput { export const validate = (obj: MalformedRangeInput, path = ""): __ValidationFailure[] => { function getMemberValidator( member: T - ): NonNullable<(typeof memberValidators)[T]> { + ): NonNullable { if (memberValidators[member] === undefined) { switch (member) { case "byte": { @@ -781,6 +799,42 @@ export namespace MalformedRangeInput { memberValidators["maxByte"] = new __CompositeValidator([new __RangeValidator(undefined, 8)]); break; } + case "short": { + memberValidators["short"] = new __CompositeValidator([new __RangeValidator(2, 8)]); + break; + } + case "minShort": { + memberValidators["minShort"] = new __CompositeValidator([new __RangeValidator(2, undefined)]); + break; + } + case "maxShort": { + memberValidators["maxShort"] = new __CompositeValidator([new __RangeValidator(undefined, 8)]); + break; + } + case "integer": { + memberValidators["integer"] = new __CompositeValidator([new __RangeValidator(2, 8)]); + break; + } + case "minInteger": { + memberValidators["minInteger"] = new __CompositeValidator([new __RangeValidator(2, undefined)]); + break; + } + case "maxInteger": { + memberValidators["maxInteger"] = new __CompositeValidator([new __RangeValidator(undefined, 8)]); + break; + } + case "long": { + memberValidators["long"] = new __CompositeValidator([new __RangeValidator(2, 8)]); + break; + } + case "minLong": { + memberValidators["minLong"] = new __CompositeValidator([new __RangeValidator(2, undefined)]); + break; + } + case "maxLong": { + memberValidators["maxLong"] = new __CompositeValidator([new __RangeValidator(undefined, 8)]); + break; + } case "float": { memberValidators["float"] = new __CompositeValidator([new __RangeValidator(2.2, 8.8)]); break; @@ -801,6 +855,15 @@ export namespace MalformedRangeInput { ...getMemberValidator("byte").validate(obj.byte, `${path}/byte`), ...getMemberValidator("minByte").validate(obj.minByte, `${path}/minByte`), ...getMemberValidator("maxByte").validate(obj.maxByte, `${path}/maxByte`), + ...getMemberValidator("short").validate(obj.short, `${path}/short`), + ...getMemberValidator("minShort").validate(obj.minShort, `${path}/minShort`), + ...getMemberValidator("maxShort").validate(obj.maxShort, `${path}/maxShort`), + ...getMemberValidator("integer").validate(obj.integer, `${path}/integer`), + ...getMemberValidator("minInteger").validate(obj.minInteger, `${path}/minInteger`), + ...getMemberValidator("maxInteger").validate(obj.maxInteger, `${path}/maxInteger`), + ...getMemberValidator("long").validate(obj.long, `${path}/long`), + ...getMemberValidator("minLong").validate(obj.minLong, `${path}/minLong`), + ...getMemberValidator("maxLong").validate(obj.maxLong, `${path}/maxLong`), ...getMemberValidator("float").validate(obj.float, `${path}/float`), ...getMemberValidator("minFloat").validate(obj.minFloat, `${path}/minFloat`), ...getMemberValidator("maxFloat").validate(obj.maxFloat, `${path}/maxFloat`), @@ -812,6 +875,15 @@ export interface MalformedRangeOverrideInput { byte?: number; minByte?: number; maxByte?: number; + short?: number; + minShort?: number; + maxShort?: number; + integer?: number; + minInteger?: number; + maxInteger?: number; + long?: number; + minLong?: number; + maxLong?: number; float?: number; minFloat?: number; maxFloat?: number; @@ -828,6 +900,15 @@ export namespace MalformedRangeOverrideInput { byte?: __MultiConstraintValidator; minByte?: __MultiConstraintValidator; maxByte?: __MultiConstraintValidator; + short?: __MultiConstraintValidator; + minShort?: __MultiConstraintValidator; + maxShort?: __MultiConstraintValidator; + integer?: __MultiConstraintValidator; + minInteger?: __MultiConstraintValidator; + maxInteger?: __MultiConstraintValidator; + long?: __MultiConstraintValidator; + minLong?: __MultiConstraintValidator; + maxLong?: __MultiConstraintValidator; float?: __MultiConstraintValidator; minFloat?: __MultiConstraintValidator; maxFloat?: __MultiConstraintValidator; @@ -838,7 +919,7 @@ export namespace MalformedRangeOverrideInput { export const validate = (obj: MalformedRangeOverrideInput, path = ""): __ValidationFailure[] => { function getMemberValidator( member: T - ): NonNullable<(typeof memberValidators)[T]> { + ): NonNullable { if (memberValidators[member] === undefined) { switch (member) { case "byte": { @@ -853,6 +934,42 @@ export namespace MalformedRangeOverrideInput { memberValidators["maxByte"] = new __CompositeValidator([new __RangeValidator(undefined, 6)]); break; } + case "short": { + memberValidators["short"] = new __CompositeValidator([new __RangeValidator(4, 6)]); + break; + } + case "minShort": { + memberValidators["minShort"] = new __CompositeValidator([new __RangeValidator(4, undefined)]); + break; + } + case "maxShort": { + memberValidators["maxShort"] = new __CompositeValidator([new __RangeValidator(undefined, 6)]); + break; + } + case "integer": { + memberValidators["integer"] = new __CompositeValidator([new __RangeValidator(4, 6)]); + break; + } + case "minInteger": { + memberValidators["minInteger"] = new __CompositeValidator([new __RangeValidator(4, undefined)]); + break; + } + case "maxInteger": { + memberValidators["maxInteger"] = new __CompositeValidator([new __RangeValidator(undefined, 6)]); + break; + } + case "long": { + memberValidators["long"] = new __CompositeValidator([new __RangeValidator(4, 6)]); + break; + } + case "minLong": { + memberValidators["minLong"] = new __CompositeValidator([new __RangeValidator(4, undefined)]); + break; + } + case "maxLong": { + memberValidators["maxLong"] = new __CompositeValidator([new __RangeValidator(undefined, 6)]); + break; + } case "float": { memberValidators["float"] = new __CompositeValidator([new __RangeValidator(4.4, 6.6)]); break; @@ -873,6 +990,15 @@ export namespace MalformedRangeOverrideInput { ...getMemberValidator("byte").validate(obj.byte, `${path}/byte`), ...getMemberValidator("minByte").validate(obj.minByte, `${path}/minByte`), ...getMemberValidator("maxByte").validate(obj.maxByte, `${path}/maxByte`), + ...getMemberValidator("short").validate(obj.short, `${path}/short`), + ...getMemberValidator("minShort").validate(obj.minShort, `${path}/minShort`), + ...getMemberValidator("maxShort").validate(obj.maxShort, `${path}/maxShort`), + ...getMemberValidator("integer").validate(obj.integer, `${path}/integer`), + ...getMemberValidator("minInteger").validate(obj.minInteger, `${path}/minInteger`), + ...getMemberValidator("maxInteger").validate(obj.maxInteger, `${path}/maxInteger`), + ...getMemberValidator("long").validate(obj.long, `${path}/long`), + ...getMemberValidator("minLong").validate(obj.minLong, `${path}/minLong`), + ...getMemberValidator("maxLong").validate(obj.maxLong, `${path}/maxLong`), ...getMemberValidator("float").validate(obj.float, `${path}/float`), ...getMemberValidator("minFloat").validate(obj.minFloat, `${path}/minFloat`), ...getMemberValidator("maxFloat").validate(obj.maxFloat, `${path}/maxFloat`), @@ -904,7 +1030,7 @@ export namespace MalformedRequiredInput { export const validate = (obj: MalformedRequiredInput, path = ""): __ValidationFailure[] => { function getMemberValidator( member: T - ): NonNullable<(typeof memberValidators)[T]> { + ): NonNullable { if (memberValidators[member] === undefined) { switch (member) { case "string": { @@ -957,7 +1083,7 @@ export namespace SensitiveValidationInput { export const validate = (obj: SensitiveValidationInput, path = ""): __ValidationFailure[] => { function getMemberValidator( member: T - ): NonNullable<(typeof memberValidators)[T]> { + ): NonNullable { if (memberValidators[member] === undefined) { switch (member) { case "string": { @@ -1020,7 +1146,7 @@ export namespace RecursiveUnionOne { export const validate = (obj: RecursiveUnionOne, path = ""): __ValidationFailure[] => { function getMemberValidator( member: T - ): NonNullable<(typeof memberValidators)[T]> { + ): NonNullable { if (memberValidators[member] === undefined) { switch (member) { case "string": { @@ -1099,7 +1225,7 @@ export namespace RecursiveUnionTwo { export const validate = (obj: RecursiveUnionTwo, path = ""): __ValidationFailure[] => { function getMemberValidator( member: T - ): NonNullable<(typeof memberValidators)[T]> { + ): NonNullable { if (memberValidators[member] === undefined) { switch (member) { case "string": { @@ -1153,7 +1279,7 @@ export namespace RecursiveStructuresInput { export const validate = (obj: RecursiveStructuresInput, path = ""): __ValidationFailure[] => { function getMemberValidator( member: T - ): NonNullable<(typeof memberValidators)[T]> { + ): NonNullable { if (memberValidators[member] === undefined) { switch (member) { case "union": { diff --git a/private/aws-restjson-validation-server/src/protocols/Aws_restJson1.ts b/private/aws-restjson-validation-server/src/protocols/Aws_restJson1.ts index c0dbc3989439c..596772cb43bd5 100644 --- a/private/aws-restjson-validation-server/src/protocols/Aws_restJson1.ts +++ b/private/aws-restjson-validation-server/src/protocols/Aws_restJson1.ts @@ -2,8 +2,11 @@ import { HttpRequest as __HttpRequest, HttpResponse as __HttpResponse } from "@aws-sdk/protocol-http"; import { expectByte as __expectByte, + expectInt32 as __expectInt32, + expectLong as __expectLong, expectNonNull as __expectNonNull, expectObject as __expectObject, + expectShort as __expectShort, expectString as __expectString, expectUnion as __expectUnion, limitedParseFloat32 as __limitedParseFloat32, @@ -334,18 +337,45 @@ export const deserializeMalformedRangeRequest = async ( if (data.float != null) { contents.float = __limitedParseFloat32(data.float); } + if (data.integer != null) { + contents.integer = __expectInt32(data.integer); + } + if (data.long != null) { + contents.long = __expectLong(data.long); + } if (data.maxByte != null) { contents.maxByte = __expectByte(data.maxByte); } if (data.maxFloat != null) { contents.maxFloat = __limitedParseFloat32(data.maxFloat); } + if (data.maxInteger != null) { + contents.maxInteger = __expectInt32(data.maxInteger); + } + if (data.maxLong != null) { + contents.maxLong = __expectLong(data.maxLong); + } + if (data.maxShort != null) { + contents.maxShort = __expectShort(data.maxShort); + } if (data.minByte != null) { contents.minByte = __expectByte(data.minByte); } if (data.minFloat != null) { contents.minFloat = __limitedParseFloat32(data.minFloat); } + if (data.minInteger != null) { + contents.minInteger = __expectInt32(data.minInteger); + } + if (data.minLong != null) { + contents.minLong = __expectLong(data.minLong); + } + if (data.minShort != null) { + contents.minShort = __expectShort(data.minShort); + } + if (data.short != null) { + contents.short = __expectShort(data.short); + } return contents; }; @@ -377,18 +407,45 @@ export const deserializeMalformedRangeOverrideRequest = async ( if (data.float != null) { contents.float = __limitedParseFloat32(data.float); } + if (data.integer != null) { + contents.integer = __expectInt32(data.integer); + } + if (data.long != null) { + contents.long = __expectLong(data.long); + } if (data.maxByte != null) { contents.maxByte = __expectByte(data.maxByte); } if (data.maxFloat != null) { contents.maxFloat = __limitedParseFloat32(data.maxFloat); } + if (data.maxInteger != null) { + contents.maxInteger = __expectInt32(data.maxInteger); + } + if (data.maxLong != null) { + contents.maxLong = __expectLong(data.maxLong); + } + if (data.maxShort != null) { + contents.maxShort = __expectShort(data.maxShort); + } if (data.minByte != null) { contents.minByte = __expectByte(data.minByte); } if (data.minFloat != null) { contents.minFloat = __limitedParseFloat32(data.minFloat); } + if (data.minInteger != null) { + contents.minInteger = __expectInt32(data.minInteger); + } + if (data.minLong != null) { + contents.minLong = __expectLong(data.minLong); + } + if (data.minShort != null) { + contents.minShort = __expectShort(data.minShort); + } + if (data.short != null) { + contents.short = __expectShort(data.short); + } return contents; }; diff --git a/private/aws-restjson-validation-server/test/functional/restjson1.spec.ts b/private/aws-restjson-validation-server/test/functional/restjson1.spec.ts index 6b3bdd7f780ee..5897ee2840999 100644 --- a/private/aws-restjson-validation-server/test/functional/restjson1.spec.ts +++ b/private/aws-restjson-validation-server/test/functional/restjson1.spec.ts @@ -2753,11 +2753,695 @@ it("RestJsonMalformedRangeMaxFloat:MalformedRequest", async () => { expect(unequalParts).toBeUndefined(); }); +/** + * When a short member does not fit within range bounds, + * the response should be a 400 ValidationException. + */ +it("RestJsonMalformedRangeShort_case0:MalformedRequest", async () => { + const testFunction = jest.fn(); + testFunction.mockImplementation(() => { + throw new Error("This request should have been rejected."); + }); + const testService: Partial> = { + MalformedRange: testFunction as MalformedRange<{}>, + }; + const handler = getRestJsonValidationServiceHandler(testService as RestJsonValidationService<{}>); + const request = new HttpRequest({ + method: "POST", + hostname: "foo.example.com", + path: "/MalformedRange", + query: {}, + headers: { + "content-type": "application/json", + }, + body: Readable.from(['{ "short" : 1 }']), + }); + const r = await handler.handle(request, {}); + + expect(testFunction.mock.calls.length).toBe(0); + expect(r.statusCode).toBe(400); + expect(r.headers["x-amzn-errortype"]).toBeDefined(); + expect(r.headers["x-amzn-errortype"]).toBe("ValidationException"); + + expect(r.body).toBeDefined(); + const utf8Encoder = __utf8Encoder; + const bodyString = `{ \"message\" : \"1 validation error detected. Value 1 at '/short' failed to satisfy constraint: Member must be between 2 and 8, inclusive\", + \"fieldList\" : [{\"message\": \"Value 1 at '/short' failed to satisfy constraint: Member must be between 2 and 8, inclusive\", \"path\": \"/short\"}]}`; + const unequalParts: any = compareEquivalentJsonBodies(bodyString, r.body.toString()); + expect(unequalParts).toBeUndefined(); +}); + +/** + * When a short member does not fit within range bounds, + * the response should be a 400 ValidationException. + */ +it("RestJsonMalformedRangeShort_case1:MalformedRequest", async () => { + const testFunction = jest.fn(); + testFunction.mockImplementation(() => { + throw new Error("This request should have been rejected."); + }); + const testService: Partial> = { + MalformedRange: testFunction as MalformedRange<{}>, + }; + const handler = getRestJsonValidationServiceHandler(testService as RestJsonValidationService<{}>); + const request = new HttpRequest({ + method: "POST", + hostname: "foo.example.com", + path: "/MalformedRange", + query: {}, + headers: { + "content-type": "application/json", + }, + body: Readable.from(['{ "short" : 9 }']), + }); + const r = await handler.handle(request, {}); + + expect(testFunction.mock.calls.length).toBe(0); + expect(r.statusCode).toBe(400); + expect(r.headers["x-amzn-errortype"]).toBeDefined(); + expect(r.headers["x-amzn-errortype"]).toBe("ValidationException"); + + expect(r.body).toBeDefined(); + const utf8Encoder = __utf8Encoder; + const bodyString = `{ \"message\" : \"1 validation error detected. Value 9 at '/short' failed to satisfy constraint: Member must be between 2 and 8, inclusive\", + \"fieldList\" : [{\"message\": \"Value 9 at '/short' failed to satisfy constraint: Member must be between 2 and 8, inclusive\", \"path\": \"/short\"}]}`; + const unequalParts: any = compareEquivalentJsonBodies(bodyString, r.body.toString()); + expect(unequalParts).toBeUndefined(); +}); + +/** + * When a short member does not fit within range bounds, + * the response should be a 400 ValidationException. + */ +it("RestJsonMalformedRangeMinShort:MalformedRequest", async () => { + const testFunction = jest.fn(); + testFunction.mockImplementation(() => { + throw new Error("This request should have been rejected."); + }); + const testService: Partial> = { + MalformedRange: testFunction as MalformedRange<{}>, + }; + const handler = getRestJsonValidationServiceHandler(testService as RestJsonValidationService<{}>); + const request = new HttpRequest({ + method: "POST", + hostname: "foo.example.com", + path: "/MalformedRange", + query: {}, + headers: { + "content-type": "application/json", + }, + body: Readable.from(['{ "minShort" : 1 }']), + }); + const r = await handler.handle(request, {}); + + expect(testFunction.mock.calls.length).toBe(0); + expect(r.statusCode).toBe(400); + expect(r.headers["x-amzn-errortype"]).toBeDefined(); + expect(r.headers["x-amzn-errortype"]).toBe("ValidationException"); + + expect(r.body).toBeDefined(); + const utf8Encoder = __utf8Encoder; + const bodyString = `{ \"message\" : \"1 validation error detected. Value 1 at '/minShort' failed to satisfy constraint: Member must be greater than or equal to 2\", + \"fieldList\" : [{\"message\": \"Value 1 at '/minShort' failed to satisfy constraint: Member must be greater than or equal to 2\", \"path\": \"/minShort\"}]}`; + const unequalParts: any = compareEquivalentJsonBodies(bodyString, r.body.toString()); + expect(unequalParts).toBeUndefined(); +}); + +/** + * When a short member does not fit within range bounds, + * the response should be a 400 ValidationException. + */ +it("RestJsonMalformedRangeMaxShort:MalformedRequest", async () => { + const testFunction = jest.fn(); + testFunction.mockImplementation(() => { + throw new Error("This request should have been rejected."); + }); + const testService: Partial> = { + MalformedRange: testFunction as MalformedRange<{}>, + }; + const handler = getRestJsonValidationServiceHandler(testService as RestJsonValidationService<{}>); + const request = new HttpRequest({ + method: "POST", + hostname: "foo.example.com", + path: "/MalformedRange", + query: {}, + headers: { + "content-type": "application/json", + }, + body: Readable.from(['{ "maxShort" : 9 }']), + }); + const r = await handler.handle(request, {}); + + expect(testFunction.mock.calls.length).toBe(0); + expect(r.statusCode).toBe(400); + expect(r.headers["x-amzn-errortype"]).toBeDefined(); + expect(r.headers["x-amzn-errortype"]).toBe("ValidationException"); + + expect(r.body).toBeDefined(); + const utf8Encoder = __utf8Encoder; + const bodyString = `{ \"message\" : \"1 validation error detected. Value 9 at '/maxShort' failed to satisfy constraint: Member must be less than or equal to 8\", + \"fieldList\" : [{\"message\": \"Value 9 at '/maxShort' failed to satisfy constraint: Member must be less than or equal to 8\", \"path\": \"/maxShort\"}]}`; + const unequalParts: any = compareEquivalentJsonBodies(bodyString, r.body.toString()); + expect(unequalParts).toBeUndefined(); +}); + +/** + * When a integer member does not fit within range bounds, + * the response should be a 400 ValidationException. + */ +it("RestJsonMalformedRangeInteger_case0:MalformedRequest", async () => { + const testFunction = jest.fn(); + testFunction.mockImplementation(() => { + throw new Error("This request should have been rejected."); + }); + const testService: Partial> = { + MalformedRange: testFunction as MalformedRange<{}>, + }; + const handler = getRestJsonValidationServiceHandler(testService as RestJsonValidationService<{}>); + const request = new HttpRequest({ + method: "POST", + hostname: "foo.example.com", + path: "/MalformedRange", + query: {}, + headers: { + "content-type": "application/json", + }, + body: Readable.from(['{ "integer" : 1 }']), + }); + const r = await handler.handle(request, {}); + + expect(testFunction.mock.calls.length).toBe(0); + expect(r.statusCode).toBe(400); + expect(r.headers["x-amzn-errortype"]).toBeDefined(); + expect(r.headers["x-amzn-errortype"]).toBe("ValidationException"); + + expect(r.body).toBeDefined(); + const utf8Encoder = __utf8Encoder; + const bodyString = `{ \"message\" : \"1 validation error detected. Value 1 at '/integer' failed to satisfy constraint: Member must be between 2 and 8, inclusive\", + \"fieldList\" : [{\"message\": \"Value 1 at '/integer' failed to satisfy constraint: Member must be between 2 and 8, inclusive\", \"path\": \"/integer\"}]}`; + const unequalParts: any = compareEquivalentJsonBodies(bodyString, r.body.toString()); + expect(unequalParts).toBeUndefined(); +}); + +/** + * When a integer member does not fit within range bounds, + * the response should be a 400 ValidationException. + */ +it("RestJsonMalformedRangeInteger_case1:MalformedRequest", async () => { + const testFunction = jest.fn(); + testFunction.mockImplementation(() => { + throw new Error("This request should have been rejected."); + }); + const testService: Partial> = { + MalformedRange: testFunction as MalformedRange<{}>, + }; + const handler = getRestJsonValidationServiceHandler(testService as RestJsonValidationService<{}>); + const request = new HttpRequest({ + method: "POST", + hostname: "foo.example.com", + path: "/MalformedRange", + query: {}, + headers: { + "content-type": "application/json", + }, + body: Readable.from(['{ "integer" : 9 }']), + }); + const r = await handler.handle(request, {}); + + expect(testFunction.mock.calls.length).toBe(0); + expect(r.statusCode).toBe(400); + expect(r.headers["x-amzn-errortype"]).toBeDefined(); + expect(r.headers["x-amzn-errortype"]).toBe("ValidationException"); + + expect(r.body).toBeDefined(); + const utf8Encoder = __utf8Encoder; + const bodyString = `{ \"message\" : \"1 validation error detected. Value 9 at '/integer' failed to satisfy constraint: Member must be between 2 and 8, inclusive\", + \"fieldList\" : [{\"message\": \"Value 9 at '/integer' failed to satisfy constraint: Member must be between 2 and 8, inclusive\", \"path\": \"/integer\"}]}`; + const unequalParts: any = compareEquivalentJsonBodies(bodyString, r.body.toString()); + expect(unequalParts).toBeUndefined(); +}); + +/** + * When a integer member does not fit within range bounds, + * the response should be a 400 ValidationException. + */ +it("RestJsonMalformedRangeMinInteger:MalformedRequest", async () => { + const testFunction = jest.fn(); + testFunction.mockImplementation(() => { + throw new Error("This request should have been rejected."); + }); + const testService: Partial> = { + MalformedRange: testFunction as MalformedRange<{}>, + }; + const handler = getRestJsonValidationServiceHandler(testService as RestJsonValidationService<{}>); + const request = new HttpRequest({ + method: "POST", + hostname: "foo.example.com", + path: "/MalformedRange", + query: {}, + headers: { + "content-type": "application/json", + }, + body: Readable.from(['{ "minInteger" : 1 }']), + }); + const r = await handler.handle(request, {}); + + expect(testFunction.mock.calls.length).toBe(0); + expect(r.statusCode).toBe(400); + expect(r.headers["x-amzn-errortype"]).toBeDefined(); + expect(r.headers["x-amzn-errortype"]).toBe("ValidationException"); + + expect(r.body).toBeDefined(); + const utf8Encoder = __utf8Encoder; + const bodyString = `{ \"message\" : \"1 validation error detected. Value 1 at '/minInteger' failed to satisfy constraint: Member must be greater than or equal to 2\", + \"fieldList\" : [{\"message\": \"Value 1 at '/minInteger' failed to satisfy constraint: Member must be greater than or equal to 2\", \"path\": \"/minInteger\"}]}`; + const unequalParts: any = compareEquivalentJsonBodies(bodyString, r.body.toString()); + expect(unequalParts).toBeUndefined(); +}); + +/** + * When a integer member does not fit within range bounds, + * the response should be a 400 ValidationException. + */ +it("RestJsonMalformedRangeMaxInteger:MalformedRequest", async () => { + const testFunction = jest.fn(); + testFunction.mockImplementation(() => { + throw new Error("This request should have been rejected."); + }); + const testService: Partial> = { + MalformedRange: testFunction as MalformedRange<{}>, + }; + const handler = getRestJsonValidationServiceHandler(testService as RestJsonValidationService<{}>); + const request = new HttpRequest({ + method: "POST", + hostname: "foo.example.com", + path: "/MalformedRange", + query: {}, + headers: { + "content-type": "application/json", + }, + body: Readable.from(['{ "maxInteger" : 9 }']), + }); + const r = await handler.handle(request, {}); + + expect(testFunction.mock.calls.length).toBe(0); + expect(r.statusCode).toBe(400); + expect(r.headers["x-amzn-errortype"]).toBeDefined(); + expect(r.headers["x-amzn-errortype"]).toBe("ValidationException"); + + expect(r.body).toBeDefined(); + const utf8Encoder = __utf8Encoder; + const bodyString = `{ \"message\" : \"1 validation error detected. Value 9 at '/maxInteger' failed to satisfy constraint: Member must be less than or equal to 8\", + \"fieldList\" : [{\"message\": \"Value 9 at '/maxInteger' failed to satisfy constraint: Member must be less than or equal to 8\", \"path\": \"/maxInteger\"}]}`; + const unequalParts: any = compareEquivalentJsonBodies(bodyString, r.body.toString()); + expect(unequalParts).toBeUndefined(); +}); + +/** + * When a long member does not fit within range bounds, + * the response should be a 400 ValidationException. + */ +it("RestJsonMalformedRangeLong_case0:MalformedRequest", async () => { + const testFunction = jest.fn(); + testFunction.mockImplementation(() => { + throw new Error("This request should have been rejected."); + }); + const testService: Partial> = { + MalformedRange: testFunction as MalformedRange<{}>, + }; + const handler = getRestJsonValidationServiceHandler(testService as RestJsonValidationService<{}>); + const request = new HttpRequest({ + method: "POST", + hostname: "foo.example.com", + path: "/MalformedRange", + query: {}, + headers: { + "content-type": "application/json", + }, + body: Readable.from(['{ "long" : 1 }']), + }); + const r = await handler.handle(request, {}); + + expect(testFunction.mock.calls.length).toBe(0); + expect(r.statusCode).toBe(400); + expect(r.headers["x-amzn-errortype"]).toBeDefined(); + expect(r.headers["x-amzn-errortype"]).toBe("ValidationException"); + + expect(r.body).toBeDefined(); + const utf8Encoder = __utf8Encoder; + const bodyString = `{ \"message\" : \"1 validation error detected. Value 1 at '/long' failed to satisfy constraint: Member must be between 2 and 8, inclusive\", + \"fieldList\" : [{\"message\": \"Value 1 at '/long' failed to satisfy constraint: Member must be between 2 and 8, inclusive\", \"path\": \"/long\"}]}`; + const unequalParts: any = compareEquivalentJsonBodies(bodyString, r.body.toString()); + expect(unequalParts).toBeUndefined(); +}); + +/** + * When a long member does not fit within range bounds, + * the response should be a 400 ValidationException. + */ +it("RestJsonMalformedRangeLong_case1:MalformedRequest", async () => { + const testFunction = jest.fn(); + testFunction.mockImplementation(() => { + throw new Error("This request should have been rejected."); + }); + const testService: Partial> = { + MalformedRange: testFunction as MalformedRange<{}>, + }; + const handler = getRestJsonValidationServiceHandler(testService as RestJsonValidationService<{}>); + const request = new HttpRequest({ + method: "POST", + hostname: "foo.example.com", + path: "/MalformedRange", + query: {}, + headers: { + "content-type": "application/json", + }, + body: Readable.from(['{ "long" : 9 }']), + }); + const r = await handler.handle(request, {}); + + expect(testFunction.mock.calls.length).toBe(0); + expect(r.statusCode).toBe(400); + expect(r.headers["x-amzn-errortype"]).toBeDefined(); + expect(r.headers["x-amzn-errortype"]).toBe("ValidationException"); + + expect(r.body).toBeDefined(); + const utf8Encoder = __utf8Encoder; + const bodyString = `{ \"message\" : \"1 validation error detected. Value 9 at '/long' failed to satisfy constraint: Member must be between 2 and 8, inclusive\", + \"fieldList\" : [{\"message\": \"Value 9 at '/long' failed to satisfy constraint: Member must be between 2 and 8, inclusive\", \"path\": \"/long\"}]}`; + const unequalParts: any = compareEquivalentJsonBodies(bodyString, r.body.toString()); + expect(unequalParts).toBeUndefined(); +}); + +/** + * When a long member does not fit within range bounds, + * the response should be a 400 ValidationException. + */ +it("RestJsonMalformedRangeMinLong:MalformedRequest", async () => { + const testFunction = jest.fn(); + testFunction.mockImplementation(() => { + throw new Error("This request should have been rejected."); + }); + const testService: Partial> = { + MalformedRange: testFunction as MalformedRange<{}>, + }; + const handler = getRestJsonValidationServiceHandler(testService as RestJsonValidationService<{}>); + const request = new HttpRequest({ + method: "POST", + hostname: "foo.example.com", + path: "/MalformedRange", + query: {}, + headers: { + "content-type": "application/json", + }, + body: Readable.from(['{ "minLong" : 1 }']), + }); + const r = await handler.handle(request, {}); + + expect(testFunction.mock.calls.length).toBe(0); + expect(r.statusCode).toBe(400); + expect(r.headers["x-amzn-errortype"]).toBeDefined(); + expect(r.headers["x-amzn-errortype"]).toBe("ValidationException"); + + expect(r.body).toBeDefined(); + const utf8Encoder = __utf8Encoder; + const bodyString = `{ \"message\" : \"1 validation error detected. Value 1 at '/minLong' failed to satisfy constraint: Member must be greater than or equal to 2\", + \"fieldList\" : [{\"message\": \"Value 1 at '/minLong' failed to satisfy constraint: Member must be greater than or equal to 2\", \"path\": \"/minLong\"}]}`; + const unequalParts: any = compareEquivalentJsonBodies(bodyString, r.body.toString()); + expect(unequalParts).toBeUndefined(); +}); + +/** + * When a long member does not fit within range bounds, + * the response should be a 400 ValidationException. + */ +it("RestJsonMalformedRangeMaxLong:MalformedRequest", async () => { + const testFunction = jest.fn(); + testFunction.mockImplementation(() => { + throw new Error("This request should have been rejected."); + }); + const testService: Partial> = { + MalformedRange: testFunction as MalformedRange<{}>, + }; + const handler = getRestJsonValidationServiceHandler(testService as RestJsonValidationService<{}>); + const request = new HttpRequest({ + method: "POST", + hostname: "foo.example.com", + path: "/MalformedRange", + query: {}, + headers: { + "content-type": "application/json", + }, + body: Readable.from(['{ "maxLong" : 9 }']), + }); + const r = await handler.handle(request, {}); + + expect(testFunction.mock.calls.length).toBe(0); + expect(r.statusCode).toBe(400); + expect(r.headers["x-amzn-errortype"]).toBeDefined(); + expect(r.headers["x-amzn-errortype"]).toBe("ValidationException"); + + expect(r.body).toBeDefined(); + const utf8Encoder = __utf8Encoder; + const bodyString = `{ \"message\" : \"1 validation error detected. Value 9 at '/maxLong' failed to satisfy constraint: Member must be less than or equal to 8\", + \"fieldList\" : [{\"message\": \"Value 9 at '/maxLong' failed to satisfy constraint: Member must be less than or equal to 8\", \"path\": \"/maxLong\"}]}`; + const unequalParts: any = compareEquivalentJsonBodies(bodyString, r.body.toString()); + expect(unequalParts).toBeUndefined(); +}); + +/** + * When a byte member does not fit within range bounds, + * the response should be a 400 ValidationException. + */ +it("RestJsonMalformedRangeByteOverride_case0:MalformedRequest", async () => { + const testFunction = jest.fn(); + testFunction.mockImplementation(() => { + throw new Error("This request should have been rejected."); + }); + const testService: Partial> = { + MalformedRangeOverride: testFunction as MalformedRangeOverride<{}>, + }; + const handler = getRestJsonValidationServiceHandler(testService as RestJsonValidationService<{}>); + const request = new HttpRequest({ + method: "POST", + hostname: "foo.example.com", + path: "/MalformedRangeOverride", + query: {}, + headers: { + "content-type": "application/json", + }, + body: Readable.from(['{ "byte" : 3 }']), + }); + const r = await handler.handle(request, {}); + + expect(testFunction.mock.calls.length).toBe(0); + expect(r.statusCode).toBe(400); + expect(r.headers["x-amzn-errortype"]).toBeDefined(); + expect(r.headers["x-amzn-errortype"]).toBe("ValidationException"); + + expect(r.body).toBeDefined(); + const utf8Encoder = __utf8Encoder; + const bodyString = `{ \"message\" : \"1 validation error detected. Value 3 at '/byte' failed to satisfy constraint: Member must be between 4 and 6, inclusive\", + \"fieldList\" : [{\"message\": \"Value 3 at '/byte' failed to satisfy constraint: Member must be between 4 and 6, inclusive\", \"path\": \"/byte\"}]}`; + const unequalParts: any = compareEquivalentJsonBodies(bodyString, r.body.toString()); + expect(unequalParts).toBeUndefined(); +}); + +/** + * When a byte member does not fit within range bounds, + * the response should be a 400 ValidationException. + */ +it("RestJsonMalformedRangeByteOverride_case1:MalformedRequest", async () => { + const testFunction = jest.fn(); + testFunction.mockImplementation(() => { + throw new Error("This request should have been rejected."); + }); + const testService: Partial> = { + MalformedRangeOverride: testFunction as MalformedRangeOverride<{}>, + }; + const handler = getRestJsonValidationServiceHandler(testService as RestJsonValidationService<{}>); + const request = new HttpRequest({ + method: "POST", + hostname: "foo.example.com", + path: "/MalformedRangeOverride", + query: {}, + headers: { + "content-type": "application/json", + }, + body: Readable.from(['{ "byte" : 7 }']), + }); + const r = await handler.handle(request, {}); + + expect(testFunction.mock.calls.length).toBe(0); + expect(r.statusCode).toBe(400); + expect(r.headers["x-amzn-errortype"]).toBeDefined(); + expect(r.headers["x-amzn-errortype"]).toBe("ValidationException"); + + expect(r.body).toBeDefined(); + const utf8Encoder = __utf8Encoder; + const bodyString = `{ \"message\" : \"1 validation error detected. Value 7 at '/byte' failed to satisfy constraint: Member must be between 4 and 6, inclusive\", + \"fieldList\" : [{\"message\": \"Value 7 at '/byte' failed to satisfy constraint: Member must be between 4 and 6, inclusive\", \"path\": \"/byte\"}]}`; + const unequalParts: any = compareEquivalentJsonBodies(bodyString, r.body.toString()); + expect(unequalParts).toBeUndefined(); +}); + +/** + * When a byte member does not fit within range bounds, + * the response should be a 400 ValidationException. + */ +it("RestJsonMalformedRangeMinByteOverride:MalformedRequest", async () => { + const testFunction = jest.fn(); + testFunction.mockImplementation(() => { + throw new Error("This request should have been rejected."); + }); + const testService: Partial> = { + MalformedRangeOverride: testFunction as MalformedRangeOverride<{}>, + }; + const handler = getRestJsonValidationServiceHandler(testService as RestJsonValidationService<{}>); + const request = new HttpRequest({ + method: "POST", + hostname: "foo.example.com", + path: "/MalformedRangeOverride", + query: {}, + headers: { + "content-type": "application/json", + }, + body: Readable.from(['{ "minByte" : 3 }']), + }); + const r = await handler.handle(request, {}); + + expect(testFunction.mock.calls.length).toBe(0); + expect(r.statusCode).toBe(400); + expect(r.headers["x-amzn-errortype"]).toBeDefined(); + expect(r.headers["x-amzn-errortype"]).toBe("ValidationException"); + + expect(r.body).toBeDefined(); + const utf8Encoder = __utf8Encoder; + const bodyString = `{ \"message\" : \"1 validation error detected. Value 3 at '/minByte' failed to satisfy constraint: Member must be greater than or equal to 4\", + \"fieldList\" : [{\"message\": \"Value 3 at '/minByte' failed to satisfy constraint: Member must be greater than or equal to 4\", \"path\": \"/minByte\"}]}`; + const unequalParts: any = compareEquivalentJsonBodies(bodyString, r.body.toString()); + expect(unequalParts).toBeUndefined(); +}); + /** * When a byte member does not fit within range bounds, * the response should be a 400 ValidationException. */ -it("RestJsonMalformedRangeByteOverride_case0:MalformedRequest", async () => { +it("RestJsonMalformedRangeMaxByteOverride:MalformedRequest", async () => { + const testFunction = jest.fn(); + testFunction.mockImplementation(() => { + throw new Error("This request should have been rejected."); + }); + const testService: Partial> = { + MalformedRangeOverride: testFunction as MalformedRangeOverride<{}>, + }; + const handler = getRestJsonValidationServiceHandler(testService as RestJsonValidationService<{}>); + const request = new HttpRequest({ + method: "POST", + hostname: "foo.example.com", + path: "/MalformedRangeOverride", + query: {}, + headers: { + "content-type": "application/json", + }, + body: Readable.from(['{ "maxByte" : 7 }']), + }); + const r = await handler.handle(request, {}); + + expect(testFunction.mock.calls.length).toBe(0); + expect(r.statusCode).toBe(400); + expect(r.headers["x-amzn-errortype"]).toBeDefined(); + expect(r.headers["x-amzn-errortype"]).toBe("ValidationException"); + + expect(r.body).toBeDefined(); + const utf8Encoder = __utf8Encoder; + const bodyString = `{ \"message\" : \"1 validation error detected. Value 7 at '/maxByte' failed to satisfy constraint: Member must be less than or equal to 6\", + \"fieldList\" : [{\"message\": \"Value 7 at '/maxByte' failed to satisfy constraint: Member must be less than or equal to 6\", \"path\": \"/maxByte\"}]}`; + const unequalParts: any = compareEquivalentJsonBodies(bodyString, r.body.toString()); + expect(unequalParts).toBeUndefined(); +}); + +/** + * When a float member does not fit within range bounds, + * the response should be a 400 ValidationException. + */ +it("RestJsonMalformedRangeFloatOverride_case0:MalformedRequest", async () => { + const testFunction = jest.fn(); + testFunction.mockImplementation(() => { + throw new Error("This request should have been rejected."); + }); + const testService: Partial> = { + MalformedRangeOverride: testFunction as MalformedRangeOverride<{}>, + }; + const handler = getRestJsonValidationServiceHandler(testService as RestJsonValidationService<{}>); + const request = new HttpRequest({ + method: "POST", + hostname: "foo.example.com", + path: "/MalformedRangeOverride", + query: {}, + headers: { + "content-type": "application/json", + }, + body: Readable.from(['{ "float" : 4.3 }']), + }); + const r = await handler.handle(request, {}); + + expect(testFunction.mock.calls.length).toBe(0); + expect(r.statusCode).toBe(400); + expect(r.headers["x-amzn-errortype"]).toBeDefined(); + expect(r.headers["x-amzn-errortype"]).toBe("ValidationException"); + + expect(r.body).toBeDefined(); + const utf8Encoder = __utf8Encoder; + const bodyString = `{ \"message\" : \"1 validation error detected. Value 4.3 at '/float' failed to satisfy constraint: Member must be between 4.4 and 6.6, inclusive\", + \"fieldList\" : [{\"message\": \"Value 4.3 at '/float' failed to satisfy constraint: Member must be between 4.4 and 6.6, inclusive\", \"path\": \"/float\"}]}`; + const unequalParts: any = compareEquivalentJsonBodies(bodyString, r.body.toString()); + expect(unequalParts).toBeUndefined(); +}); + +/** + * When a float member does not fit within range bounds, + * the response should be a 400 ValidationException. + */ +it("RestJsonMalformedRangeFloatOverride_case1:MalformedRequest", async () => { + const testFunction = jest.fn(); + testFunction.mockImplementation(() => { + throw new Error("This request should have been rejected."); + }); + const testService: Partial> = { + MalformedRangeOverride: testFunction as MalformedRangeOverride<{}>, + }; + const handler = getRestJsonValidationServiceHandler(testService as RestJsonValidationService<{}>); + const request = new HttpRequest({ + method: "POST", + hostname: "foo.example.com", + path: "/MalformedRangeOverride", + query: {}, + headers: { + "content-type": "application/json", + }, + body: Readable.from(['{ "float" : 6.7 }']), + }); + const r = await handler.handle(request, {}); + + expect(testFunction.mock.calls.length).toBe(0); + expect(r.statusCode).toBe(400); + expect(r.headers["x-amzn-errortype"]).toBeDefined(); + expect(r.headers["x-amzn-errortype"]).toBe("ValidationException"); + + expect(r.body).toBeDefined(); + const utf8Encoder = __utf8Encoder; + const bodyString = `{ \"message\" : \"1 validation error detected. Value 6.7 at '/float' failed to satisfy constraint: Member must be between 4.4 and 6.6, inclusive\", + \"fieldList\" : [{\"message\": \"Value 6.7 at '/float' failed to satisfy constraint: Member must be between 4.4 and 6.6, inclusive\", \"path\": \"/float\"}]}`; + const unequalParts: any = compareEquivalentJsonBodies(bodyString, r.body.toString()); + expect(unequalParts).toBeUndefined(); +}); + +/** + * When a float member does not fit within range bounds, + * the response should be a 400 ValidationException. + */ +it("RestJsonMalformedRangeMinFloatOverride:MalformedRequest", async () => { const testFunction = jest.fn(); testFunction.mockImplementation(() => { throw new Error("This request should have been rejected."); @@ -2774,7 +3458,7 @@ it("RestJsonMalformedRangeByteOverride_case0:MalformedRequest", async () => { headers: { "content-type": "application/json", }, - body: Readable.from(['{ "byte" : 3 }']), + body: Readable.from(['{ "minFloat" : 4.3 }']), }); const r = await handler.handle(request, {}); @@ -2785,17 +3469,17 @@ it("RestJsonMalformedRangeByteOverride_case0:MalformedRequest", async () => { expect(r.body).toBeDefined(); const utf8Encoder = __utf8Encoder; - const bodyString = `{ \"message\" : \"1 validation error detected. Value 3 at '/byte' failed to satisfy constraint: Member must be between 4 and 6, inclusive\", - \"fieldList\" : [{\"message\": \"Value 3 at '/byte' failed to satisfy constraint: Member must be between 4 and 6, inclusive\", \"path\": \"/byte\"}]}`; + const bodyString = `{ \"message\" : \"1 validation error detected. Value 4.3 at '/minFloat' failed to satisfy constraint: Member must be greater than or equal to 4.4\", + \"fieldList\" : [{\"message\": \"Value 4.3 at '/minFloat' failed to satisfy constraint: Member must be greater than or equal to 4.4\", \"path\": \"/minFloat\"}]}`; const unequalParts: any = compareEquivalentJsonBodies(bodyString, r.body.toString()); expect(unequalParts).toBeUndefined(); }); /** - * When a byte member does not fit within range bounds, + * When a float member does not fit within range bounds, * the response should be a 400 ValidationException. */ -it("RestJsonMalformedRangeByteOverride_case1:MalformedRequest", async () => { +it("RestJsonMalformedRangeMaxFloatOverride:MalformedRequest", async () => { const testFunction = jest.fn(); testFunction.mockImplementation(() => { throw new Error("This request should have been rejected."); @@ -2812,7 +3496,7 @@ it("RestJsonMalformedRangeByteOverride_case1:MalformedRequest", async () => { headers: { "content-type": "application/json", }, - body: Readable.from(['{ "byte" : 7 }']), + body: Readable.from(['{ "maxFloat" : 6.7 }']), }); const r = await handler.handle(request, {}); @@ -2823,17 +3507,17 @@ it("RestJsonMalformedRangeByteOverride_case1:MalformedRequest", async () => { expect(r.body).toBeDefined(); const utf8Encoder = __utf8Encoder; - const bodyString = `{ \"message\" : \"1 validation error detected. Value 7 at '/byte' failed to satisfy constraint: Member must be between 4 and 6, inclusive\", - \"fieldList\" : [{\"message\": \"Value 7 at '/byte' failed to satisfy constraint: Member must be between 4 and 6, inclusive\", \"path\": \"/byte\"}]}`; + const bodyString = `{ \"message\" : \"1 validation error detected. Value 6.7 at '/maxFloat' failed to satisfy constraint: Member must be less than or equal to 6.6\", + \"fieldList\" : [{\"message\": \"Value 6.7 at '/maxFloat' failed to satisfy constraint: Member must be less than or equal to 6.6\", \"path\": \"/maxFloat\"}]}`; const unequalParts: any = compareEquivalentJsonBodies(bodyString, r.body.toString()); expect(unequalParts).toBeUndefined(); }); /** - * When a byte member does not fit within range bounds, + * When a short member does not fit within range bounds, * the response should be a 400 ValidationException. */ -it("RestJsonMalformedRangeMinByteOverride:MalformedRequest", async () => { +it("RestJsonMalformedRangeShortOverride_case0:MalformedRequest", async () => { const testFunction = jest.fn(); testFunction.mockImplementation(() => { throw new Error("This request should have been rejected."); @@ -2850,7 +3534,7 @@ it("RestJsonMalformedRangeMinByteOverride:MalformedRequest", async () => { headers: { "content-type": "application/json", }, - body: Readable.from(['{ "minByte" : 3 }']), + body: Readable.from(['{ "short" : 3 }']), }); const r = await handler.handle(request, {}); @@ -2861,17 +3545,17 @@ it("RestJsonMalformedRangeMinByteOverride:MalformedRequest", async () => { expect(r.body).toBeDefined(); const utf8Encoder = __utf8Encoder; - const bodyString = `{ \"message\" : \"1 validation error detected. Value 3 at '/minByte' failed to satisfy constraint: Member must be greater than or equal to 4\", - \"fieldList\" : [{\"message\": \"Value 3 at '/minByte' failed to satisfy constraint: Member must be greater than or equal to 4\", \"path\": \"/minByte\"}]}`; + const bodyString = `{ \"message\" : \"1 validation error detected. Value 3 at '/short' failed to satisfy constraint: Member must be between 4 and 6, inclusive\", + \"fieldList\" : [{\"message\": \"Value 3 at '/short' failed to satisfy constraint: Member must be between 4 and 6, inclusive\", \"path\": \"/short\"}]}`; const unequalParts: any = compareEquivalentJsonBodies(bodyString, r.body.toString()); expect(unequalParts).toBeUndefined(); }); /** - * When a byte member does not fit within range bounds, + * When a short member does not fit within range bounds, * the response should be a 400 ValidationException. */ -it("RestJsonMalformedRangeMaxByteOverride:MalformedRequest", async () => { +it("RestJsonMalformedRangeShortOverride_case1:MalformedRequest", async () => { const testFunction = jest.fn(); testFunction.mockImplementation(() => { throw new Error("This request should have been rejected."); @@ -2888,7 +3572,7 @@ it("RestJsonMalformedRangeMaxByteOverride:MalformedRequest", async () => { headers: { "content-type": "application/json", }, - body: Readable.from(['{ "maxByte" : 7 }']), + body: Readable.from(['{ "short" : 7 }']), }); const r = await handler.handle(request, {}); @@ -2899,17 +3583,17 @@ it("RestJsonMalformedRangeMaxByteOverride:MalformedRequest", async () => { expect(r.body).toBeDefined(); const utf8Encoder = __utf8Encoder; - const bodyString = `{ \"message\" : \"1 validation error detected. Value 7 at '/maxByte' failed to satisfy constraint: Member must be less than or equal to 6\", - \"fieldList\" : [{\"message\": \"Value 7 at '/maxByte' failed to satisfy constraint: Member must be less than or equal to 6\", \"path\": \"/maxByte\"}]}`; + const bodyString = `{ \"message\" : \"1 validation error detected. Value 7 at '/short' failed to satisfy constraint: Member must be between 4 and 6, inclusive\", + \"fieldList\" : [{\"message\": \"Value 7 at '/short' failed to satisfy constraint: Member must be between 4 and 6, inclusive\", \"path\": \"/short\"}]}`; const unequalParts: any = compareEquivalentJsonBodies(bodyString, r.body.toString()); expect(unequalParts).toBeUndefined(); }); /** - * When a float member does not fit within range bounds, + * When a short member does not fit within range bounds, * the response should be a 400 ValidationException. */ -it("RestJsonMalformedRangeFloatOverride_case0:MalformedRequest", async () => { +it("RestJsonMalformedRangeMinShortOverride:MalformedRequest", async () => { const testFunction = jest.fn(); testFunction.mockImplementation(() => { throw new Error("This request should have been rejected."); @@ -2926,7 +3610,7 @@ it("RestJsonMalformedRangeFloatOverride_case0:MalformedRequest", async () => { headers: { "content-type": "application/json", }, - body: Readable.from(['{ "float" : 4.3 }']), + body: Readable.from(['{ "minShort" : 3 }']), }); const r = await handler.handle(request, {}); @@ -2937,17 +3621,17 @@ it("RestJsonMalformedRangeFloatOverride_case0:MalformedRequest", async () => { expect(r.body).toBeDefined(); const utf8Encoder = __utf8Encoder; - const bodyString = `{ \"message\" : \"1 validation error detected. Value 4.3 at '/float' failed to satisfy constraint: Member must be between 4.4 and 6.6, inclusive\", - \"fieldList\" : [{\"message\": \"Value 4.3 at '/float' failed to satisfy constraint: Member must be between 4.4 and 6.6, inclusive\", \"path\": \"/float\"}]}`; + const bodyString = `{ \"message\" : \"1 validation error detected. Value 3 at '/minShort' failed to satisfy constraint: Member must be greater than or equal to 4\", + \"fieldList\" : [{\"message\": \"Value 3 at '/minShort' failed to satisfy constraint: Member must be greater than or equal to 4\", \"path\": \"/minShort\"}]}`; const unequalParts: any = compareEquivalentJsonBodies(bodyString, r.body.toString()); expect(unequalParts).toBeUndefined(); }); /** - * When a float member does not fit within range bounds, + * When a short member does not fit within range bounds, * the response should be a 400 ValidationException. */ -it("RestJsonMalformedRangeFloatOverride_case1:MalformedRequest", async () => { +it("RestJsonMalformedRangeMaxShortOverride:MalformedRequest", async () => { const testFunction = jest.fn(); testFunction.mockImplementation(() => { throw new Error("This request should have been rejected."); @@ -2964,7 +3648,7 @@ it("RestJsonMalformedRangeFloatOverride_case1:MalformedRequest", async () => { headers: { "content-type": "application/json", }, - body: Readable.from(['{ "float" : 6.7 }']), + body: Readable.from(['{ "maxShort" : 7 }']), }); const r = await handler.handle(request, {}); @@ -2975,17 +3659,17 @@ it("RestJsonMalformedRangeFloatOverride_case1:MalformedRequest", async () => { expect(r.body).toBeDefined(); const utf8Encoder = __utf8Encoder; - const bodyString = `{ \"message\" : \"1 validation error detected. Value 6.7 at '/float' failed to satisfy constraint: Member must be between 4.4 and 6.6, inclusive\", - \"fieldList\" : [{\"message\": \"Value 6.7 at '/float' failed to satisfy constraint: Member must be between 4.4 and 6.6, inclusive\", \"path\": \"/float\"}]}`; + const bodyString = `{ \"message\" : \"1 validation error detected. Value 7 at '/maxShort' failed to satisfy constraint: Member must be less than or equal to 6\", + \"fieldList\" : [{\"message\": \"Value 7 at '/maxShort' failed to satisfy constraint: Member must be less than or equal to 6\", \"path\": \"/maxShort\"}]}`; const unequalParts: any = compareEquivalentJsonBodies(bodyString, r.body.toString()); expect(unequalParts).toBeUndefined(); }); /** - * When a float member does not fit within range bounds, + * When a integer member does not fit within range bounds, * the response should be a 400 ValidationException. */ -it("RestJsonMalformedRangeMinFloatOverride:MalformedRequest", async () => { +it("RestJsonMalformedRangeIntegerOverride_case0:MalformedRequest", async () => { const testFunction = jest.fn(); testFunction.mockImplementation(() => { throw new Error("This request should have been rejected."); @@ -3002,7 +3686,7 @@ it("RestJsonMalformedRangeMinFloatOverride:MalformedRequest", async () => { headers: { "content-type": "application/json", }, - body: Readable.from(['{ "minFloat" : 4.3 }']), + body: Readable.from(['{ "integer" : 3 }']), }); const r = await handler.handle(request, {}); @@ -3013,17 +3697,17 @@ it("RestJsonMalformedRangeMinFloatOverride:MalformedRequest", async () => { expect(r.body).toBeDefined(); const utf8Encoder = __utf8Encoder; - const bodyString = `{ \"message\" : \"1 validation error detected. Value 4.3 at '/minFloat' failed to satisfy constraint: Member must be greater than or equal to 4.4\", - \"fieldList\" : [{\"message\": \"Value 4.3 at '/minFloat' failed to satisfy constraint: Member must be greater than or equal to 4.4\", \"path\": \"/minFloat\"}]}`; + const bodyString = `{ \"message\" : \"1 validation error detected. Value 3 at '/integer' failed to satisfy constraint: Member must be between 4 and 6, inclusive\", + \"fieldList\" : [{\"message\": \"Value 3 at '/integer' failed to satisfy constraint: Member must be between 4 and 6, inclusive\", \"path\": \"/integer\"}]}`; const unequalParts: any = compareEquivalentJsonBodies(bodyString, r.body.toString()); expect(unequalParts).toBeUndefined(); }); /** - * When a float member does not fit within range bounds, + * When a integer member does not fit within range bounds, * the response should be a 400 ValidationException. */ -it("RestJsonMalformedRangeMaxFloatOverride:MalformedRequest", async () => { +it("RestJsonMalformedRangeIntegerOverride_case1:MalformedRequest", async () => { const testFunction = jest.fn(); testFunction.mockImplementation(() => { throw new Error("This request should have been rejected."); @@ -3040,7 +3724,7 @@ it("RestJsonMalformedRangeMaxFloatOverride:MalformedRequest", async () => { headers: { "content-type": "application/json", }, - body: Readable.from(['{ "maxFloat" : 6.7 }']), + body: Readable.from(['{ "integer" : 7 }']), }); const r = await handler.handle(request, {}); @@ -3051,8 +3735,236 @@ it("RestJsonMalformedRangeMaxFloatOverride:MalformedRequest", async () => { expect(r.body).toBeDefined(); const utf8Encoder = __utf8Encoder; - const bodyString = `{ \"message\" : \"1 validation error detected. Value 6.7 at '/maxFloat' failed to satisfy constraint: Member must be less than or equal to 6.6\", - \"fieldList\" : [{\"message\": \"Value 6.7 at '/maxFloat' failed to satisfy constraint: Member must be less than or equal to 6.6\", \"path\": \"/maxFloat\"}]}`; + const bodyString = `{ \"message\" : \"1 validation error detected. Value 7 at '/integer' failed to satisfy constraint: Member must be between 4 and 6, inclusive\", + \"fieldList\" : [{\"message\": \"Value 7 at '/integer' failed to satisfy constraint: Member must be between 4 and 6, inclusive\", \"path\": \"/integer\"}]}`; + const unequalParts: any = compareEquivalentJsonBodies(bodyString, r.body.toString()); + expect(unequalParts).toBeUndefined(); +}); + +/** + * When a integer member does not fit within range bounds, + * the response should be a 400 ValidationException. + */ +it("RestJsonMalformedRangeMinIntegerOverride:MalformedRequest", async () => { + const testFunction = jest.fn(); + testFunction.mockImplementation(() => { + throw new Error("This request should have been rejected."); + }); + const testService: Partial> = { + MalformedRangeOverride: testFunction as MalformedRangeOverride<{}>, + }; + const handler = getRestJsonValidationServiceHandler(testService as RestJsonValidationService<{}>); + const request = new HttpRequest({ + method: "POST", + hostname: "foo.example.com", + path: "/MalformedRangeOverride", + query: {}, + headers: { + "content-type": "application/json", + }, + body: Readable.from(['{ "minInteger" : 3 }']), + }); + const r = await handler.handle(request, {}); + + expect(testFunction.mock.calls.length).toBe(0); + expect(r.statusCode).toBe(400); + expect(r.headers["x-amzn-errortype"]).toBeDefined(); + expect(r.headers["x-amzn-errortype"]).toBe("ValidationException"); + + expect(r.body).toBeDefined(); + const utf8Encoder = __utf8Encoder; + const bodyString = `{ \"message\" : \"1 validation error detected. Value 3 at '/minInteger' failed to satisfy constraint: Member must be greater than or equal to 4\", + \"fieldList\" : [{\"message\": \"Value 3 at '/minInteger' failed to satisfy constraint: Member must be greater than or equal to 4\", \"path\": \"/minInteger\"}]}`; + const unequalParts: any = compareEquivalentJsonBodies(bodyString, r.body.toString()); + expect(unequalParts).toBeUndefined(); +}); + +/** + * When a integer member does not fit within range bounds, + * the response should be a 400 ValidationException. + */ +it("RestJsonMalformedRangeMaxIntegerOverride:MalformedRequest", async () => { + const testFunction = jest.fn(); + testFunction.mockImplementation(() => { + throw new Error("This request should have been rejected."); + }); + const testService: Partial> = { + MalformedRangeOverride: testFunction as MalformedRangeOverride<{}>, + }; + const handler = getRestJsonValidationServiceHandler(testService as RestJsonValidationService<{}>); + const request = new HttpRequest({ + method: "POST", + hostname: "foo.example.com", + path: "/MalformedRangeOverride", + query: {}, + headers: { + "content-type": "application/json", + }, + body: Readable.from(['{ "maxInteger" : 7 }']), + }); + const r = await handler.handle(request, {}); + + expect(testFunction.mock.calls.length).toBe(0); + expect(r.statusCode).toBe(400); + expect(r.headers["x-amzn-errortype"]).toBeDefined(); + expect(r.headers["x-amzn-errortype"]).toBe("ValidationException"); + + expect(r.body).toBeDefined(); + const utf8Encoder = __utf8Encoder; + const bodyString = `{ \"message\" : \"1 validation error detected. Value 7 at '/maxInteger' failed to satisfy constraint: Member must be less than or equal to 6\", + \"fieldList\" : [{\"message\": \"Value 7 at '/maxInteger' failed to satisfy constraint: Member must be less than or equal to 6\", \"path\": \"/maxInteger\"}]}`; + const unequalParts: any = compareEquivalentJsonBodies(bodyString, r.body.toString()); + expect(unequalParts).toBeUndefined(); +}); + +/** + * When a long member does not fit within range bounds, + * the response should be a 400 ValidationException. + */ +it("RestJsonMalformedRangeLongOverride_case0:MalformedRequest", async () => { + const testFunction = jest.fn(); + testFunction.mockImplementation(() => { + throw new Error("This request should have been rejected."); + }); + const testService: Partial> = { + MalformedRangeOverride: testFunction as MalformedRangeOverride<{}>, + }; + const handler = getRestJsonValidationServiceHandler(testService as RestJsonValidationService<{}>); + const request = new HttpRequest({ + method: "POST", + hostname: "foo.example.com", + path: "/MalformedRangeOverride", + query: {}, + headers: { + "content-type": "application/json", + }, + body: Readable.from(['{ "long" : 3 }']), + }); + const r = await handler.handle(request, {}); + + expect(testFunction.mock.calls.length).toBe(0); + expect(r.statusCode).toBe(400); + expect(r.headers["x-amzn-errortype"]).toBeDefined(); + expect(r.headers["x-amzn-errortype"]).toBe("ValidationException"); + + expect(r.body).toBeDefined(); + const utf8Encoder = __utf8Encoder; + const bodyString = `{ \"message\" : \"1 validation error detected. Value 3 at '/long' failed to satisfy constraint: Member must be between 4 and 6, inclusive\", + \"fieldList\" : [{\"message\": \"Value 3 at '/long' failed to satisfy constraint: Member must be between 4 and 6, inclusive\", \"path\": \"/long\"}]}`; + const unequalParts: any = compareEquivalentJsonBodies(bodyString, r.body.toString()); + expect(unequalParts).toBeUndefined(); +}); + +/** + * When a long member does not fit within range bounds, + * the response should be a 400 ValidationException. + */ +it("RestJsonMalformedRangeLongOverride_case1:MalformedRequest", async () => { + const testFunction = jest.fn(); + testFunction.mockImplementation(() => { + throw new Error("This request should have been rejected."); + }); + const testService: Partial> = { + MalformedRangeOverride: testFunction as MalformedRangeOverride<{}>, + }; + const handler = getRestJsonValidationServiceHandler(testService as RestJsonValidationService<{}>); + const request = new HttpRequest({ + method: "POST", + hostname: "foo.example.com", + path: "/MalformedRangeOverride", + query: {}, + headers: { + "content-type": "application/json", + }, + body: Readable.from(['{ "long" : 7 }']), + }); + const r = await handler.handle(request, {}); + + expect(testFunction.mock.calls.length).toBe(0); + expect(r.statusCode).toBe(400); + expect(r.headers["x-amzn-errortype"]).toBeDefined(); + expect(r.headers["x-amzn-errortype"]).toBe("ValidationException"); + + expect(r.body).toBeDefined(); + const utf8Encoder = __utf8Encoder; + const bodyString = `{ \"message\" : \"1 validation error detected. Value 7 at '/long' failed to satisfy constraint: Member must be between 4 and 6, inclusive\", + \"fieldList\" : [{\"message\": \"Value 7 at '/long' failed to satisfy constraint: Member must be between 4 and 6, inclusive\", \"path\": \"/long\"}]}`; + const unequalParts: any = compareEquivalentJsonBodies(bodyString, r.body.toString()); + expect(unequalParts).toBeUndefined(); +}); + +/** + * When a long member does not fit within range bounds, + * the response should be a 400 ValidationException. + */ +it("RestJsonMalformedRangeMinLongOverride:MalformedRequest", async () => { + const testFunction = jest.fn(); + testFunction.mockImplementation(() => { + throw new Error("This request should have been rejected."); + }); + const testService: Partial> = { + MalformedRangeOverride: testFunction as MalformedRangeOverride<{}>, + }; + const handler = getRestJsonValidationServiceHandler(testService as RestJsonValidationService<{}>); + const request = new HttpRequest({ + method: "POST", + hostname: "foo.example.com", + path: "/MalformedRangeOverride", + query: {}, + headers: { + "content-type": "application/json", + }, + body: Readable.from(['{ "minLong" : 3 }']), + }); + const r = await handler.handle(request, {}); + + expect(testFunction.mock.calls.length).toBe(0); + expect(r.statusCode).toBe(400); + expect(r.headers["x-amzn-errortype"]).toBeDefined(); + expect(r.headers["x-amzn-errortype"]).toBe("ValidationException"); + + expect(r.body).toBeDefined(); + const utf8Encoder = __utf8Encoder; + const bodyString = `{ \"message\" : \"1 validation error detected. Value 3 at '/minLong' failed to satisfy constraint: Member must be greater than or equal to 4\", + \"fieldList\" : [{\"message\": \"Value 3 at '/minLong' failed to satisfy constraint: Member must be greater than or equal to 4\", \"path\": \"/minLong\"}]}`; + const unequalParts: any = compareEquivalentJsonBodies(bodyString, r.body.toString()); + expect(unequalParts).toBeUndefined(); +}); + +/** + * When a long member does not fit within range bounds, + * the response should be a 400 ValidationException. + */ +it("RestJsonMalformedRangeMaxLongOverride:MalformedRequest", async () => { + const testFunction = jest.fn(); + testFunction.mockImplementation(() => { + throw new Error("This request should have been rejected."); + }); + const testService: Partial> = { + MalformedRangeOverride: testFunction as MalformedRangeOverride<{}>, + }; + const handler = getRestJsonValidationServiceHandler(testService as RestJsonValidationService<{}>); + const request = new HttpRequest({ + method: "POST", + hostname: "foo.example.com", + path: "/MalformedRangeOverride", + query: {}, + headers: { + "content-type": "application/json", + }, + body: Readable.from(['{ "maxLong" : 7 }']), + }); + const r = await handler.handle(request, {}); + + expect(testFunction.mock.calls.length).toBe(0); + expect(r.statusCode).toBe(400); + expect(r.headers["x-amzn-errortype"]).toBeDefined(); + expect(r.headers["x-amzn-errortype"]).toBe("ValidationException"); + + expect(r.body).toBeDefined(); + const utf8Encoder = __utf8Encoder; + const bodyString = `{ \"message\" : \"1 validation error detected. Value 7 at '/maxLong' failed to satisfy constraint: Member must be less than or equal to 6\", + \"fieldList\" : [{\"message\": \"Value 7 at '/maxLong' failed to satisfy constraint: Member must be less than or equal to 6\", \"path\": \"/maxLong\"}]}`; const unequalParts: any = compareEquivalentJsonBodies(bodyString, r.body.toString()); expect(unequalParts).toBeUndefined(); });