IDecompressor.cs 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899
  1. using System;
  2. using System.IO;
  3. using BestHTTP.Logger;
  4. namespace BestHTTP.Decompression
  5. {
  6. public struct DecompressedData
  7. {
  8. public readonly byte[] Data;
  9. public readonly int Length;
  10. internal DecompressedData(byte[] data, int length)
  11. {
  12. this.Data = data;
  13. this.Length = length;
  14. }
  15. }
  16. public interface IDecompressor : IDisposable
  17. {
  18. DecompressedData Decompress(byte[] data, int offset, int count, bool forceDecompress = false, bool dataCanBeLarger = false);
  19. }
  20. public static class DecompressorFactory
  21. {
  22. public const int MinLengthToDecompress = 256;
  23. public static void SetupHeaders(HTTPRequest request)
  24. {
  25. if (!request.HasHeader("Accept-Encoding"))
  26. {
  27. #if BESTHTTP_DISABLE_GZIP
  28. request.AddHeader("Accept-Encoding", "identity");
  29. #else
  30. if (BrotliDecompressor.IsSupported())
  31. request.AddHeader("Accept-Encoding", "br, gzip, identity");
  32. else
  33. request.AddHeader("Accept-Encoding", "gzip, identity");
  34. #endif
  35. }
  36. }
  37. public static IDecompressor GetDecompressor(string encoding, LoggingContext context)
  38. {
  39. if (encoding == null)
  40. return null;
  41. switch (encoding.ToLowerInvariant())
  42. {
  43. case "identity":
  44. case "utf-8":
  45. break;
  46. case "gzip": return new Decompression.GZipDecompressor(MinLengthToDecompress);
  47. case "br":
  48. if (Decompression.BrotliDecompressor.IsSupported())
  49. return new Decompression.BrotliDecompressor(MinLengthToDecompress);
  50. else
  51. goto default;
  52. default:
  53. HTTPManager.Logger.Warning("DecompressorFactory", "GetDecompressor - unsupported encoding: " + encoding, context);
  54. break;
  55. }
  56. return null;
  57. }
  58. /// <summary>
  59. /// Returns with a properly set up GZip/Deflate/Brotli stream, or null if the encoding is null or compiled for WebGl.
  60. /// </summary>
  61. public static Stream GetDecoderStream(Stream streamToDecode, string encoding)
  62. {
  63. if (streamToDecode == null)
  64. throw new ArgumentNullException(nameof(streamToDecode));
  65. if (string.IsNullOrEmpty(encoding))
  66. return null;
  67. switch (encoding)
  68. {
  69. #if !UNITY_WEBGL || UNITY_EDITOR
  70. case "gzip": return new Decompression.Zlib.GZipStream(streamToDecode, Decompression.Zlib.CompressionMode.Decompress);
  71. case "deflate": return new Decompression.Zlib.DeflateStream(streamToDecode, Decompression.Zlib.CompressionMode.Decompress);
  72. #if (NET_STANDARD_2_1 || UNITY_2021_2_OR_NEWER) && BESTHTTP_ENABLE_BROTLI
  73. case "br": return new System.IO.Compression.BrotliStream(streamToDecode, System.IO.Compression.CompressionMode.Decompress, true);
  74. #endif
  75. #endif
  76. //identity, utf-8, etc. Or compiled for WebGl.
  77. default:
  78. // Do not copy from one stream to an other, just return with the raw bytes
  79. return null;
  80. }
  81. }
  82. }
  83. }