< Summary

Line coverage
44%
Covered lines: 25
Uncovered lines: 31
Coverable lines: 56
Total lines: 104
Line coverage: 44.6%
Branch coverage
31%
Covered branches: 7
Total branches: 22
Branch coverage: 31.8%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

MethodBranch coverage Cyclomatic complexity NPath complexity Sequence coverage
.cctor()100%11100%
.ctor(...)100%11100%
TryParseValue(...)60%101057.14%
DecodeUtf8FromString(...)0%10100%
ToString(...)50%2277.77%

File(s)

https://raw.githubusercontent.com/dotnet/runtime/811a7eabb75c42db53440e8ba3f60c07511cfd1f/src/libraries/System.Net.Http/src/System/Net/Http/Headers/UriHeaderParser.cs

#LineLine coverage
 1// Licensed to the .NET Foundation under one or more agreements.
 2// The .NET Foundation licenses this file to you under the MIT license.
 3
 4using System;
 5using System.Diagnostics;
 6using System.Diagnostics.CodeAnalysis;
 7using System.Text;
 8
 9namespace System.Net.Http.Headers
 10{
 11    // Don't derive from BaseHeaderParser since parsing is delegated to Uri.TryCreate()
 12    // which will remove leading and trailing whitespace.
 13    internal sealed class UriHeaderParser : HttpHeaderParser
 14    {
 15        private readonly UriKind _uriKind;
 16
 117        internal static readonly UriHeaderParser RelativeOrAbsoluteUriParser =
 118            new UriHeaderParser(UriKind.RelativeOrAbsolute);
 19
 20        private UriHeaderParser(UriKind uriKind)
 121            : base(false)
 122        {
 123            _uriKind = uriKind;
 124        }
 25
 26        public override bool TryParseValue([NotNullWhen(true)] string? value, object? storeValue, ref int index, [NotNul
 2227        {
 2228            parsedValue = null;
 29
 30            // Some headers support empty/null values. This one doesn't.
 2231            if (string.IsNullOrEmpty(value) || (index == value.Length))
 1432            {
 1433                return false;
 34            }
 35
 836            string uriString = value;
 837            if (index > 0)
 038            {
 039                uriString = value.Substring(index);
 040            }
 41
 842            if (!Uri.TryCreate(uriString, _uriKind, out Uri? uri))
 043            {
 44                // Some servers send the host names in Utf-8.
 045                uriString = DecodeUtf8FromString(uriString);
 46
 047                if (!Uri.TryCreate(uriString, _uriKind, out uri))
 048                {
 049                    return false;
 50                }
 051            }
 52
 853            index = value.Length;
 854            parsedValue = uri;
 855            return true;
 2256        }
 57
 58        // The normal client header parser just casts bytes to chars (see GetString).
 59        // Check if those bytes were actually utf-8 instead of ASCII.
 60        // If not, just return the input value.
 61        internal static string DecodeUtf8FromString(string input)
 062        {
 063            if (!string.IsNullOrWhiteSpace(input))
 064            {
 065                int possibleUtf8Pos = input.AsSpan().IndexOfAnyExceptInRange((char)0, (char)127);
 066                if (possibleUtf8Pos >= 0 &&
 067                    !input.AsSpan(possibleUtf8Pos).ContainsAnyExceptInRange((char)0, (char)255))
 068                {
 069                    Span<byte> rawBytes = input.Length <= 256 ? stackalloc byte[input.Length] : new byte[input.Length];
 070                    for (int i = 0; i < input.Length; i++)
 071                    {
 072                        rawBytes[i] = (byte)input[i];
 073                    }
 74
 75                    try
 076                    {
 77                        // We don't want '?' replacement characters, just fail.
 078                        Encoding decoder = Encoding.GetEncoding("utf-8", EncoderFallback.ExceptionFallback, DecoderFallb
 079                        return decoder.GetString(rawBytes);
 80                    }
 081                    catch (ArgumentException) { } // Not actually Utf-8
 082                }
 083            }
 84
 085            return input;
 086        }
 87
 88        public override string ToString(object value)
 1289        {
 1290            Debug.Assert(value is Uri);
 1291            Uri uri = (Uri)value;
 92
 1293            if (uri.IsAbsoluteUri)
 094            {
 095                return uri.AbsoluteUri;
 96            }
 97            else
 1298            {
 1299                return uri.GetComponents(UriComponents.SerializationInfoString, UriFormat.UriEscaped);
 100            }
 12101        }
 102    }
 103}
 104