@@ -2,8 +2,8 @@ import type { Middleware } from '../../types/index.js';
2
2
import type { CompressionOptions } from '../../types/rest.js' ;
3
3
import {
4
4
CACHE_CONTROL_NO_TRANSFORM_REGEX ,
5
- COMPRESSIBLE_CONTENT_TYPE_REGEX ,
6
5
COMPRESSION_ENCODING_TYPES ,
6
+ DEFAULT_COMPRESSION_RESPONSE_THRESHOLD ,
7
7
} from '../constants.js' ;
8
8
9
9
/**
@@ -25,8 +25,8 @@ import {
25
25
*
26
26
* @example
27
27
* ```typescript
28
- * import { Router } from '@aws-lambda-powertools/event-handler';
29
- * import { compress } from '@aws-lambda-powertools/event-handler/rest/middleware';
28
+ * import { Router } from '@aws-lambda-powertools/event-handler/experimental-rest ';
29
+ * import { compress } from '@aws-lambda-powertools/event-handler/experimental- rest/middleware';
30
30
*
31
31
* const app = new Router();
32
32
*
@@ -41,8 +41,8 @@ import {
41
41
*
42
42
* @example
43
43
* ```typescript
44
- * import { Router } from '@aws-lambda-powertools/event-handler';
45
- * import { compress } from '@aws-lambda-powertools/event-handler/rest/middleware';
44
+ * import { Router } from '@aws-lambda-powertools/event-handler/experimental-rest ';
45
+ * import { compress } from '@aws-lambda-powertools/event-handler/experimental- rest/middleware';
46
46
*
47
47
* const app = new Router();
48
48
*
@@ -62,59 +62,59 @@ import {
62
62
*/
63
63
64
64
const compress = ( options ?: CompressionOptions ) : Middleware => {
65
- const threshold = options ?. threshold ?? 1024 ;
65
+ const preferredEncoding =
66
+ options ?. encoding ?? COMPRESSION_ENCODING_TYPES . GZIP ;
67
+ const threshold =
68
+ options ?. threshold ?? DEFAULT_COMPRESSION_RESPONSE_THRESHOLD ;
66
69
67
70
return async ( _ , reqCtx , next ) => {
68
71
await next ( ) ;
69
72
70
- const contentLength = reqCtx . res . headers . get ( 'content-length' ) ;
71
- const isEncodedOrChunked =
72
- reqCtx . res . headers . has ( 'content-encoding' ) ||
73
- reqCtx . res . headers . has ( 'transfer-encoding' ) ;
74
-
75
- // Check if response should be compressed
76
73
if (
77
- isEncodedOrChunked ||
78
- reqCtx . request . method === 'HEAD' ||
79
- ( contentLength && Number ( contentLength ) < threshold ) ||
80
- ! shouldCompress ( reqCtx . res ) ||
81
- ! shouldTransform ( reqCtx . res ) ||
82
- ! reqCtx . res . body
74
+ ! shouldCompress ( reqCtx . request , reqCtx . res , preferredEncoding , threshold )
83
75
) {
84
76
return ;
85
77
}
86
78
87
- const acceptedEncoding = reqCtx . request . headers . get ( 'accept-encoding' ) ;
88
- const encoding =
89
- options ?. encoding ??
90
- Object . values ( COMPRESSION_ENCODING_TYPES ) . find ( ( encoding ) =>
91
- acceptedEncoding ?. includes ( encoding )
92
- ) ??
93
- COMPRESSION_ENCODING_TYPES . GZIP ;
94
-
95
79
// Compress the response
96
- const stream = new CompressionStream ( encoding ) ;
80
+ const stream = new CompressionStream ( preferredEncoding ) ;
97
81
reqCtx . res = new Response ( reqCtx . res . body . pipeThrough ( stream ) , reqCtx . res ) ;
98
82
reqCtx . res . headers . delete ( 'content-length' ) ;
99
- reqCtx . res . headers . set ( 'content-encoding' , encoding ) ;
83
+ reqCtx . res . headers . set ( 'content-encoding' , preferredEncoding ) ;
100
84
} ;
101
85
} ;
102
86
103
- const shouldCompress = ( res : Response ) => {
104
- const type = res . headers . get ( 'content-type' ) ;
105
- return (
106
- type &&
107
- ( COMPRESSIBLE_CONTENT_TYPE_REGEX . COMMON . test ( type ) ||
108
- COMPRESSIBLE_CONTENT_TYPE_REGEX . OCCASIONAL . test ( type ) ||
109
- COMPRESSIBLE_CONTENT_TYPE_REGEX . RARE . test ( type ) )
110
- ) ;
111
- } ;
87
+ const shouldCompress = (
88
+ request : Request ,
89
+ response : Response ,
90
+ preferredEncoding : NonNullable < CompressionOptions [ 'encoding' ] > ,
91
+ threshold : NonNullable < CompressionOptions [ 'threshold' ] >
92
+ ) : response is Response & { body : NonNullable < Response [ 'body' ] > } => {
93
+ const acceptedEncoding =
94
+ request . headers . get ( 'accept-encoding' ) ?? COMPRESSION_ENCODING_TYPES . ANY ;
95
+ const contentLength = response . headers . get ( 'content-length' ) ;
96
+ const cacheControl = response . headers . get ( 'cache-control' ) ;
97
+
98
+ const isEncodedOrChunked =
99
+ response . headers . has ( 'content-encoding' ) ||
100
+ response . headers . has ( 'transfer-encoding' ) ;
101
+
102
+ const shouldEncode =
103
+ ! acceptedEncoding . includes ( COMPRESSION_ENCODING_TYPES . IDENTITY ) &&
104
+ ( acceptedEncoding . includes ( preferredEncoding ) ||
105
+ acceptedEncoding . includes ( COMPRESSION_ENCODING_TYPES . ANY ) ) ;
112
106
113
- const shouldTransform = ( res : Response ) => {
114
- const cacheControl = res . headers . get ( 'cache-control' ) ;
115
- // Don't compress for Cache-Control: no-transform
116
- // https://tools.ietf.org/html/rfc7234#section-5.2.2.4
117
- return ! cacheControl || ! CACHE_CONTROL_NO_TRANSFORM_REGEX . test ( cacheControl ) ;
107
+ if (
108
+ ! shouldEncode ||
109
+ isEncodedOrChunked ||
110
+ request . method === 'HEAD' ||
111
+ ( contentLength && Number ( contentLength ) < threshold ) ||
112
+ ( cacheControl && CACHE_CONTROL_NO_TRANSFORM_REGEX . test ( cacheControl ) ) ||
113
+ ! response . body
114
+ ) {
115
+ return false ;
116
+ }
117
+ return true ;
118
118
} ;
119
119
120
120
export { compress } ;
0 commit comments