public async Task Invoke(HttpContext context) { StringValues encodings = context.Request.Headers[HeaderNames.AcceptEncoding]; if (!StringValues.IsNullOrEmpty(encodings) && StringWithQualityHeaderValue.TryParseList(encodings, out var encodingsList) && (encodingsList != null) && (encodingsList.Count > 0)) { string[] encodingsWithQuality = new string[encodingsList.Count]; for (int encodingIndex = 0; encodingIndex < encodingsList.Count; encodingIndex++) { // If there is any quality value provided don't change anything if (encodingsList[encodingIndex].Quality.HasValue) { encodingsWithQuality = null; break; } else { var encodingValue = encodingsList[encodingIndex].Value.Value; encodingsWithQuality[encodingIndex] = (new StringWithQualityHeaderValue(encodingValue, _encodingQuality.ContainsKey(encodingValue) ? _encodingQuality[encodingValue] : 0.1)).ToString(); } } if (encodingsWithQuality != null) { context.Request.Headers[HeaderNames.AcceptEncoding] = new StringValues(encodingsWithQuality); } } await _next(context); }
private static IList <StringWithQualityHeaderValue> GetAcceptCharsetHeaderValues(HttpRequest request) { if (StringWithQualityHeaderValue.TryParseList(request.Headers[HeaderNames.AcceptCharset], out var result)) { return(result); } return(Array.Empty <StringWithQualityHeaderValue>()); }
internal static IList<StringWithQualityHeaderValue> GetAcceptCharsetHeaderValues(OutputFormatterWriteContext context) { var request = context.MazeContext.Request; if (StringWithQualityHeaderValue.TryParseList(request.Headers[HeaderNames.AcceptCharset], out IList<StringWithQualityHeaderValue> result)) { return result; } return Array.Empty<StringWithQualityHeaderValue>(); }
internal static IList <StringWithQualityHeaderValue> GetAcceptCharsetHeaderValues(OutputFormatterWriteContext context) { var request = context.HttpContext.Request; if (StringWithQualityHeaderValue.TryParseList(request.Headers.AcceptCharset, out var result)) { return(result); } return(Array.Empty <StringWithQualityHeaderValue>()); }
public static CompressionType?GetType(StringValues contentEncoding) { if (!contentEncoding.Any()) { return(CompressionType.Unknown); } StringWithQualityHeaderValue.TryParseList(contentEncoding, out var encodingsList); if (encodingsList == null || !encodingsList.Any()) { return(CompressionType.Unknown); } return(GetType(encodingsList)); }
/// <inheritdoc /> public virtual ICompressionProvider GetCompressionProvider(HttpContext context) { IList <StringWithQualityHeaderValue> unsorted; // e.g. Accept-Encoding: gzip, deflate, sdch var accept = context.Request.Headers[HeaderNames.AcceptEncoding]; if (!StringValues.IsNullOrEmpty(accept) && StringWithQualityHeaderValue.TryParseList(accept, out unsorted) && unsorted != null && unsorted.Count > 0) { // TODO PERF: clients don't usually include quality values so this sort will not have any effect. Fast-path? var sorted = unsorted .Where(s => s.Quality.GetValueOrDefault(1) > 0) .OrderByDescending(s => s.Quality.GetValueOrDefault(1)); foreach (var encoding in sorted) { // There will rarely be more than three providers, and there's only one by default foreach (var provider in _providers) { if (StringSegment.Equals(provider.EncodingName, encoding.Value, StringComparison.OrdinalIgnoreCase)) { return(provider); } } // Uncommon but valid options if (StringSegment.Equals("*", encoding.Value, StringComparison.Ordinal)) { // Any return(_providers[0]); } if (StringSegment.Equals("identity", encoding.Value, StringComparison.OrdinalIgnoreCase)) { // No compression return(null); } } } return(null); }
public override ICompressionProvider GetCompressionProvider(HttpContext context) { // e.g. Accept-Encoding: gzip, deflate, sdch var accept = context.Request.Headers[HeaderNames.AcceptEncoding]; if (!StringValues.IsNullOrEmpty(accept) && StringWithQualityHeaderValue.TryParseList(accept, out var unsorted) && unsorted != null && unsorted.Count > 0) { foreach (var provider in _providers) { if (unsorted.Any( x => StringSegment.Equals(provider.EncodingName, x.Value, StringComparison.Ordinal))) { return(provider); } } } return(base.GetCompressionProvider(context)); }
private void NegotiateEncoding(HttpContext context) { var accept = context.Request.Headers.AcceptEncoding; if (StringValues.IsNullOrEmpty(accept)) { return; } if (!StringWithQualityHeaderValue.TryParseList(accept, out var encodings) || encodings.Count == 0) { return; } var selectedEncoding = StringSegment.Empty; var selectedEncodingQuality = .0; foreach (var encoding in encodings) { var encodingName = encoding.Value; var quality = encoding.Quality.GetValueOrDefault(1); if (quality >= double.Epsilon && quality >= selectedEncodingQuality) { if (quality == selectedEncodingQuality) { selectedEncoding = PickPreferredEncoding(context, selectedEncoding, encoding); } else if (_encodingExtensionMap.TryGetValue(encodingName, out var encodingExtension) && ResourceExists(context, encodingExtension)) { selectedEncoding = encodingName; selectedEncodingQuality = quality; } if (StringSegment.Equals("*", encodingName, StringComparison.Ordinal)) { // If we *, pick the first preferrent encoding for which a resource exists. selectedEncoding = PickPreferredEncoding(context, default, encoding);
public void TryParseList_WithSomeInvalidValues_IgnoresInvalidValues() { var inputs = new[] { "", "text1", "text 1", "text2", "\"text 2\",", "text3;q=0.5", "text4;q=0.5, extra stuff", " text5 ; q = 0.50 ", "\r\n text6 ; q = 0.05 ", "text7,text8;q=0.5", " text9 , text10 ; q = 0.5 ", }; Assert.True(StringWithQualityHeaderValue.TryParseList(inputs, out var results)); var expectedResults = new[] { new StringWithQualityHeaderValue("text1"), new StringWithQualityHeaderValue("1"), new StringWithQualityHeaderValue("text2"), new StringWithQualityHeaderValue("text3", 0.5), new StringWithQualityHeaderValue("text4", 0.5), new StringWithQualityHeaderValue("stuff"), new StringWithQualityHeaderValue("text5", 0.5), new StringWithQualityHeaderValue("text6", 0.05), new StringWithQualityHeaderValue("text7"), new StringWithQualityHeaderValue("text8", 0.5), new StringWithQualityHeaderValue("text9"), new StringWithQualityHeaderValue("text10", 0.5), }.ToList(); Assert.Equal(expectedResults, results); }
public void TryParseList_SetOfValidValueStrings_ParsedCorrectly() { var inputs = new[] { "", "text1", "text2,", "textA,textB", "text3;q=0.5", "text4;q=0.5,", " text5 ; q = 0.50 ", "\r\n text6 ; q = 0.05 ", "text7,text8;q=0.5", " text9 , text10 ; q = 0.5 ", }; Assert.True(StringWithQualityHeaderValue.TryParseList(inputs, out var results)); var expectedResults = new[] { new StringWithQualityHeaderValue("text1"), new StringWithQualityHeaderValue("text2"), new StringWithQualityHeaderValue("textA"), new StringWithQualityHeaderValue("textB"), new StringWithQualityHeaderValue("text3", 0.5), new StringWithQualityHeaderValue("text4", 0.5), new StringWithQualityHeaderValue("text5", 0.5), new StringWithQualityHeaderValue("text6", 0.05), new StringWithQualityHeaderValue("text7"), new StringWithQualityHeaderValue("text8", 0.5), new StringWithQualityHeaderValue("text9"), new StringWithQualityHeaderValue("text10", 0.5), }.ToList(); Assert.Equal(expectedResults, results); }
/// <inheritdoc /> public virtual ICompressionProvider?GetCompressionProvider(HttpContext context) { // e.g. Accept-Encoding: gzip, deflate, sdch var accept = context.Request.Headers.AcceptEncoding; // Note this is already checked in CheckRequestAcceptsCompression which _should_ prevent any of these other methods from being called. if (StringValues.IsNullOrEmpty(accept)) { Debug.Assert(false, "Duplicate check failed."); _logger.NoAcceptEncoding(); return(null); } if (!StringWithQualityHeaderValue.TryParseList(accept, out var encodings) || encodings.Count == 0) { _logger.NoAcceptEncoding(); return(null); } var candidates = new HashSet <ProviderCandidate>(); foreach (var encoding in encodings) { var encodingName = encoding.Value; var quality = encoding.Quality.GetValueOrDefault(1); if (quality < double.Epsilon) { continue; } 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)); } } // Uncommon but valid options if (StringSegment.Equals("*", encodingName, StringComparison.Ordinal)) { for (int i = 0; i < _providers.Length; i++) { var provider = _providers[i]; // Any provider is a candidate. candidates.Add(new ProviderCandidate(provider.EncodingName, quality, i, provider)); } break; } if (StringSegment.Equals("identity", encodingName, StringComparison.OrdinalIgnoreCase)) { // We add 'identity' to the list of "candidates" with a very low priority and no provider. // This will allow it to be ordered based on its quality (and priority) later in the method. candidates.Add(new ProviderCandidate(encodingName.Value, quality, priority: int.MaxValue, provider: null)); } } ICompressionProvider?selectedProvider = null; if (candidates.Count <= 1) { selectedProvider = candidates.FirstOrDefault().Provider; } else { selectedProvider = candidates .OrderByDescending(x => x.Quality) .ThenBy(x => x.Priority) .First().Provider; } if (selectedProvider == null) { // "identity" would match as a candidate but not have a provider implementation _logger.NoCompressionProvider(); return(null); } _logger.CompressingWith(selectedProvider.EncodingName); return(selectedProvider); }
/// <inheritdoc /> public virtual ICompressionProvider GetCompressionProvider(HttpContext context) { // e.g. Accept-Encoding: gzip, deflate, sdch var accept = context.Request.Headers[HeaderNames.AcceptEncoding]; if (StringValues.IsNullOrEmpty(accept)) { return(null); } if (StringWithQualityHeaderValue.TryParseList(accept, out var encodings)) { if (encodings.Count == 0) { return(null); } var candidates = new HashSet <ProviderCandidate>(); foreach (var encoding in encodings) { var encodingName = encoding.Value; var quality = encoding.Quality.GetValueOrDefault(1); if (quality < double.Epsilon) { continue; } 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)); } } // Uncommon but valid options if (StringSegment.Equals("*", encodingName, StringComparison.Ordinal)) { for (int i = 0; i < _providers.Length; i++) { var provider = _providers[i]; // Any provider is a candidate. candidates.Add(new ProviderCandidate(provider.EncodingName, quality, i, provider)); } break; } if (StringSegment.Equals("identity", encodingName, StringComparison.OrdinalIgnoreCase)) { // We add 'identity' to the list of "candidates" with a very low priority and no provider. // This will allow it to be ordered based on its quality (and priority) later in the method. candidates.Add(new ProviderCandidate(encodingName.Value, quality, priority: int.MaxValue, provider: null)); } } if (candidates.Count <= 1) { return(candidates.ElementAtOrDefault(0).Provider); } var accepted = candidates .OrderByDescending(x => x.Quality) .ThenBy(x => x.Priority) .First(); return(accepted.Provider); } return(null); }