diff --git a/package.json b/package.json index afa40fac..c68e61a0 100644 --- a/package.json +++ b/package.json @@ -102,6 +102,11 @@ { "name": "Matej Vasek", "url": "https://github.com/matejvasek" + }, + { + "name": "Shiva", + "email": "shiv@shiv.me", + "url": "https://github.com/shiva" } ], "license": "Apache-2.0", 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..943f7713 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({ @@ -287,16 +287,16 @@ describe("Kafka transport", () => { expect(messageBody.data_base64).to.equal(image_base64); }); - it.skip("Converts base64 encoded data to binary when deserializing structured messages", () => { + it("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..9ddb292d 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,33 @@ 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; + const bytes = deserialized.data as Uint8Array; + expect(bytes).to.be.instanceOf(Uint8Array); + expect(bytes.length).to.equal(4); + expect(bytes.buffer.byteLength).to.equal(4); + expect(Array.from(bytes)).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 +357,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 +434,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); });