@@ -34,6 +34,10 @@ const isCompressionAlgorithmKey = (key: number | undefined): key is keyof typeof
34
34
35
35
type CompressionAlgorithm = ( typeof CompressionAlgorithms ) [ keyof typeof CompressionAlgorithms ] ;
36
36
37
+ type SharedCompressionFilterConfig = {
38
+ serverSupportedEncodingHeader ?: string ;
39
+ } ;
40
+
37
41
abstract class CompressionHandler {
38
42
protected abstract compressMessage ( message : Buffer ) : Promise < Buffer > ;
39
43
protected abstract decompressMessage ( data : Buffer ) : Promise < Buffer > ;
@@ -181,14 +185,25 @@ export class CompressionFilter extends BaseFilter implements Filter {
181
185
private receiveCompression : CompressionHandler = new IdentityHandler ( ) ;
182
186
private defaultCompressionAlgorithm : CompressionAlgorithm | undefined ;
183
187
184
- constructor ( channelOptions : ChannelOptions ) {
188
+ constructor ( channelOptions : ChannelOptions , private sharedFilterConfig : SharedCompressionFilterConfig ) {
185
189
super ( ) ;
186
190
191
+ const serverSupportedEncodings = sharedFilterConfig . serverSupportedEncodingHeader ?. split ( ',' ) ;
187
192
const compressionAlgorithmKey = channelOptions [ 'grpc.default_compression_algorithm' ] ;
188
193
if ( compressionAlgorithmKey !== undefined ) {
189
194
if ( isCompressionAlgorithmKey ( compressionAlgorithmKey ) ) {
190
- this . defaultCompressionAlgorithm = CompressionAlgorithms [ compressionAlgorithmKey ] ;
191
- this . sendCompression = getCompressionHandler ( this . defaultCompressionAlgorithm ) ;
195
+ const clientSelectedEncoding = CompressionAlgorithms [ compressionAlgorithmKey ] ;
196
+ /**
197
+ * There are two possible situations here:
198
+ * 1) We don't have any info yet from the server about what compression it supports
199
+ * In that case we should just use what the client tells us to use
200
+ * 2) We've previously received a response from the server including a grpc-accept-encoding header
201
+ * In that case we only want to use the encoding chosen by the client if the server supports it
202
+ */
203
+ if ( ! serverSupportedEncodings || serverSupportedEncodings . includes ( clientSelectedEncoding ) ) {
204
+ this . defaultCompressionAlgorithm = clientSelectedEncoding ;
205
+ this . sendCompression = getCompressionHandler ( this . defaultCompressionAlgorithm ) ;
206
+ }
192
207
} else {
193
208
logging . log ( LogVerbosity . ERROR , `Invalid value provided for grpc.default_compression_algorithm option: ${ compressionAlgorithmKey } ` ) ;
194
209
}
@@ -223,6 +238,7 @@ export class CompressionFilter extends BaseFilter implements Filter {
223
238
* If not, reset the sendCompression filter and have it use the default IdentityHandler */
224
239
const serverSupportedEncodingsHeader = metadata . get ( 'grpc-accept-encoding' ) [ 0 ] as string | undefined ;
225
240
if ( serverSupportedEncodingsHeader ) {
241
+ this . sharedFilterConfig . serverSupportedEncodingHeader = serverSupportedEncodingsHeader ;
226
242
const serverSupportedEncodings = serverSupportedEncodingsHeader . split ( ',' ) ;
227
243
228
244
if ( ( this . sendCompression instanceof DeflateHandler && ! serverSupportedEncodings . includes ( 'deflate' ) )
@@ -263,8 +279,9 @@ export class CompressionFilter extends BaseFilter implements Filter {
263
279
264
280
export class CompressionFilterFactory
265
281
implements FilterFactory < CompressionFilter > {
282
+ private sharedFilterConfig : SharedCompressionFilterConfig = { } ;
266
283
constructor ( private readonly channel : Channel , private readonly options : ChannelOptions ) { }
267
284
createFilter ( callStream : Call ) : CompressionFilter {
268
- return new CompressionFilter ( this . options ) ;
285
+ return new CompressionFilter ( this . options , this . sharedFilterConfig ) ;
269
286
}
270
287
}
0 commit comments