ASP.NET Core中的响应压缩的实现
private void OnWrite() { if (!_compressionChecked) { _compressionChecked = true; //判定是否满意执行压缩相干的逻辑 if (_provider.ShouldCompressResponse(_context)) { //匹配Vary头信息对应的值 var varyValues = _context.Response.Headers.GetCommaSeparatedValues(HeaderNames.Vary); var varyByAcceptEncoding = false; //判定Vary的值是否为Accept-Encoding for (var i = 0; i < varyValues.Length; i++) { if (string.Equals(varyValues[i], HeaderNames.AcceptEncoding, StringComparison.OrdinalIgnoreCase)) { varyByAcceptEncoding = true; break; } } if (!varyByAcceptEncoding) { _context.Response.Headers.Append(HeaderNames.Vary, HeaderNames.AcceptEncoding); } //获取最佳的ICompressionProvider即最佳的压缩方法 var compressionProvider = ResolveCompressionProvider(); if (compressionProvider != null) { //配置选定的压缩算法,放入Content-Encoding头的值里 //客户端可以通过Content-Encoding头信息判定处事端回收的哪种压缩算法 _context.Response.Headers.Append(HeaderNames.ContentEncoding, compressionProvider.EncodingName); //举办压缩时,将 Content-MD5 删除该标头,由于正文内容已变动且哈希不再有用。 _context.Response.Headers.Remove(HeaderNames.ContentMD5); //举办压缩时,将 Content-Length 删除该标头,由于在对相应举办压缩时,正文内容会产生变动。 _context.Response.Headers.Remove(HeaderNames.ContentLength); //返回压缩相干输出流 _compressionStream = compressionProvider.CreateStream(_innerStream); } } } } private ICompressionProvider ResolveCompressionProvider() { if (!_providerCreated) { _providerCreated = true; //挪用ResponseCompressionProvider的要领返回最吻合的压缩算法 _compressionProvider = _provider.GetCompressionProvider(_context); } return _compressionProvider; } 从上面的逻辑我们可以看到,在执行压缩相干逻辑之前必要判定是否满意执行压缩相干的要领ShouldCompressResponse,这个要领是ResponseCompressionProvider里的要领,这里就不再粘贴代码了,原来就是判定逻辑我直接清算出来大抵就是一下几种环境 假如哀求是Https的环境下,是否配置了应承Https环境下压缩的配置,即ResponseCompressionOptions的EnableForHttps属性配置 Response.Head里不能包括Content-Range头信息 Response.Head里之前不能包括Content-Encoding头信息 Response.Head里之前必必要包括Content-Type头信息 返回的MimeType里不能包括设置的不必要压缩的范例,即ResponseCompressionOptions的ExcludedMimeTypes 返回的MimeType里必要包括设置的必要压缩的范例,即ResponseCompressionOptions的MimeTypes 假如不满意上面的两种环境,返回的MimeType里包括*/*也可以执行相应压缩 接下来我们查察ResponseCompressionProvider的GetCompressionProvider要领看它是怎样确定返回哪一种压缩范例的 public virtual ICompressionProvider GetCompressionProvider(HttpContext context) { var accept = context.Request.Headers[HeaderNames.AcceptEncoding]; //判定哀求头是否包括Accept-Encoding信念 if (StringValues.IsNullOrEmpty(accept)) { Debug.Assert(false, "Duplicate check failed."); return null; } //获取Accept-Encoding里的值,判定是否包括gzip、br、identity等,并返回匹配信息 if (!StringWithQualityHeaderValue.TryParseList(accept, out var encodings) || !encodings.Any()) { return null; } //按照哀求信息和配置信息计较匹配优先级 var candidates = new HashSet<ProviderCandidate>(); foreach (var encoding in encodings) { var encodingName = encoding.Value; //Quality涉及到一个很是伟大的算法,有乐趣的可以自行查阅 var quality = encoding.Quality.GetValueOrDefault(1); //quality需大于0 if (quality < double.Epsilon) { continue; } //匹配哀求头里encodingName和配置的providers压缩算法里EncodingName同等的算法 //从这里可以看出匹配的优先级和注册providers里的次序也有相关 for (int i = 0; i < _providers.Length; i++) { var provider = _providers[i]; if (StringSegment.Equals(provider.EncodingName, encodingName, StringComparison.OrdinalIgnoreCase)) { candidates.Add(new ProviderCandidate(provider.EncodingName, quality, i, provider)); } } //假如哀求头里EncodingName是*的环境则在全部注册的providers里举办匹配 if (StringSegment.Equals("*", encodingName, StringComparison.Ordinal)) { for (int i = 0; i < _providers.Length; i++) { var provider = _providers[i]; candidates.Add(new ProviderCandidate(provider.EncodingName, quality, i, provider)); } break; } //假如哀求头里EncodingName是identity的环境,则差池相应举办编码 if (StringSegment.Equals("identity", encodingName, StringComparison.OrdinalIgnoreCase)) { candidates.Add(new ProviderCandidate(encodingName.Value, quality, priority: int.MaxValue, provider: null)); } } ICompressionProvider selectedProvider = null; //假如匹配的只有一个则直接返回 if (candidates.Count <= 1) { selectedProvider = candidates.FirstOrDefault().Provider; } else { //假如匹配到多个则凭证Quality倒序和Priority正序的认真匹配第一个 selectedProvider = candidates .OrderByDescending(x => x.Quality) .ThenBy(x => x.Priority) .First().Provider; } //假如没有匹配到selectedProvider或是identity的环境直接返回null if (selectedProvider == null) { return null; } return selectedProvider; } 通过以上的先容我们可以大抵相识到相应压缩的大抵事变方法,简朴总结一下 起首配置压缩相干的算法范例或是压缩方针的MimeType 其次我们可以配置压缩级别,这将抉择压缩的质量和压缩机能 (编辑:湖南网) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |