@@ -2,16 +2,17 @@ import { CloudEvent, CloudEventV03, CloudEventV1, CONSTANTS, Mode, Version } fro
22import { Message , Headers } from ".." ;
33
44import { headersFor , sanitize , v03structuredParsers , v1binaryParsers , v1structuredParsers } from "./headers" ;
5- import { asData , isBase64 , isString , isStringOrObjectOrThrow , ValidationError } from "../../event/validation" ;
6- import { Base64Parser , JSONParser , MappedParser , Parser , parserByContentType } from "../../parsers" ;
5+ import { isStringOrObjectOrThrow , ValidationError } from "../../event/validation" ;
6+ import { JSONParser , MappedParser , Parser , parserByContentType } from "../../parsers" ;
77
88// implements Serializer
99export function binary ( event : CloudEvent ) : Message {
1010 const contentType : Headers = { [ CONSTANTS . HEADER_CONTENT_TYPE ] : CONSTANTS . DEFAULT_CONTENT_TYPE } ;
1111 const headers : Headers = { ...contentType , ...headersFor ( event ) } ;
12- let body = asData ( event . data , event . datacontenttype as string ) ;
13- if ( typeof body === "object" ) {
14- body = JSON . stringify ( body ) ;
12+ let body = event . data ;
13+ if ( typeof event . data === "object" && ! ( event . data instanceof Uint32Array ) ) {
14+ // we'll stringify objects, but not binary data
15+ body = JSON . stringify ( event . data ) ;
1516 }
1617 return {
1718 headers,
@@ -21,6 +22,10 @@ export function binary(event: CloudEvent): Message {
2122
2223// implements Serializer
2324export function structured ( event : CloudEvent ) : Message {
25+ if ( event . data_base64 ) {
26+ // The event's data is binary - delete it
27+ event = event . cloneWith ( { data : undefined } ) ;
28+ }
2429 return {
2530 headers : {
2631 [ CONSTANTS . HEADER_CONTENT_TYPE ] : CONSTANTS . DEFAULT_CE_CONTENT_TYPE ,
@@ -89,7 +94,7 @@ function getMode(headers: Headers): Mode {
8994 * @param {Record<string, unknown> } body the HTTP request body
9095 * @returns {Version } the CloudEvent specification version
9196 */
92- function getVersion ( mode : Mode , headers : Headers , body : string | Record < string , string > ) {
97+ function getVersion ( mode : Mode , headers : Headers , body : string | Record < string , string > | unknown ) {
9398 if ( mode === Mode . BINARY ) {
9499 // Check the headers for the version
95100 const versionHeader = headers [ CONSTANTS . CE_HEADERS . SPEC_VERSION ] ;
@@ -129,8 +134,6 @@ function parseBinary(message: Message, version: Version): CloudEvent {
129134 throw new ValidationError ( `invalid spec version ${ headers [ CONSTANTS . CE_HEADERS . SPEC_VERSION ] } ` ) ;
130135 }
131136
132- body = isString ( body ) && isBase64 ( body ) ? Buffer . from ( body as string , "base64" ) . toString ( ) : body ;
133-
134137 // Clone and low case all headers names
135138 const sanitizedHeaders = sanitize ( headers ) ;
136139
@@ -145,30 +148,26 @@ function parseBinary(message: Message, version: Version): CloudEvent {
145148 }
146149 }
147150
148- let parsedPayload ;
149-
150- if ( body ) {
151- const parser = parserByContentType [ eventObj . datacontenttype as string ] ;
152- if ( ! parser ) {
153- throw new ValidationError ( `no parser found for content type ${ eventObj . datacontenttype } ` ) ;
154- }
155- parsedPayload = parser . parse ( body ) ;
156- }
157-
158151 // Every unprocessed header can be an extension
159152 for ( const header in sanitizedHeaders ) {
160153 if ( header . startsWith ( CONSTANTS . EXTENSIONS_PREFIX ) ) {
161154 eventObj [ header . substring ( CONSTANTS . EXTENSIONS_PREFIX . length ) ] = headers [ header ] ;
162155 }
163156 }
157+
158+ const parser = parserByContentType [ eventObj . datacontenttype as string ] ;
159+ if ( parser && body ) {
160+ body = parser . parse ( body as string ) ;
161+ }
162+
164163 // At this point, if the datacontenttype is application/json and the datacontentencoding is base64
165164 // then the data has already been decoded as a string, then parsed as JSON. We don't need to have
166165 // the datacontentencoding property set - in fact, it's incorrect to do so.
167166 if ( eventObj . datacontenttype === CONSTANTS . MIME_JSON && eventObj . datacontentencoding === CONSTANTS . ENCODING_BASE64 ) {
168167 delete eventObj . datacontentencoding ;
169168 }
170169
171- return new CloudEvent ( { ...eventObj , data : parsedPayload } as CloudEventV1 | CloudEventV03 , false ) ;
170+ return new CloudEvent ( { ...eventObj , data : body } as CloudEventV1 | CloudEventV03 , false ) ;
172171}
173172
174173/**
@@ -201,7 +200,7 @@ function parseStructured(message: Message, version: Version): CloudEvent {
201200 const contentType = sanitizedHeaders [ CONSTANTS . HEADER_CONTENT_TYPE ] ;
202201 const parser : Parser = contentType ? parserByContentType [ contentType ] : new JSONParser ( ) ;
203202 if ( ! parser ) throw new ValidationError ( `invalid content type ${ sanitizedHeaders [ CONSTANTS . HEADER_CONTENT_TYPE ] } ` ) ;
204- const incoming = { ...( parser . parse ( payload ) as Record < string , unknown > ) } ;
203+ const incoming = { ...( parser . parse ( payload as string ) as Record < string , unknown > ) } ;
205204
206205 const eventObj : { [ key : string ] : unknown } = { } ;
207206 const parserMap : Record < string , MappedParser > = version === Version . V1 ? v1structuredParsers : v03structuredParsers ;
@@ -220,10 +219,12 @@ function parseStructured(message: Message, version: Version): CloudEvent {
220219 eventObj [ key ] = incoming [ key ] ;
221220 }
222221
223- // ensure data content is correctly decoded
224- if ( eventObj . data_base64 ) {
225- const parser = new Base64Parser ( ) ;
226- eventObj . data = JSON . parse ( parser . parse ( eventObj . data_base64 as string ) ) ;
222+ // data_base64 is a property that only exists on V1 events. For V03 events,
223+ // there will be a .datacontentencoding property, and the .data property
224+ // itself will be encoded as base64
225+ if ( eventObj . data_base64 || eventObj . datacontentencoding === CONSTANTS . ENCODING_BASE64 ) {
226+ const data = eventObj . data_base64 || eventObj . data ;
227+ eventObj . data = new Uint32Array ( Buffer . from ( data as string , "base64" ) ) ;
227228 delete eventObj . data_base64 ;
228229 delete eventObj . datacontentencoding ;
229230 }
0 commit comments