@middy/http-content-encoding 3.0.0-alpha.2 → 3.0.0-alpha.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/index.js +89 -60
  2. package/package.json +6 -5
package/index.js CHANGED
@@ -1,90 +1,119 @@
1
- import { Readable, Writable, pipeline as pipelineCallback } from 'stream';
2
- import { promisify } from 'util';
3
- import { createBrotliCompress, createGzip, createDeflate } from 'zlib';
4
- import { normalizeHttpResponse } from '@middy/util';
5
- const pipeline = promisify(pipelineCallback);
1
+ /*
2
+ * `zstd` disabled due to lack of support in browsers
3
+ * https://github.com/Fyrd/caniuse/issues/4065
4
+ * https://github.com/andrew-aladev/brotli-vs-zstd
5
+ */
6
+
7
+ import { Readable, Writable, pipeline as pipelineCallback } from 'stream'
8
+ // import {pipeline} from 'stream/promises' // available in node >=15
9
+ import { promisify } from 'util'
10
+
11
+ import { createBrotliCompress, createGzip, createDeflate } from 'zlib'
12
+ // import {ZSTDCompress as createZstdCompress} from 'simple-zstd'
13
+
14
+ import { normalizeHttpResponse } from '@middy/util'
15
+ const pipeline = promisify(pipelineCallback)
16
+
6
17
  const contentEncodingStreams = {
7
18
  br: (opts = {}) => createBrotliCompress(opts),
19
+ // zstd: (opt = {}) => createZstdCompress(opts),
8
20
  gzip: (opts = {}) => createGzip(opts),
9
21
  deflate: (opts = {}) => createDeflate(opts)
10
- };
22
+ }
23
+
11
24
  const defaults = {
12
25
  br: undefined,
26
+ // zstd: undefined,
13
27
  gzip: undefined,
14
28
  deflate: undefined,
15
29
  overridePreferredEncoding: []
16
- };
17
-
18
- const httpContentEncodingMiddleware = opts => {
19
- const options = { ...defaults,
20
- ...opts
21
- };
22
-
23
- const httpContentEncodingMiddlewareAfter = async request => {
24
- normalizeHttpResponse(request);
25
- const {
26
- event: {
27
- preferredEncoding,
28
- preferredEncodings
29
- },
30
- response
31
- } = request;
32
-
33
- if (!preferredEncoding || response.isBase64Encoded) {
34
- return;
35
- }
30
+ }
31
+
32
+ const httpContentEncodingMiddleware = (opts) => {
33
+ const options = { ...defaults, ...opts }
36
34
 
37
- const bodyIsString = typeof response.body === 'string';
38
- let contentEncodingStream = contentEncodingStreams[preferredEncoding](options[preferredEncoding]);
39
- let contentEncoding = preferredEncoding;
35
+ const supportedContentEncodings = Object.keys(contentEncodingStreams)
40
36
 
37
+ const httpContentEncodingMiddlewareAfter = async (request) => {
38
+ normalizeHttpResponse(request)
39
+ const { event: { preferredEncoding, preferredEncodings }, response } = request
40
+
41
+ // Encoding not supported OR already encoded
42
+ if (response.isBase64Encoded || !preferredEncoding || !supportedContentEncodings.includes(preferredEncoding)) { return }
43
+
44
+ const bodyIsString = typeof response.body === 'string'
45
+
46
+ let contentEncodingStream = contentEncodingStreams[preferredEncoding](options[preferredEncoding])
47
+ let contentEncoding = preferredEncoding
41
48
  for (const encoding of options.overridePreferredEncoding) {
42
- if (!preferredEncodings.includes(encoding)) continue;
43
- contentEncodingStream = contentEncodingStreams[encoding](options[encoding]);
44
- contentEncoding = encoding;
45
- break;
49
+ if (!preferredEncodings.includes(encoding)) continue
50
+ contentEncodingStream = contentEncodingStreams[encoding](options[encoding])
51
+ contentEncoding = encoding
52
+ break
46
53
  }
47
54
 
48
55
  if (bodyIsString) {
49
- const readStream = Readable.from(response.body, {
50
- objectMode: false
51
- });
52
- const chunks = [];
56
+ const readStream = Readable.from(response.body, { objectMode: false })
57
+
58
+ const chunks = []
53
59
  const writeStream = new Writable({
54
- write(chunk, encoding, callback) {
55
- chunks.push(chunk);
56
- callback();
60
+ write (chunk, encoding, callback) {
61
+ chunks.push(chunk)
62
+ callback()
57
63
  }
64
+ })
58
65
 
59
- });
60
- await pipeline(readStream, contentEncodingStream, writeStream);
61
- const body = Buffer.concat(chunks).toString('base64');
66
+ await pipeline(
67
+ readStream,
68
+ contentEncodingStream,
69
+ writeStream
70
+ )
62
71
 
72
+ const body = Buffer.concat(chunks).toString('base64')
73
+
74
+ // Only apply encoding if it's smaller
63
75
  if (body.length < response.body.length) {
64
- response.headers['Content-Encoding'] = contentEncoding;
65
- response.body = body;
66
- response.isBase64Encoded = true;
76
+ response.headers['Content-Encoding'] = contentEncoding
77
+ response.body = body
78
+ response.isBase64Encoded = true
67
79
  }
68
80
  } else if (isReadableStream(response.body)) {
69
- response.headers['Content-Encoding'] = contentEncoding;
70
- response.body = response.body.pipe(contentEncodingStream);
71
- response.isBase64Encoded = true;
81
+ // Note: body to not cast to string to allow stream chaining
82
+ response.headers['Content-Encoding'] = contentEncoding
83
+ response.body = response.body.pipe(contentEncodingStream)
84
+ response.isBase64Encoded = true
72
85
  }
86
+ request.response = response
87
+ }
73
88
 
74
- request.response = response;
75
- };
76
-
77
- const httpContentEncodingMiddlewareOnError = async request => {
78
- if (request.response === undefined) return;
79
- return httpContentEncodingMiddlewareAfter(request);
80
- };
89
+ const httpContentEncodingMiddlewareOnError = async (request) => {
90
+ if (request.response === undefined) return
91
+ return httpContentEncodingMiddlewareAfter(request)
92
+ }
81
93
 
82
94
  return {
83
95
  after: httpContentEncodingMiddlewareAfter,
84
96
  onError: httpContentEncodingMiddlewareOnError
85
- };
86
- };
97
+ }
98
+ }
99
+
100
+ const isReadableStream = (stream) =>
101
+ typeof stream?.pipe === 'function' &&
102
+ stream?.readable !== false &&
103
+ typeof stream?._read === 'function' &&
104
+ typeof stream?._readableState === 'object'
87
105
 
88
- const isReadableStream = stream => typeof stream.pipe === 'function' && stream.readable !== false && typeof stream._read === 'function' && typeof stream._readableState === 'object';
106
+ const polyfillPipelinePromise = async () => {
107
+ if (process.version < 'v15.0.0') {
108
+ const stream = await import('stream');
109
+ const util = await import('util');
110
+ return util.promisify(stream.pipeline);
111
+ } else {
112
+ const stream = await import('stream/promises')
113
+ return stream.pipeline
114
+ }
115
+ }
116
+ global.pipeline = await polyfillPipelinePromise()
117
+ // import {pipeline} from 'stream/promises'
89
118
 
90
- export default httpContentEncodingMiddleware;
119
+ export default httpContentEncodingMiddleware
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@middy/http-content-encoding",
3
- "version": "3.0.0-alpha.2",
3
+ "version": "3.0.0-alpha.3",
4
4
  "description": "Http content encoding middleware for the middy framework",
5
5
  "type": "module",
6
6
  "engines": {
@@ -18,7 +18,8 @@
18
18
  ],
19
19
  "scripts": {
20
20
  "test": "npm run test:unit",
21
- "test:unit": "ava"
21
+ "test:unit": "ava",
22
+ "test:benchmark": "node __benchmarks__/index.js"
22
23
  },
23
24
  "license": "MIT",
24
25
  "keywords": [
@@ -50,10 +51,10 @@
50
51
  },
51
52
  "homepage": "https://github.com/middyjs/middy#readme",
52
53
  "dependencies": {
53
- "@middy/util": "^3.0.0-alpha.2"
54
+ "@middy/util": "^3.0.0-alpha.3"
54
55
  },
55
56
  "devDependencies": {
56
- "@middy/core": "^3.0.0-alpha.2"
57
+ "@middy/core": "^3.0.0-alpha.3"
57
58
  },
58
- "gitHead": "de30419273ecbff08f367f47c7e320ec981cf145"
59
+ "gitHead": "1441158711580313765e6d156046ef0fade0d156"
59
60
  }