From 8fcdbfec40ce51cda3d79b03fcc6f70522b085f7 Mon Sep 17 00:00:00 2001 From: marcodalessandro Date: Wed, 27 Oct 2021 17:03:08 -0700 Subject: [PATCH] [@azure/event-hubs] Adding `disableDeserialization` option when subscribing (#18173) --- sdk/eventhub/event-hubs/CHANGELOG.md | 3 +- sdk/eventhub/event-hubs/package.json | 2 +- .../event-hubs/review/event-hubs.api.md | 1 + .../event-hubs/src/dataTransformer.ts | 13 +- sdk/eventhub/event-hubs/src/eventData.ts | 8 +- .../src/eventHubConsumerClientModels.ts | 6 + .../event-hubs/src/eventHubReceiver.ts | 6 +- sdk/eventhub/event-hubs/src/models/private.ts | 12 +- sdk/eventhub/event-hubs/src/partitionPump.ts | 3 +- sdk/eventhub/event-hubs/src/util/constants.ts | 2 +- .../event-hubs/test/internal/amqp.spec.ts | 26 +- .../test/internal/dataTransformer.spec.ts | 296 +++++++++++++----- .../test/internal/eventdata.spec.ts | 106 ++++--- 13 files changed, 331 insertions(+), 153 deletions(-) diff --git a/sdk/eventhub/event-hubs/CHANGELOG.md b/sdk/eventhub/event-hubs/CHANGELOG.md index 8d28b086e7e8..6551fbfdfdd0 100644 --- a/sdk/eventhub/event-hubs/CHANGELOG.md +++ b/sdk/eventhub/event-hubs/CHANGELOG.md @@ -1,8 +1,9 @@ # Release History -## 5.6.1 (Unreleased) +## 5.7.0 (Unreleased) ### Features Added +- Added `skipParsingBodyAsJson` optional parameter to `EventHubConsumerClient.subscribe` method. When set to `true` it will disable the client from running `JSON.parse()` on the message body when receiving the message. Not applicable if the message was sent with AMQP body type `value` or `sequence`. ### Breaking Changes diff --git a/sdk/eventhub/event-hubs/package.json b/sdk/eventhub/event-hubs/package.json index f2a6a4f93aa5..cd39e524764c 100644 --- a/sdk/eventhub/event-hubs/package.json +++ b/sdk/eventhub/event-hubs/package.json @@ -1,7 +1,7 @@ { "name": "@azure/event-hubs", "sdk-type": "client", - "version": "5.6.1", + "version": "5.7.0", "description": "Azure Event Hubs SDK for JS.", "author": "Microsoft Corporation", "license": "MIT", diff --git a/sdk/eventhub/event-hubs/review/event-hubs.api.md b/sdk/eventhub/event-hubs/review/event-hubs.api.md index 9a2d13787a1d..938214a25cd2 100644 --- a/sdk/eventhub/event-hubs/review/event-hubs.api.md +++ b/sdk/eventhub/event-hubs/review/event-hubs.api.md @@ -277,6 +277,7 @@ export interface SubscribeOptions { maxBatchSize?: number; maxWaitTimeInSeconds?: number; ownerLevel?: number; + skipParsingBodyAsJson?: boolean; startPosition?: EventPosition | { [partitionId: string]: EventPosition; }; diff --git a/sdk/eventhub/event-hubs/src/dataTransformer.ts b/sdk/eventhub/event-hubs/src/dataTransformer.ts index d26361922b08..ab4d1e912b78 100644 --- a/sdk/eventhub/event-hubs/src/dataTransformer.ts +++ b/sdk/eventhub/event-hubs/src/dataTransformer.ts @@ -75,14 +75,21 @@ export const defaultDataTransformer = { * indicating which part of the AMQP message the body was decoded from. * * @param body - The AMQP message body as received from rhea. + * @param skipParsingBodyAsJson - Boolean to skip running JSON.parse() on message body when body type is `content`. * @returns The decoded/raw body and the body type. */ - decode(body: unknown | RheaAmqpSection): { body: unknown; bodyType: BodyTypes } { + decode( + body: unknown | RheaAmqpSection, + skipParsingBodyAsJson: boolean + ): { body: unknown; bodyType: BodyTypes } { try { if (isRheaAmqpSection(body)) { switch (body.typecode) { case dataSectionTypeCode: - return { body: tryToJsonDecode(body.content), bodyType: "data" }; + return { + body: skipParsingBodyAsJson ? body.content : tryToJsonDecode(body.content), + bodyType: "data" + }; case sequenceSectionTypeCode: return { body: body.content, bodyType: "sequence" }; case valueSectionTypeCode: @@ -90,7 +97,7 @@ export const defaultDataTransformer = { } } else { if (isBuffer(body)) { - return { body: tryToJsonDecode(body), bodyType: "data" }; + return { body: skipParsingBodyAsJson ? body : tryToJsonDecode(body), bodyType: "data" }; } return { body, bodyType: "value" }; diff --git a/sdk/eventhub/event-hubs/src/eventData.ts b/sdk/eventhub/event-hubs/src/eventData.ts index 2684a0a4f5a0..d32a5affc5ef 100644 --- a/sdk/eventhub/event-hubs/src/eventData.ts +++ b/sdk/eventhub/event-hubs/src/eventData.ts @@ -156,11 +156,15 @@ const messagePropertiesMap = { /** * Converts the AMQP message to an EventData. * @param msg - The AMQP message that needs to be converted to EventData. + * @param skipParsingBodyAsJson - Boolean to skip running JSON.parse() on message body when body type is `content`. * @hidden */ -export function fromRheaMessage(msg: RheaMessage): EventDataInternal { +export function fromRheaMessage( + msg: RheaMessage, + skipParsingBodyAsJson: boolean +): EventDataInternal { const rawMessage = AmqpAnnotatedMessage.fromRheaMessage(msg); - const { body, bodyType } = defaultDataTransformer.decode(msg.body); + const { body, bodyType } = defaultDataTransformer.decode(msg.body, skipParsingBodyAsJson); rawMessage.bodyType = bodyType; const data: EventDataInternal = { diff --git a/sdk/eventhub/event-hubs/src/eventHubConsumerClientModels.ts b/sdk/eventhub/event-hubs/src/eventHubConsumerClientModels.ts index 904fc4d24a52..4d98ec00a354 100644 --- a/sdk/eventhub/event-hubs/src/eventHubConsumerClientModels.ts +++ b/sdk/eventhub/event-hubs/src/eventHubConsumerClientModels.ts @@ -198,6 +198,12 @@ export interface SubscribeOptions { * Options for configuring tracing. */ tracingOptions?: OperationTracingOptions; + /** + * Option to disable the client from running JSON.parse() on the message body when receiving the message. + * Not applicable if the message was sent with AMQP body type value or sequence. Use this option when you + * prefer to work directly with the bytes present in the message body than have the client attempt to parse it. + */ + skipParsingBodyAsJson?: boolean; } /** diff --git a/sdk/eventhub/event-hubs/src/eventHubReceiver.ts b/sdk/eventhub/event-hubs/src/eventHubReceiver.ts index b0d97fe83b6b..d9472eb27114 100644 --- a/sdk/eventhub/event-hubs/src/eventHubReceiver.ts +++ b/sdk/eventhub/event-hubs/src/eventHubReceiver.ts @@ -221,8 +221,10 @@ export class EventHubReceiver extends LinkEntity { if (!context.message) { return; } - - const data: EventDataInternal = fromRheaMessage(context.message); + const data: EventDataInternal = fromRheaMessage( + context.message, + !!this.options.skipParsingBodyAsJson + ); const rawMessage = data.getRawAmqpMessage(); const receivedEventData: ReceivedEventData = { body: data.body, diff --git a/sdk/eventhub/event-hubs/src/models/private.ts b/sdk/eventhub/event-hubs/src/models/private.ts index c2e0f6bad922..4946020a0d0e 100644 --- a/sdk/eventhub/event-hubs/src/models/private.ts +++ b/sdk/eventhub/event-hubs/src/models/private.ts @@ -76,6 +76,9 @@ export interface CommonEventProcessorOptions * consumers to fail if their `ownerLevel` is lower or doesn't exist. * - `retryOptions`: The retry options used to govern retry attempts when an issue is encountered while receiving events. * A simple usage can be `{ "maxRetries": 4 }`. + * - `skipParsingBodyAsJson` : Option to disable the client from running JSON.parse() on the message body when receiving the message. + * Not applicable if the message was sent with AMQP body type value or sequence. Use this option when you prefer to work directly with + * the bytes present in the message body than have the client attempt to parse it. * * Example usage: * ```js @@ -83,7 +86,8 @@ export interface CommonEventProcessorOptions * retryOptions: { * maxRetries: 4 * }, - * trackLastEnqueuedEventProperties: false + * trackLastEnqueuedEventProperties: false, + * skipParsingBodyAsJson: true * } * ``` * @internal @@ -113,4 +117,10 @@ export interface EventHubConsumerOptions { * against periodically making requests for partition properties using the Event Hub client. */ trackLastEnqueuedEventProperties?: boolean; + /** + * Option to disable the client from running JSON.parse() on the message body when receiving the message. + * Not applicable if the message was sent with AMQP body type value or sequence. Use this option when you + * prefer to work directly with the bytes present in the message body than have the client attempt to parse it. + */ + skipParsingBodyAsJson?: boolean; } diff --git a/sdk/eventhub/event-hubs/src/partitionPump.ts b/sdk/eventhub/event-hubs/src/partitionPump.ts index 8276d00d2c96..9fcdefacc5bf 100644 --- a/sdk/eventhub/event-hubs/src/partitionPump.ts +++ b/sdk/eventhub/event-hubs/src/partitionPump.ts @@ -90,7 +90,8 @@ export class PartitionPump { { ownerLevel: this._processorOptions.ownerLevel, trackLastEnqueuedEventProperties: this._processorOptions.trackLastEnqueuedEventProperties, - retryOptions: this._processorOptions.retryOptions + retryOptions: this._processorOptions.retryOptions, + skipParsingBodyAsJson: this._processorOptions.skipParsingBodyAsJson } ); diff --git a/sdk/eventhub/event-hubs/src/util/constants.ts b/sdk/eventhub/event-hubs/src/util/constants.ts index 4261fd7e177e..49d26688c3a2 100644 --- a/sdk/eventhub/event-hubs/src/util/constants.ts +++ b/sdk/eventhub/event-hubs/src/util/constants.ts @@ -6,5 +6,5 @@ */ export const packageJsonInfo = { name: "@azure/event-hubs", - version: "5.6.1" + version: "5.7.0" }; diff --git a/sdk/eventhub/event-hubs/test/internal/amqp.spec.ts b/sdk/eventhub/event-hubs/test/internal/amqp.spec.ts index 5a520a6ed02f..a13f72c81e89 100644 --- a/sdk/eventhub/event-hubs/test/internal/amqp.spec.ts +++ b/sdk/eventhub/event-hubs/test/internal/amqp.spec.ts @@ -14,23 +14,29 @@ testWithServiceTypes(() => { assert.isFalse(isAmqpAnnotatedMessage({ body: "hello world" })); assert.isFalse( isAmqpAnnotatedMessage( - fromRheaMessage({ - message_annotations: { - [Constants.enqueuedTime]: Date.now() + fromRheaMessage( + { + message_annotations: { + [Constants.enqueuedTime]: Date.now() + }, + body: undefined }, - body: undefined - }) + false + ) ) ); assert.isTrue( isAmqpAnnotatedMessage( - fromRheaMessage({ - message_annotations: { - [Constants.enqueuedTime]: Date.now() + fromRheaMessage( + { + message_annotations: { + [Constants.enqueuedTime]: Date.now() + }, + body: undefined }, - body: undefined - }).getRawAmqpMessage() + false + ).getRawAmqpMessage() ) ); diff --git a/sdk/eventhub/event-hubs/test/internal/dataTransformer.spec.ts b/sdk/eventhub/event-hubs/test/internal/dataTransformer.spec.ts index ea02aa53f38b..413d130896fe 100644 --- a/sdk/eventhub/event-hubs/test/internal/dataTransformer.spec.ts +++ b/sdk/eventhub/event-hubs/test/internal/dataTransformer.spec.ts @@ -6,7 +6,7 @@ import * as chai from "chai"; const should = chai.should(); import * as assert from "assert"; import isBuffer from "is-buffer"; -import { defaultDataTransformer } from "../../src/dataTransformer"; +import { dataSectionTypeCode, defaultDataTransformer } from "../../src/dataTransformer"; import { testWithServiceTypes } from "../public/utils/testWithServiceTypes"; testWithServiceTypes(() => { @@ -46,103 +46,103 @@ testWithServiceTypes(() => { describe(`encoded bodyType: "data"`, () => { const bodyType = "data"; - it("should correctly encode/decode a string message body", function(done) { + it("should correctly encode/decode a string message body", (done) => { const encoded: any = transformer.encode(stringBody, "data"); encoded.typecode.should.equal(117); isBuffer(encoded.content).should.equal(true); - const { body: decoded, bodyType: decodedType } = transformer.decode(encoded); + const { body: decoded, bodyType: decodedType } = transformer.decode(encoded, false); should.equal(decodedType, bodyType); (decoded as any).should.equal(stringBody); done(); }); - it("should correctly encode/decode a number message body", function(done) { + it("should correctly encode/decode a number message body", (done) => { const encoded: any = transformer.encode(numberBody, "data"); encoded.typecode.should.equal(117); isBuffer(encoded.content).should.equal(true); - const { body: decoded, bodyType: decodedType } = transformer.decode(encoded); + const { body: decoded, bodyType: decodedType } = transformer.decode(encoded, false); should.equal(decodedType, bodyType); (decoded as any).should.equal(numberBody); done(); }); - it("should correctly encode/decode a boolean message body", function(done) { + it("should correctly encode/decode a boolean message body", (done) => { const encoded: any = transformer.encode(booleanBody, "data"); encoded.typecode.should.equal(117); isBuffer(encoded.content).should.equal(true); - const { body: decoded, bodyType: decodedType } = transformer.decode(encoded); + const { body: decoded, bodyType: decodedType } = transformer.decode(encoded, false); should.equal(decodedType, bodyType); (decoded as any).should.equal(booleanBody); done(); }); - it("should correctly encode/decode a null message body", function(done) { + it("should correctly encode/decode a null message body", (done) => { const encoded: any = transformer.encode(nullBody, "data"); encoded.typecode.should.equal(117); isBuffer(encoded.content).should.equal(false); - const { body: decoded, bodyType: decodedType } = transformer.decode(encoded); + const { body: decoded, bodyType: decodedType } = transformer.decode(encoded, false); should.equal(decodedType, bodyType); should.equal(decoded, nullBody); done(); }); - it("should correctly encode/decode an undefined message body", function(done) { + it("should correctly encode/decode an undefined message body", (done) => { const encoded: any = transformer.encode(undefinedBody, "data"); encoded.typecode.should.equal(117); isBuffer(encoded.content).should.equal(false); - const { body: decoded, bodyType: decodedType } = transformer.decode(encoded); + const { body: decoded, bodyType: decodedType } = transformer.decode(encoded, false); should.equal(decodedType, bodyType); should.equal(decoded, nullBody); done(); }); - it("should correctly encode/decode an empty string message body", function(done) { + it("should correctly encode/decode an empty string message body", (done) => { const encoded: any = transformer.encode(emptyStringBody, "data"); encoded.typecode.should.equal(117); isBuffer(encoded.content).should.equal(true); - const { body: decoded, bodyType: decodedType } = transformer.decode(encoded); + const { body: decoded, bodyType: decodedType } = transformer.decode(encoded, false); should.equal(decodedType, bodyType); (decoded as any).should.equal(emptyStringBody); done(); }); - it("should correctly encode/decode an array message body", function(done) { + it("should correctly encode/decode an array message body", (done) => { const encoded: any = transformer.encode(arrayBody, "data"); encoded.typecode.should.equal(117); isBuffer(encoded.content).should.equal(true); - const { body: decoded, bodyType: decodedType } = transformer.decode(encoded); + const { body: decoded, bodyType: decodedType } = transformer.decode(encoded, false); should.equal(decodedType, bodyType); - assert.deepEqual(decoded, arrayBody); + assert.deepStrictEqual(decoded, arrayBody); done(); }); - it("should correctly encode/decode an object message body", function(done) { + it("should correctly encode/decode an object message body", (done) => { const encoded: any = transformer.encode(objectBody, "data"); encoded.typecode.should.equal(117); isBuffer(encoded.content).should.equal(true); - const { body: decoded, bodyType: decodedType } = transformer.decode(encoded); + const { body: decoded, bodyType: decodedType } = transformer.decode(encoded, false); should.equal(decodedType, bodyType); - assert.deepEqual(decoded, objectBody); + assert.deepStrictEqual(decoded, objectBody); done(); }); - it("should correctly encode/decode a buffer message body", function(done) { + it("should correctly encode/decode a buffer message body", (done) => { const encoded: any = transformer.encode(bufferBody, "data"); encoded.typecode.should.equal(117); isBuffer(encoded.content).should.equal(true); - const { body: decoded, bodyType: decodedType } = transformer.decode(encoded); + const { body: decoded, bodyType: decodedType } = transformer.decode(encoded, false); should.equal(decodedType, bodyType); - assert.deepEqual(decoded, bufferBody); + assert.deepStrictEqual(decoded, bufferBody); done(); }); - it("should correctly encode/decode a hex buffer message body", function(done) { + it("should correctly encode/decode a hex buffer message body", (done) => { const encoded: any = transformer.encode(hexBufferBody, "data"); encoded.typecode.should.equal(117); isBuffer(encoded.content).should.equal(true); - const { body: decoded, bodyType: decodedType } = transformer.decode(encoded); + const { body: decoded, bodyType: decodedType } = transformer.decode(encoded, false); should.equal(decodedType, bodyType); - assert.deepEqual(decoded, hexBufferBody); + assert.deepStrictEqual(decoded, hexBufferBody); done(); }); }); @@ -151,95 +151,95 @@ testWithServiceTypes(() => { const expectedTypeCode = 0x77; const bodyType = "value"; - it("should correctly encode/decode a string message body", function(done) { + it("should correctly encode/decode a string message body", (done) => { const encoded: any = transformer.encode(stringBody, bodyType); encoded.typecode.should.equal(expectedTypeCode); - const { body: decoded, bodyType: decodedType } = transformer.decode(encoded); + const { body: decoded, bodyType: decodedType } = transformer.decode(encoded, false); should.equal(decodedType, bodyType); (decoded as any).should.equal(stringBody); done(); }); - it("should correctly encode/decode a number message body", function(done) { + it("should correctly encode/decode a number message body", (done) => { const encoded: any = transformer.encode(numberBody, bodyType); encoded.typecode.should.equal(expectedTypeCode); - const { body: decoded, bodyType: decodedType } = transformer.decode(encoded); + const { body: decoded, bodyType: decodedType } = transformer.decode(encoded, false); should.equal(decodedType, bodyType); (decoded as any).should.equal(numberBody); done(); }); - it("should correctly encode/decode a boolean message body", function(done) { + it("should correctly encode/decode a boolean message body", (done) => { const encoded: any = transformer.encode(booleanBody, bodyType); encoded.typecode.should.equal(expectedTypeCode); - const { body: decoded, bodyType: decodedType } = transformer.decode(encoded); + const { body: decoded, bodyType: decodedType } = transformer.decode(encoded, false); should.equal(decodedType, bodyType); (decoded as any).should.equal(booleanBody); done(); }); - it("should correctly encode/decode a null message body", function(done) { + it("should correctly encode/decode a null message body", (done) => { const encoded: any = transformer.encode(nullBody, bodyType); encoded.typecode.should.equal(expectedTypeCode); - const { body: decoded, bodyType: decodedType } = transformer.decode(encoded); + const { body: decoded, bodyType: decodedType } = transformer.decode(encoded, false); should.equal(decodedType, bodyType); should.equal(decoded, nullBody); done(); }); - it("should correctly encode/decode an undefined message body", function(done) { + it("should correctly encode/decode an undefined message body", (done) => { const encoded: any = transformer.encode(undefinedBody, bodyType); encoded.typecode.should.equal(expectedTypeCode); - const { body: decoded, bodyType: decodedType } = transformer.decode(encoded); + const { body: decoded, bodyType: decodedType } = transformer.decode(encoded, false); should.equal(decodedType, bodyType); should.equal(decoded, nullBody); done(); }); - it("should correctly encode/decode an empty string message body", function(done) { + it("should correctly encode/decode an empty string message body", (done) => { const encoded: any = transformer.encode(emptyStringBody, bodyType); encoded.typecode.should.equal(expectedTypeCode); - const { body: decoded, bodyType: decodedType } = transformer.decode(encoded); + const { body: decoded, bodyType: decodedType } = transformer.decode(encoded, false); should.equal(decodedType, bodyType); (decoded as any).should.equal(emptyStringBody); done(); }); - it("should correctly encode/decode an array message body", function(done) { + it("should correctly encode/decode an array message body", (done) => { const encoded: any = transformer.encode(arrayBody, bodyType); encoded.typecode.should.equal(expectedTypeCode); - const { body: decoded, bodyType: decodedType } = transformer.decode(encoded); + const { body: decoded, bodyType: decodedType } = transformer.decode(encoded, false); should.equal(decodedType, bodyType); - assert.deepEqual(decoded, arrayBody); + assert.deepStrictEqual(decoded, arrayBody); done(); }); - it("should correctly encode/decode an object message body", function(done) { + it("should correctly encode/decode an object message body", (done) => { const encoded: any = transformer.encode(objectBody, bodyType); encoded.typecode.should.equal(expectedTypeCode); - const { body: decoded, bodyType: decodedType } = transformer.decode(encoded); + const { body: decoded, bodyType: decodedType } = transformer.decode(encoded, false); should.equal(decodedType, bodyType); - assert.deepEqual(decoded, objectBody); + assert.deepStrictEqual(decoded, objectBody); done(); }); - it("should correctly encode/decode a buffer message body", function(done) { + it("should correctly encode/decode a buffer message body", (done) => { const encoded: any = transformer.encode(bufferBody, bodyType); encoded.typecode.should.equal(expectedTypeCode); isBuffer(encoded.content).should.equal(true); - const { body: decoded, bodyType: decodedType } = transformer.decode(encoded); + const { body: decoded, bodyType: decodedType } = transformer.decode(encoded, false); should.equal(decodedType, bodyType); - assert.deepEqual(decoded, bufferBody); + assert.deepStrictEqual(decoded, bufferBody); done(); }); - it("should correctly encode/decode a hex buffer message body", function(done) { + it("should correctly encode/decode a hex buffer message body", (done) => { const encoded: any = transformer.encode(hexBufferBody, bodyType); encoded.typecode.should.equal(expectedTypeCode); isBuffer(encoded.content).should.equal(true); - const { body: decoded, bodyType: decodedType } = transformer.decode(encoded); + const { body: decoded, bodyType: decodedType } = transformer.decode(encoded, false); should.equal(decodedType, bodyType); - assert.deepEqual(decoded, hexBufferBody); + assert.deepStrictEqual(decoded, hexBufferBody); done(); }); }); @@ -248,113 +248,241 @@ testWithServiceTypes(() => { const expectedTypeCode = 0x76; const bodyType = "sequence"; - it("should correctly encode/decode a null message body", function(done) { + it("should correctly encode/decode a null message body", (done) => { const encoded: any = transformer.encode(nullBody, bodyType); encoded.typecode.should.equal(expectedTypeCode); - const { body: decoded, bodyType: decodedType } = transformer.decode(encoded); + const { body: decoded, bodyType: decodedType } = transformer.decode(encoded, false); should.equal(decodedType, bodyType); should.equal(decoded, nullBody); done(); }); - it("should correctly encode/decode an undefined message body", function(done) { + it("should correctly encode/decode an undefined message body", (done) => { const encoded: any = transformer.encode(undefinedBody, bodyType); encoded.typecode.should.equal(expectedTypeCode); - const { body: decoded, bodyType: decodedType } = transformer.decode(encoded); + const { body: decoded, bodyType: decodedType } = transformer.decode(encoded, false); should.equal(decodedType, bodyType); should.equal(decoded, nullBody); done(); }); - it("should correctly encode/decode an array message body", function(done) { + it("should correctly encode/decode an array message body", (done) => { const encoded: any = transformer.encode(arrayBody, bodyType); encoded.typecode.should.equal(expectedTypeCode); - const { body: decoded, bodyType: decodedType } = transformer.decode(encoded); + const { body: decoded, bodyType: decodedType } = transformer.decode(encoded, false); should.equal(decodedType, bodyType); - assert.deepEqual(decoded, arrayBody); + assert.deepStrictEqual(decoded, arrayBody); done(); }); - it("should correctly encode/decode an object message body", function(done) { + it("should correctly encode/decode an object message body", (done) => { const encoded: any = transformer.encode(objectBody, bodyType); encoded.typecode.should.equal(expectedTypeCode); - const { body: decoded, bodyType: decodedType } = transformer.decode(encoded); + const { body: decoded, bodyType: decodedType } = transformer.decode(encoded, false); should.equal(decodedType, bodyType); - assert.deepEqual(decoded, objectBody); + assert.deepStrictEqual(decoded, objectBody); done(); }); }); - describe("decode", function() { + describe("decode", () => { // It is possible that we receive an AMQP value type from the messages that were sent with // previously shipped version of the sdk. If so then we should be able to handle those scenarios. - it("should correctly decode a string message body", function(done) { - const { body: decoded, bodyType: decodedType } = transformer.decode(stringBody); + it("should correctly decode a string message body", (done) => { + const { body: decoded, bodyType: decodedType } = transformer.decode(stringBody, false); should.equal(decodedType, "value"); (decoded as any).should.equal(stringBody); done(); }); - it("should correctly decode a number message body", function(done) { - const { body: decoded, bodyType: decodedType } = transformer.decode(numberBody); + it("should correctly decode a string message body, setting skipParsingBodyAsJson to true", (done) => { + const { body: decoded, bodyType: decodedType } = transformer.decode(stringBody, true); + should.equal(decodedType, "value"); + (decoded as any).should.equal(stringBody); + done(); + }); + + it("should correctly decode a number message body", (done) => { + const { body: decoded, bodyType: decodedType } = transformer.decode(numberBody, false); + should.equal(decodedType, "value"); + (decoded as any).should.equal(numberBody); + done(); + }); + + it("should correctly decode a number message body, setting skipParsingBodyAsJson to true", (done) => { + const { body: decoded, bodyType: decodedType } = transformer.decode(numberBody, true); should.equal(decodedType, "value"); (decoded as any).should.equal(numberBody); done(); }); - it("should correctly decode a boolean message body", function(done) { - const { body: decoded, bodyType: decodedType } = transformer.decode(booleanBody); + it("should correctly decode a boolean message body", (done) => { + const { body: decoded, bodyType: decodedType } = transformer.decode(booleanBody, false); + should.equal(decodedType, "value"); + (decoded as any).should.equal(booleanBody); + done(); + }); + + it("should correctly decode a boolean message body, setting skipParsingBodyAsJson to true", (done) => { + const { body: decoded, bodyType: decodedType } = transformer.decode(booleanBody, true); should.equal(decodedType, "value"); (decoded as any).should.equal(booleanBody); done(); }); - it("should correctly decode a null message body", function(done) { - const { body: decoded, bodyType: decodedType } = transformer.decode(nullBody); + it("should correctly decode a null message body", (done) => { + const { body: decoded, bodyType: decodedType } = transformer.decode(nullBody, false); should.equal(decodedType, "value"); should.equal(decoded, nullBody); done(); }); - it("should correctly decode an undefined message body", function(done) { - const { body: decoded, bodyType: decodedType } = transformer.decode(undefinedBody); + it("should correctly decode a null message body, setting skipParsingBodyAsJson to true", (done) => { + const { body: decoded, bodyType: decodedType } = transformer.decode(nullBody, true); + should.equal(decodedType, "value"); + should.equal(decoded, nullBody); + done(); + }); + + it("should correctly decode an undefined message body", (done) => { + const { body: decoded, bodyType: decodedType } = transformer.decode(undefinedBody, false); should.equal(decodedType, "value"); should.equal(decoded, undefined); done(); }); - it("should correctly decode an empty string message body", function(done) { - const { body: decoded, bodyType: decodedType } = transformer.decode(emptyStringBody); + it("should correctly decode an undefined message body, setting skipParsingBodyAsJson to true", (done) => { + const { body: decoded, bodyType: decodedType } = transformer.decode(undefinedBody, true); + should.equal(decodedType, "value"); + should.equal(decoded, undefined); + done(); + }); + + it("should correctly decode an empty string message body", (done) => { + const { body: decoded, bodyType: decodedType } = transformer.decode(emptyStringBody, false); should.equal(decodedType, "value"); (decoded as any).should.equal(emptyStringBody); done(); }); - it("should correctly decode an array message body", function(done) { - const { body: decoded, bodyType: decodedType } = transformer.decode(arrayBody); + it("should correctly decode an empty string message body, setting skipParsingBodyAsJson to true", (done) => { + const { body: decoded, bodyType: decodedType } = transformer.decode(emptyStringBody, true); + should.equal(decodedType, "value"); + (decoded as any).should.equal(emptyStringBody); + done(); + }); + + it("should correctly decode an array message body", (done) => { + const { body: decoded, bodyType: decodedType } = transformer.decode(arrayBody, false); + should.equal(decodedType, "value"); + assert.deepStrictEqual(decoded, arrayBody); + done(); + }); + + it("should correctly decode an array message body, setting skipParsingBodyAsJson to true", (done) => { + const { body: decoded, bodyType: decodedType } = transformer.decode(arrayBody, true); + should.equal(decodedType, "value"); + assert.deepStrictEqual(decoded, arrayBody); + done(); + }); + + it("should correctly decode an object message body", (done) => { + const { body: decoded, bodyType: decodedType } = transformer.decode(objectBody, false); should.equal(decodedType, "value"); - assert.deepEqual(decoded, arrayBody); + assert.deepStrictEqual(decoded, objectBody); done(); }); - it("should correctly decode an object message body", function(done) { - const { body: decoded, bodyType: decodedType } = transformer.decode(objectBody); + it("should correctly decode an object message body, setting skipParsingBodyAsJson to true", (done) => { + const { body: decoded, bodyType: decodedType } = transformer.decode(objectBody, true); should.equal(decodedType, "value"); - assert.deepEqual(decoded, objectBody); + assert.deepStrictEqual(decoded, objectBody); + done(); + }); + + it("should correctly decode a buffer message body", (done) => { + const { body: decoded, bodyType: decodedType } = transformer.decode(bufferBody, false); + should.equal(decodedType, "data"); + assert.deepStrictEqual(decoded, bufferBody); + done(); + }); + + it("should correctly decode a buffer message body, setting skipParsingBodyAsJson to true", (done) => { + const { body: decoded, bodyType: decodedType } = transformer.decode(bufferBody, true); + should.equal(decodedType, "data"); + assert.deepStrictEqual(decoded, bufferBody); + done(); + }); + + it("should correctly decode a hex buffer message body", (done) => { + const { body: decoded, bodyType: decodedType } = transformer.decode(hexBufferBody, false); + should.equal(decodedType, "data"); + assert.deepStrictEqual(decoded, hexBufferBody); + done(); + }); + + it("should correctly decode a hex buffer message body, setting skipParsingBodyAsJson to true", (done) => { + const { body: decoded, bodyType: decodedType } = transformer.decode(hexBufferBody, false); + should.equal(decodedType, "data"); + assert.deepStrictEqual(decoded, hexBufferBody); + done(); + }); + + it("should correctly decode a buffer message body and that body is a JSON string", (done) => { + const jsonBody = { + foo: "bar" + }; + const jsonStringBufferBody = Buffer.from(JSON.stringify(jsonBody), "utf8"); + const { body: decoded, bodyType: decodedType } = transformer.decode( + jsonStringBufferBody, + false + ); + should.equal(decodedType, "data"); + assert.deepStrictEqual(decoded, jsonBody); + done(); + }); + + it("should correctly decode a buffer message body and that body is a JSON string, setting skipParsingBodyAsJson to true", (done) => { + const jsonBody = { + foo: "bar" + }; + const jsonStringBufferBody = Buffer.from(JSON.stringify(jsonBody), "utf8"); + const { body: decoded, bodyType: decodedType } = transformer.decode( + jsonStringBufferBody, + true + ); + should.equal(decodedType, "data"); + assert.deepStrictEqual(decoded, jsonStringBufferBody); done(); }); - it("should correctly decode a buffer message body", function(done) { - const { body: decoded, bodyType: decodedType } = transformer.decode(bufferBody); + it("should correctly decode a buffer message body and that body is a JSON string for a rhea AMQP section", (done) => { + const jsonBody = { + foo: "bar" + }; + const jsonStringBufferBody = Buffer.from(JSON.stringify(jsonBody), "utf8"); + const rheaAmqpSection = { + typecode: dataSectionTypeCode, + content: jsonStringBufferBody + }; + const { body: decoded, bodyType: decodedType } = transformer.decode(rheaAmqpSection, false); should.equal(decodedType, "data"); - assert.deepEqual(decoded, bufferBody); + assert.deepStrictEqual(decoded, jsonBody); done(); }); - it("should correctly decode a hex buffer message body", function(done) { - const { body: decoded, bodyType: decodedType } = transformer.decode(hexBufferBody); + it("should correctly decode a buffer message body and that body is a JSON string for a rhea AMQP section, setting skipParsingBodyAsJson to true", (done) => { + const jsonBody = { + foo: "bar" + }; + const jsonStringBufferBody = Buffer.from(JSON.stringify(jsonBody), "utf8"); + const rheaAmqpSection = { + typecode: dataSectionTypeCode, + content: jsonStringBufferBody + }; + const { body: decoded, bodyType: decodedType } = transformer.decode(rheaAmqpSection, true); should.equal(decodedType, "data"); - assert.deepEqual(decoded, hexBufferBody); + assert.deepStrictEqual(decoded, jsonStringBufferBody); done(); }); }); diff --git a/sdk/eventhub/event-hubs/test/internal/eventdata.spec.ts b/sdk/eventhub/event-hubs/test/internal/eventdata.spec.ts index a32841c70e3b..03ed246e928f 100644 --- a/sdk/eventhub/event-hubs/test/internal/eventdata.spec.ts +++ b/sdk/eventhub/event-hubs/test/internal/eventdata.spec.ts @@ -48,15 +48,18 @@ testWithServiceTypes(() => { describe("EventData", function(): void { describe("fromRheaMessage", function(): void { it("populates body with the message body", function(): void { - const testEventData = fromRheaMessage(testMessage); + const testEventData = fromRheaMessage(testMessage, false); testEventData.body.should.equal(testBody); }); it("populates top-level fields", () => { - const testEventData = fromRheaMessage({ - ...testMessage, - ...{ content_type: "application/json", correlation_id: "cid", message_id: 1 } - }); + const testEventData = fromRheaMessage( + { + ...testMessage, + ...{ content_type: "application/json", correlation_id: "cid", message_id: 1 } + }, + false + ); should().equal(testEventData.messageId, 1, "Unexpected messageId found."); should().equal( testEventData.contentType, @@ -68,24 +71,24 @@ testWithServiceTypes(() => { describe("properties", function(): void { it("enqueuedTimeUtc gets the enqueued time from system properties", function(): void { - const testEventData = fromRheaMessage(testMessage); + const testEventData = fromRheaMessage(testMessage, false); testEventData .enqueuedTimeUtc!.getTime() .should.equal(testAnnotations["x-opt-enqueued-time"]); }); it("offset gets the offset from system properties", function(): void { - const testEventData = fromRheaMessage(testMessage); + const testEventData = fromRheaMessage(testMessage, false); testEventData.offset!.should.equal(testAnnotations["x-opt-offset"]); }); it("sequenceNumber gets the sequence number from system properties", function(): void { - const testEventData = fromRheaMessage(testMessage); + const testEventData = fromRheaMessage(testMessage, false); testEventData.sequenceNumber!.should.equal(testAnnotations["x-opt-sequence-number"]); }); it("partitionKey gets the sequence number from system properties", function(): void { - const testEventData = fromRheaMessage(testMessage); + const testEventData = fromRheaMessage(testMessage, false); testEventData.partitionKey!.should.equal(testAnnotations["x-opt-partition-key"]); }); @@ -94,14 +97,17 @@ testWithServiceTypes(() => { "x-iot-foo-prop": "just-a-foo", "x-iot-bar-prop": "bar-above-the-rest" }; - const testEventData = fromRheaMessage({ - body: testBody, - application_properties: applicationProperties, - message_annotations: { - ...testAnnotations, - ...extraAnnotations - } - }); + const testEventData = fromRheaMessage( + { + body: testBody, + application_properties: applicationProperties, + message_annotations: { + ...testAnnotations, + ...extraAnnotations + } + }, + false + ); testEventData .enqueuedTimeUtc!.getTime() .should.equal(testAnnotations["x-opt-enqueued-time"]); @@ -117,24 +123,27 @@ testWithServiceTypes(() => { }); it("returns systemProperties for special known properties", function(): void { - const testEventData = fromRheaMessage({ - body: testBody, - application_properties: applicationProperties, - message_annotations: testAnnotations, - message_id: "messageId", - user_id: "userId", - to: "to", - subject: "subject", - reply_to: "replyTo", - reply_to_group_id: "replyToGroupId", - content_encoding: "utf-8", - content_type: "application/json", - correlation_id: "id2", - absolute_expiry_time: new Date(0), - creation_time: new Date(0), - group_id: "groupId", - group_sequence: 1 - }); + const testEventData = fromRheaMessage( + { + body: testBody, + application_properties: applicationProperties, + message_annotations: testAnnotations, + message_id: "messageId", + user_id: "userId", + to: "to", + subject: "subject", + reply_to: "replyTo", + reply_to_group_id: "replyToGroupId", + content_encoding: "utf-8", + content_type: "application/json", + correlation_id: "id2", + absolute_expiry_time: new Date(0), + creation_time: new Date(0), + group_id: "groupId", + group_sequence: 1 + }, + false + ); testEventData .enqueuedTimeUtc!.getTime() @@ -164,20 +173,23 @@ testWithServiceTypes(() => { "x-date": timestamp, "x-number": timestamp.getTime() }; - const testEventData = fromRheaMessage({ - body: testBody, - application_properties: { - topLevelDate: timestamp, - child: { - nestedDate: timestamp, - children: [timestamp, { deepDate: timestamp }] + const testEventData = fromRheaMessage( + { + body: testBody, + application_properties: { + topLevelDate: timestamp, + child: { + nestedDate: timestamp, + children: [timestamp, { deepDate: timestamp }] + } + }, + message_annotations: { + ...testAnnotations, + ...extraAnnotations } }, - message_annotations: { - ...testAnnotations, - ...extraAnnotations - } - }); + false + ); testEventData .enqueuedTimeUtc!.getTime() .should.equal(testAnnotations["x-opt-enqueued-time"]);