diff --git a/src/message/http/index.ts b/src/message/http/index.ts index cdba2629..ad9fd701 100644 --- a/src/message/http/index.ts +++ b/src/message/http/index.ts @@ -16,7 +16,7 @@ import { v1binaryParsers, v1structuredParsers, } from "./headers"; -import { isStringOrObjectOrThrow, ValidationError } from "../../event/validation"; +import { base64AsBinary, isStringOrObjectOrThrow, ValidationError } from "../../event/validation"; import { JSONParser, MappedParser, Parser, parserByContentType } from "../../parsers"; /** @@ -248,7 +248,7 @@ function parseStructured(message: Message, version: string): CloudEvent { // itself will be encoded as base64 if (eventObj.data_base64 || eventObj.datacontentencoding === CONSTANTS.ENCODING_BASE64) { const data = eventObj.data_base64 || eventObj.data; - eventObj.data = new Uint32Array(Buffer.from(data as string, "base64")); + eventObj.data = base64AsBinary(data as string); delete eventObj.data_base64; delete eventObj.datacontentencoding; } diff --git a/test/integration/cloud_event_test.ts b/test/integration/cloud_event_test.ts index 84472070..1e9fc530 100644 --- a/test/integration/cloud_event_test.ts +++ b/test/integration/cloud_event_test.ts @@ -22,7 +22,7 @@ const fixture = Object.freeze({ data: `"some data"` }); -const imageData = new Uint32Array(fs.readFileSync(path.join(process.cwd(), "test", "integration", "ce.png"))); +const imageData = new Uint8Array(fs.readFileSync(path.join(process.cwd(), "test", "integration", "ce.png"))); const image_base64 = asBase64(imageData); // Do not replace this with the assignment of a class instance diff --git a/test/integration/kafka_tests.ts b/test/integration/kafka_tests.ts index cb858f49..e85327fc 100644 --- a/test/integration/kafka_tests.ts +++ b/test/integration/kafka_tests.ts @@ -34,12 +34,12 @@ const ext2Name = "extension2"; const ext2Value = "acme"; // Binary data as base64 -const dataBinary = Uint32Array.from(JSON.stringify(data), (c) => c.codePointAt(0) as number); +const dataBinary = Uint8Array.from(JSON.stringify(data), (c) => c.codePointAt(0) as number); const data_base64 = asBase64(dataBinary); // Since the above is a special case (string as binary), let's test // with a real binary file one is likely to encounter in the wild -const imageData = new Uint32Array(fs.readFileSync(path.join(process.cwd(), "test", "integration", "ce.png"))); +const imageData = new Uint8Array(fs.readFileSync(path.join(process.cwd(), "test", "integration", "ce.png"))); const image_base64 = asBase64(imageData); const fixture = new CloudEvent({ @@ -289,14 +289,14 @@ describe("Kafka transport", () => { it.skip("Converts base64 encoded data to binary when deserializing structured messages", () => { const message = Kafka.structured(fixture.cloneWith({ data: imageData, datacontenttype: "image/png" })); - const eventDeserialized = Kafka.toEvent(message) as CloudEvent; + const eventDeserialized = Kafka.toEvent(message) as CloudEvent; expect(eventDeserialized.data).to.deep.equal(imageData); expect(eventDeserialized.data_base64).to.equal(image_base64); }); it("Converts base64 encoded data to binary when deserializing binary messages", () => { const message = Kafka.binary(fixture.cloneWith({ data: imageData, datacontenttype: "image/png" })); - const eventDeserialized = Kafka.toEvent(message) as CloudEvent; + const eventDeserialized = Kafka.toEvent(message) as CloudEvent; expect(eventDeserialized.data).to.deep.equal(imageData); expect(eventDeserialized.data_base64).to.equal(image_base64); }); @@ -310,7 +310,7 @@ describe("Kafka transport", () => { it("Does not parse binary data from binary messages with content type application/json", () => { const message = Kafka.binary(fixture.cloneWith({ data: dataBinary })); - const eventDeserialized = Kafka.toEvent(message) as CloudEvent; + const eventDeserialized = Kafka.toEvent(message) as CloudEvent; expect(eventDeserialized.data).to.deep.equal(dataBinary); expect(eventDeserialized.data_base64).to.equal(data_base64); }); diff --git a/test/integration/message_test.ts b/test/integration/message_test.ts index 93699c61..b7dadc63 100644 --- a/test/integration/message_test.ts +++ b/test/integration/message_test.ts @@ -32,12 +32,12 @@ const ext2Name = "extension2"; const ext2Value = "acme"; // Binary data as base64 -const dataBinary = Uint32Array.from(JSON.stringify(data), (c) => c.codePointAt(0) as number); +const dataBinary = Uint8Array.from(JSON.stringify(data), (c) => c.codePointAt(0) as number); const data_base64 = asBase64(dataBinary); // Since the above is a special case (string as binary), let's test // with a real binary file one is likely to encounter in the wild -const imageData = new Uint32Array(fs.readFileSync(path.join(process.cwd(), "test", "integration", "ce.png"))); +const imageData = new Uint8Array(fs.readFileSync(path.join(process.cwd(), "test", "integration", "ce.png"))); const image_base64 = asBase64(imageData); describe("HTTP transport", () => { @@ -317,21 +317,32 @@ describe("HTTP transport", () => { it("Converts base64 encoded data to binary when deserializing structured messages", () => { const message = HTTP.structured(fixture.cloneWith({ data: imageData, datacontenttype: "image/png" })); - const eventDeserialized = HTTP.toEvent(message) as CloudEvent; + const eventDeserialized = HTTP.toEvent(message) as CloudEvent; expect(eventDeserialized.data).to.deep.equal(imageData); expect(eventDeserialized.data_base64).to.equal(image_base64); }); it("Does not parse binary data from structured messages with content type application/json", () => { const message = HTTP.structured(fixture.cloneWith({ data: dataBinary })); - const eventDeserialized = HTTP.toEvent(message) as CloudEvent; + const eventDeserialized = HTTP.toEvent(message) as CloudEvent; expect(eventDeserialized.data).to.deep.equal(dataBinary); expect(eventDeserialized.data_base64).to.equal(data_base64); }); + it("Deserializes data_base64 as Uint8Array with correct byte length", () => { + const original = new Uint8Array([0x00, 0x01, 0x02, 0xff]); + const event = fixture.cloneWith({ data: original, datacontenttype: "application/octet-stream" }); + const message = HTTP.structured(event); + const deserialized = HTTP.toEvent(message) as CloudEvent; + expect(deserialized.data).to.be.instanceOf(Uint8Array); + expect(deserialized.data!.length).to.equal(4); + expect(deserialized.data!.buffer.byteLength).to.equal(4); + expect(Array.from(deserialized.data!)).to.deep.equal([0x00, 0x01, 0x02, 0xff]); + }); + it("Converts base64 encoded data to binary when deserializing binary messages", () => { const message = HTTP.binary(fixture.cloneWith({ data: imageData, datacontenttype: "image/png" })); - const eventDeserialized = HTTP.toEvent(message) as CloudEvent; + const eventDeserialized = HTTP.toEvent(message) as CloudEvent; expect(eventDeserialized.data).to.deep.equal(imageData); expect(eventDeserialized.data_base64).to.equal(image_base64); }); @@ -345,7 +356,7 @@ describe("HTTP transport", () => { it("Does not parse binary data from binary messages with content type application/json", () => { const message = HTTP.binary(fixture.cloneWith({ data: dataBinary })); - const eventDeserialized = HTTP.toEvent(message) as CloudEvent; + const eventDeserialized = HTTP.toEvent(message) as CloudEvent; expect(eventDeserialized.data).to.deep.equal(dataBinary); expect(eventDeserialized.data_base64).to.equal(data_base64); }); @@ -422,14 +433,14 @@ describe("HTTP transport", () => { // Creating an event with binary data automatically produces base64 encoded data // which is then set as the 'data' attribute on the message body const message = HTTP.structured(fixture.cloneWith({ data: imageData, datacontenttype: "image/png" })); - const eventDeserialized = HTTP.toEvent(message) as CloudEvent; + const eventDeserialized = HTTP.toEvent(message) as CloudEvent; expect(eventDeserialized.data).to.deep.equal(imageData); expect(eventDeserialized.data_base64).to.equal(image_base64); }); it("Converts base64 encoded data to binary when deserializing binary messages", () => { const message = HTTP.binary(fixture.cloneWith({ data: imageData, datacontenttype: "image/png" })); - const eventDeserialized = HTTP.toEvent(message) as CloudEvent; + const eventDeserialized = HTTP.toEvent(message) as CloudEvent; expect(eventDeserialized.data).to.deep.equal(imageData); expect(eventDeserialized.data_base64).to.equal(image_base64); });