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>());
        }
Beispiel #3
0
        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>());
    }
Beispiel #5
0
        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));
        }
Beispiel #6
0
        /// <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));
        }
Beispiel #8
0
    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);
Beispiel #9
0
    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);
    }
Beispiel #10
0
    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);
        }