gzipEncodeResponse function

FutureOr<Response> gzipEncodeResponse(
  1. Response response, {
  2. int minimalGzipContentLength = _defaultMinimalGzipContentLength,
  3. _AlreadyCompressedContentType? alreadyCompressedContentType,
  4. int compressionLevel = _defaultGzipCompressionLevel,
  5. bool addCompressionRatioHeader = true,
  6. bool addServerTiming = false,
  7. String serverTimingEntryName = 'gzip',
})

Converts response to a gzip encoding response. Checks canGzipEncodeResponse.

  • minimalGzipContentLength is the minimal size for a content to be compressed. Default to 512.
  • alreadyCompressedContentType is a function that returns true if the passed contentType is already compressed, like a PNG, JPEG or Zip. Defaults to isAlreadyCompressedContentType.
  • If addCompressionRatioHeader is true it adds the header X-Compression-Ratio, with compression info, e.g.: 0.55 (550/1000)
  • If addServerTiming is true, include or append Gzip encoding timing to the server-timing header.
  • serverTimingEntryName is the entry name to be used in the server-timing header. See createGzipMiddleware.

Implementation

FutureOr<Response> gzipEncodeResponse(
  Response response, {
  int minimalGzipContentLength = _defaultMinimalGzipContentLength,
  _AlreadyCompressedContentType? alreadyCompressedContentType,
  int compressionLevel = _defaultGzipCompressionLevel,
  bool addCompressionRatioHeader = true,
  bool addServerTiming = false,
  String serverTimingEntryName = 'gzip',
}) async {
  if (!canGzipEncodeResponse(response,
      minimalGzipContentLength: minimalGzipContentLength,
      alreadyCompressedContentType: alreadyCompressedContentType)) {
    return response;
  }

  var gzipInit = DateTime.now();

  var bufferInitialCapacity = response.contentLength ?? 1024 * 4;

  // Read the body bytes from the response:
  var bytesBuffer = await response.read().fold<_BytesBuffer>(
      _BytesBuffer(bufferInitialCapacity),
      (result, bytes) => result..addAll(bytes));

  var gzipEncoder = compressionLevel == _defaultGzipCompressionLevel
      ? _defaultGzipEncoder
      : ZLibEncoder(gzip: true, level: compressionLevel);

  // Compressed body:
  var compressedBody = gzipEncoder.convert(bytesBuffer.toUint8List());

  var bodyLength = bytesBuffer.length;
  var compressedBodyLength = compressedBody.length;

  var headers = Map<String, String>.from(response.headers);

  headers[HttpHeaders.contentEncodingHeader] = 'gzip';
  headers[HttpHeaders.contentLengthHeader] = compressedBodyLength.toString();

  if (addCompressionRatioHeader) {
    var compressionRatio = compressedBodyLength / bodyLength;

    var compressionRatioStr = '$compressionRatio';
    if (compressionRatioStr.length > 6) {
      compressionRatioStr = compressionRatio.toStringAsFixed(4);
    }

    headers['X-Compression-Ratio'] =
        '$compressionRatioStr ($compressedBodyLength/$bodyLength)';
  }

  if (addServerTiming) {
    const headerServerTiming = 'server-timing';

    var gzipTime = DateTime.now().difference(gzipInit);
    var dur = gzipTime.inMicroseconds / 1000;

    var serverTiming2 = StringBuffer();

    var serverTiming = headers[headerServerTiming];
    if (serverTiming != null && serverTiming.isNotEmpty) {
      serverTiming2.write(serverTiming);
      serverTiming2.write(',');
    }

    serverTiming2.write(serverTimingEntryName);
    serverTiming2.write(';dur=');
    serverTiming2.write(dur);

    headers[headerServerTiming] = serverTiming2.toString();
  }

  return response.change(headers: headers, body: compressedBody);
}