diff --git a/dist/ResponseStream.d.ts b/dist/ResponseStream.d.ts index 612bdec..0098817 100644 --- a/dist/ResponseStream.d.ts +++ b/dist/ResponseStream.d.ts @@ -3,9 +3,11 @@ import { Stream } from 'stream'; export declare class ResponseStream extends Stream.Writable { private response; _contentType?: string; + _isBase64Encoded?: boolean; constructor(); _write(chunk: any, encoding: BufferEncoding, callback: (error?: Error | null) => void): void; getBufferedData(): Buffer; setContentType(contentType: string): void; + setIsBase64Encoded(isBase64Encoded: boolean): void; } //# sourceMappingURL=ResponseStream.d.ts.map \ No newline at end of file diff --git a/dist/ResponseStream.d.ts.map b/dist/ResponseStream.d.ts.map index 4618340..f377a00 100644 --- a/dist/ResponseStream.d.ts.map +++ b/dist/ResponseStream.d.ts.map @@ -1 +1 @@ -{"version":3,"file":"ResponseStream.d.ts","sourceRoot":"","sources":["../src/ResponseStream.ts"],"names":[],"mappings":";AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAA;AAE/B,qBAAa,cAAe,SAAQ,MAAM,CAAC,QAAQ;IACjD,OAAO,CAAC,QAAQ,CAAU;IAC1B,YAAY,CAAC,EAAE,MAAM,CAAA;;IAQrB,MAAM,CACJ,KAAK,EAAE,GAAG,EACV,QAAQ,EAAE,cAAc,EACxB,QAAQ,EAAE,CAAC,KAAK,CAAC,EAAE,KAAK,GAAG,IAAI,KAAK,IAAI,GACvC,IAAI;IAKP,eAAe,IAAI,MAAM;IAIzB,cAAc,CAAC,WAAW,EAAE,MAAM;CAGnC"} \ No newline at end of file +{"version":3,"file":"ResponseStream.d.ts","sourceRoot":"","sources":["../src/ResponseStream.ts"],"names":[],"mappings":";AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAA;AAE/B,qBAAa,cAAe,SAAQ,MAAM,CAAC,QAAQ;IACjD,OAAO,CAAC,QAAQ,CAAU;IAC1B,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,gBAAgB,CAAC,EAAE,OAAO,CAAA;;IAQ1B,MAAM,CACJ,KAAK,EAAE,GAAG,EACV,QAAQ,EAAE,cAAc,EACxB,QAAQ,EAAE,CAAC,KAAK,CAAC,EAAE,KAAK,GAAG,IAAI,KAAK,IAAI,GACvC,IAAI;IAKP,eAAe,IAAI,MAAM;IAIzB,cAAc,CAAC,WAAW,EAAE,MAAM;IAIlC,kBAAkB,CAAC,eAAe,EAAE,OAAO;CAG5C"} \ No newline at end of file diff --git a/dist/ResponseStream.js b/dist/ResponseStream.js index 40e874e..fbaa02c 100644 --- a/dist/ResponseStream.js +++ b/dist/ResponseStream.js @@ -19,6 +19,9 @@ class ResponseStream extends stream_1.Stream.Writable { setContentType(contentType) { this._contentType = contentType; } + setIsBase64Encoded(isBase64Encoded) { + this._isBase64Encoded = isBase64Encoded; + } } exports.ResponseStream = ResponseStream; //# sourceMappingURL=ResponseStream.js.map \ No newline at end of file diff --git a/dist/ResponseStream.js.map b/dist/ResponseStream.js.map index 9546391..42c8476 100644 --- a/dist/ResponseStream.js.map +++ b/dist/ResponseStream.js.map @@ -1 +1 @@ -{"version":3,"file":"ResponseStream.js","sourceRoot":"","sources":["../src/ResponseStream.ts"],"names":[],"mappings":";;;AAAA,mCAA+B;AAE/B,MAAa,cAAe,SAAQ,eAAM,CAAC,QAAQ;IAIjD;QACE,KAAK,EAAE,CAAA;QACP,IAAI,CAAC,QAAQ,GAAG,EAAE,CAAA;IACpB,CAAC;IACD,mLAAmL;IACnL,gDAAgD;IAChD,MAAM,CACJ,KAAU,EACV,QAAwB,EACxB,QAAwC;QAExC,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,EAAE,QAAQ,CAAC,CAAC,CAAA;QAChD,QAAQ,EAAE,CAAA;IACZ,CAAC;IAED,eAAe;QACb,OAAO,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAA;IACrC,CAAC;IAED,cAAc,CAAC,WAAmB;QAChC,IAAI,CAAC,YAAY,GAAG,WAAW,CAAA;IACjC,CAAC;CACF;AA1BD,wCA0BC"} \ No newline at end of file +{"version":3,"file":"ResponseStream.js","sourceRoot":"","sources":["../src/ResponseStream.ts"],"names":[],"mappings":";;;AAAA,mCAA+B;AAE/B,MAAa,cAAe,SAAQ,eAAM,CAAC,QAAQ;IAKjD;QACE,KAAK,EAAE,CAAA;QACP,IAAI,CAAC,QAAQ,GAAG,EAAE,CAAA;IACpB,CAAC;IACD,mLAAmL;IACnL,gDAAgD;IAChD,MAAM,CACJ,KAAU,EACV,QAAwB,EACxB,QAAwC;QAExC,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,EAAE,QAAQ,CAAC,CAAC,CAAA;QAChD,QAAQ,EAAE,CAAA;IACZ,CAAC;IAED,eAAe;QACb,OAAO,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAA;IACrC,CAAC;IAED,cAAc,CAAC,WAAmB;QAChC,IAAI,CAAC,YAAY,GAAG,WAAW,CAAA;IACjC,CAAC;IAED,kBAAkB,CAAC,eAAwB;QACzC,IAAI,CAAC,gBAAgB,GAAG,eAAe,CAAA;IACzC,CAAC;CACF;AA/BD,wCA+BC"} \ No newline at end of file diff --git a/dist/index.d.ts.map b/dist/index.d.ts.map index e8535da..8d2d720 100644 --- a/dist/index.d.ts.map +++ b/dist/index.d.ts.map @@ -1 +1 @@ -{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAGA,eAAO,MAAM,iBAAiB,eAE7B,CAAA;AACD,eAAO,MAAM,eAAe,aAAa,CAAA;AAEzC,wBAAgB,OAAO,CAAC,OAAO,EAAE,GAAG,GAAG,OAAO,CAK7C;AAED,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,QAAQ,GAAG,QAAQ,CAe7D;AAUD,OAAO,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAA"} \ No newline at end of file +{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAGA,eAAO,MAAM,iBAAiB,eAE7B,CAAA;AACD,eAAO,MAAM,eAAe,aAAa,CAAA;AAEzC,wBAAgB,OAAO,CAAC,OAAO,EAAE,GAAG,GAAG,OAAO,CAK7C;AAED,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,QAAQ,GAAG,QAAQ,CAyB7D;AAUD,OAAO,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAA"} \ No newline at end of file diff --git a/dist/index.js b/dist/index.js index 2ccabfe..7062437 100644 --- a/dist/index.js +++ b/dist/index.js @@ -20,8 +20,13 @@ function streamifyResponse(handler) { apply: async function (target, _, argList) { const responseStream = patchArgs(argList); await target(...argList); - // Todo - honor content type - return responseStream.getBufferedData().toString(); + return Object.assign(Object.assign({ statusCode: 200, headers: { + 'content-type': responseStream._contentType || 'application/json', + } }, (responseStream._isBase64Encoded + ? { isBase64Encoded: responseStream._isBase64Encoded } + : {})), { body: responseStream._isBase64Encoded + ? responseStream.getBufferedData().toString('base64') + : responseStream.getBufferedData().toString() }); }, }); } diff --git a/dist/index.js.map b/dist/index.js.map index 9b2f21f..e75c085 100644 --- a/dist/index.js.map +++ b/dist/index.js.map @@ -1 +1 @@ -{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,YAAY,CAAA;;;AAEZ,qDAAiD;AACpC,QAAA,iBAAiB,GAAG,MAAM,CAAC,GAAG,CACzC,sCAAsC,CACvC,CAAA;AACY,QAAA,eAAe,GAAG,UAAU,CAAA;AAEzC,SAAgB,OAAO,CAAC,OAAY;IAClC,OAAO,CACL,OAAO,CAAC,yBAAiB,CAAC,KAAK,SAAS;QACxC,OAAO,CAAC,yBAAiB,CAAC,KAAK,uBAAe,CAC/C,CAAA;AACH,CAAC;AALD,0BAKC;AAED,SAAgB,iBAAiB,CAAC,OAAiB;IACjD,6BAA6B;IAC7B,IAAI,OAAO,CAAC,OAAO,CAAC,EAAE;QACpB,aAAa;QACb,OAAO,SAAS,CAAC,iBAAiB,CAAC,OAAO,CAAC,CAAA;KAC5C;SAAM;QACL,OAAO,IAAI,KAAK,CAAC,OAAO,EAAE;YACxB,KAAK,EAAE,KAAK,WAAW,MAAM,EAAE,CAAC,EAAE,OAAO;gBACvC,MAAM,cAAc,GAAmB,SAAS,CAAC,OAAO,CAAC,CAAA;gBACzD,MAAM,MAAM,CAAC,GAAG,OAAO,CAAC,CAAA;gBACxB,4BAA4B;gBAC5B,OAAO,cAAc,CAAC,eAAe,EAAE,CAAC,QAAQ,EAAE,CAAA;YACpD,CAAC;SACF,CAAC,CAAA;KACH;AACH,CAAC;AAfD,8CAeC;AAED,SAAS,SAAS,CAAC,OAAc;IAC/B,IAAI,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,YAAY,+BAAc,CAAC,EAAE;QAC3C,MAAM,cAAc,GAAG,IAAI,+BAAc,EAAE,CAAA;QAC3C,OAAO,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC,EAAE,cAAc,CAAC,CAAA;KACrC;IACD,OAAO,OAAO,CAAC,CAAC,CAAC,CAAA;AACnB,CAAC;AAED,mDAAiD;AAAxC,gHAAA,cAAc,OAAA"} \ No newline at end of file +{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,YAAY,CAAA;;;AAEZ,qDAAiD;AACpC,QAAA,iBAAiB,GAAG,MAAM,CAAC,GAAG,CACzC,sCAAsC,CACvC,CAAA;AACY,QAAA,eAAe,GAAG,UAAU,CAAA;AAEzC,SAAgB,OAAO,CAAC,OAAY;IAClC,OAAO,CACL,OAAO,CAAC,yBAAiB,CAAC,KAAK,SAAS;QACxC,OAAO,CAAC,yBAAiB,CAAC,KAAK,uBAAe,CAC/C,CAAA;AACH,CAAC;AALD,0BAKC;AAED,SAAgB,iBAAiB,CAAC,OAAiB;IACjD,6BAA6B;IAC7B,IAAI,OAAO,CAAC,OAAO,CAAC,EAAE;QACpB,aAAa;QACb,OAAO,SAAS,CAAC,iBAAiB,CAAC,OAAO,CAAC,CAAA;KAC5C;SAAM;QACL,OAAO,IAAI,KAAK,CAAC,OAAO,EAAE;YACxB,KAAK,EAAE,KAAK,WAAW,MAAM,EAAE,CAAC,EAAE,OAAO;gBACvC,MAAM,cAAc,GAAmB,SAAS,CAAC,OAAO,CAAC,CAAA;gBACzD,MAAM,MAAM,CAAC,GAAG,OAAO,CAAC,CAAA;gBACxB,qCACE,UAAU,EAAE,GAAG,EACf,OAAO,EAAE;wBACP,cAAc,EAAE,cAAc,CAAC,YAAY,IAAI,kBAAkB;qBAClE,IACE,CAAC,cAAc,CAAC,gBAAgB;oBACjC,CAAC,CAAC,EAAE,eAAe,EAAE,cAAc,CAAC,gBAAgB,EAAE;oBACtD,CAAC,CAAC,EAAE,CAAC,KACP,IAAI,EAAE,cAAc,CAAC,gBAAgB;wBACnC,CAAC,CAAC,cAAc,CAAC,eAAe,EAAE,CAAC,QAAQ,CAAC,QAAQ,CAAC;wBACrD,CAAC,CAAC,cAAc,CAAC,eAAe,EAAE,CAAC,QAAQ,EAAE,IAChD;YACH,CAAC;SACF,CAAC,CAAA;KACH;AACH,CAAC;AAzBD,8CAyBC;AAED,SAAS,SAAS,CAAC,OAAc;IAC/B,IAAI,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,YAAY,+BAAc,CAAC,EAAE;QAC3C,MAAM,cAAc,GAAG,IAAI,+BAAc,EAAE,CAAA;QAC3C,OAAO,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC,EAAE,cAAc,CAAC,CAAA;KACrC;IACD,OAAO,OAAO,CAAC,CAAC,CAAC,CAAA;AACnB,CAAC;AAED,mDAAiD;AAAxC,gHAAA,cAAc,OAAA"} \ No newline at end of file diff --git a/examples/src/binary-base64-handler.ts b/examples/src/binary-base64-handler.ts new file mode 100644 index 0000000..872677e --- /dev/null +++ b/examples/src/binary-base64-handler.ts @@ -0,0 +1,16 @@ +import { APIGatewayProxyEvent } from 'aws-lambda' +import { ResponseStream, streamifyResponse } from 'lambda-stream' +import { Readable } from 'stream' +import { pipeline } from 'stream/promises' + +export const binaryBase64Handler = streamifyResponse(myHandler) + +async function myHandler( + event: APIGatewayProxyEvent, + responseStream: ResponseStream +): Promise { + const source = Readable.from(Buffer.from('hello world')) + responseStream.setContentType('binary/octet-stream') + responseStream.setIsBase64Encoded(true) + await pipeline(source, responseStream) +} diff --git a/src/ResponseStream.ts b/src/ResponseStream.ts index b627471..fab8c36 100644 --- a/src/ResponseStream.ts +++ b/src/ResponseStream.ts @@ -3,6 +3,7 @@ import { Stream } from 'stream' export class ResponseStream extends Stream.Writable { private response: Buffer[] _contentType?: string + _isBase64Encoded?: boolean constructor() { super() @@ -26,4 +27,8 @@ export class ResponseStream extends Stream.Writable { setContentType(contentType: string) { this._contentType = contentType } + + setIsBase64Encoded(isBase64Encoded: boolean) { + this._isBase64Encoded = isBase64Encoded + } } diff --git a/src/index.ts b/src/index.ts index 752e04a..b96173a 100644 --- a/src/index.ts +++ b/src/index.ts @@ -23,8 +23,18 @@ export function streamifyResponse(handler: Function): Function { apply: async function (target, _, argList) { const responseStream: ResponseStream = patchArgs(argList) await target(...argList) - // Todo - honor content type - return responseStream.getBufferedData().toString() + return { + statusCode: 200, + headers: { + 'content-type': responseStream._contentType || 'application/json', + }, + ...(responseStream._isBase64Encoded + ? { isBase64Encoded: responseStream._isBase64Encoded } + : {}), + body: responseStream._isBase64Encoded + ? responseStream.getBufferedData().toString('base64') + : responseStream.getBufferedData().toString(), + } }, }) } diff --git a/test/binary-pipeline.spec.ts b/test/binary-pipeline.spec.ts new file mode 100644 index 0000000..8636459 --- /dev/null +++ b/test/binary-pipeline.spec.ts @@ -0,0 +1,9 @@ +import { binaryBase64Handler } from '../examples/src/binary-base64-handler' + +describe('simple handler', () => { + it('awaits and returns the response', async () => { + const resp = await binaryBase64Handler('hello') + const decodedMessage = Buffer.from(resp.body, 'base64').toString() + expect(decodedMessage).toEqual('hello world') + }) +}) diff --git a/test/pipeline.spec.ts b/test/pipeline.spec.ts index 68e4174..7aae0a2 100644 --- a/test/pipeline.spec.ts +++ b/test/pipeline.spec.ts @@ -3,7 +3,7 @@ const { gzip } = require('../examples/example.js') describe('simple handler', () => { it('awaits and returns the response', async () => { const resp = await gzip('hello') - const parsed = JSON.parse(resp) + const parsed = JSON.parse(resp.body) expect(parsed).toMatchObject({ hello: 'world' }) }) }) diff --git a/test/simpleHandler.spec.ts b/test/simpleHandler.spec.ts index bf1e6d0..8266779 100644 --- a/test/simpleHandler.spec.ts +++ b/test/simpleHandler.spec.ts @@ -3,6 +3,6 @@ import { handler } from '../examples/src/handler' describe('simple handler', () => { it('awaits and returns the response', async () => { const resp = await handler('hello') - expect(resp).toEqual('Hello, world!') + expect(resp.body).toEqual('Hello, world!') }) })