< Summary

Information
Class: System.Net.CredentialCacheHelper
Assembly: System.Net.Http
File(s): D:\runner\runtime\src\libraries\Common\src\System\Net\CredentialCacheKey.cs
Line coverage
0%
Covered lines: 0
Uncovered lines: 26
Coverable lines: 26
Total lines: 148
Line coverage: 0%
Branch coverage
0%
Covered branches: 0
Total branches: 10
Branch coverage: 0%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

MethodBranch coverage Cyclomatic complexity NPath complexity Sequence coverage
TryGetCredential(...)0%10100%

File(s)

D:\runner\runtime\src\libraries\Common\src\System\Net\CredentialCacheKey.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.Collections;
 5using System.Collections.Generic;
 6using System.Diagnostics;
 7using System.Diagnostics.CodeAnalysis;
 8using System.Globalization;
 9
 10namespace System.Net
 11{
 12    internal sealed class CredentialCacheKey : IEquatable<CredentialCacheKey?>
 13    {
 14        public readonly Uri UriPrefix;
 15        public readonly int UriPrefixLength = -1;
 16        public readonly string AuthenticationType;
 17
 18        internal CredentialCacheKey(Uri uriPrefix, string authenticationType)
 19        {
 20            Debug.Assert(uriPrefix != null);
 21            Debug.Assert(authenticationType != null);
 22
 23            UriPrefix = uriPrefix;
 24            UriPrefixLength = UriPrefix.AbsolutePath.LastIndexOf('/');
 25            AuthenticationType = authenticationType;
 26        }
 27
 28        internal bool Match(Uri uri, int prefixLen, string authenticationType)
 29        {
 30            if (uri == null || authenticationType == null)
 31            {
 32                return false;
 33            }
 34
 35            // If the protocols don't match, this credential is not applicable for the given Uri.
 36            if (!string.Equals(authenticationType, AuthenticationType, StringComparison.OrdinalIgnoreCase))
 37            {
 38                return false;
 39            }
 40
 41            if (NetEventSource.Log.IsEnabled()) NetEventSource.Info(this, $"Match({UriPrefix} & {uri})");
 42
 43            return IsPrefix(uri, prefixLen);
 44        }
 45
 46        // IsPrefix (Uri)
 47        //
 48        // Determines whether <this> is a prefix of this URI. A prefix
 49        // match is defined as:
 50        //
 51        //     scheme match
 52        //     + host match
 53        //     + port match, if any
 54        //     + <prefix> path is a prefix of <URI> path, if any
 55        //
 56        // Returns:
 57        // True if <prefixUri> is a prefix of this URI
 58        private bool IsPrefix(Uri uri, int prefixLen)
 59        {
 60            Debug.Assert(uri != null);
 61            Uri uriPrefix = UriPrefix;
 62
 63            if (uriPrefix.Scheme != uri.Scheme || uriPrefix.Host != uri.Host || uriPrefix.Port != uri.Port)
 64            {
 65                return false;
 66            }
 67
 68            if (UriPrefixLength > prefixLen)
 69            {
 70                return false;
 71            }
 72
 73            return string.Compare(uri.AbsolutePath, 0, uriPrefix.AbsolutePath, 0, UriPrefixLength, StringComparison.Ordi
 74        }
 75
 76        public override int GetHashCode() =>
 77            StringComparer.OrdinalIgnoreCase.GetHashCode(AuthenticationType) ^
 78            UriPrefix.GetHashCode();
 79
 80        public bool Equals([NotNullWhen(true)] CredentialCacheKey? other)
 81        {
 82            if (other == null)
 83            {
 84                return false;
 85            }
 86
 87            bool equals =
 88                string.Equals(AuthenticationType, other.AuthenticationType, StringComparison.OrdinalIgnoreCase) &&
 89                UriPrefix.Equals(other.UriPrefix);
 90
 91            if (NetEventSource.Log.IsEnabled()) NetEventSource.Info(this, $"Equals({this},{other}) returns {equals}");
 92
 93            return equals;
 94        }
 95
 96        public override bool Equals([NotNullWhen(true)] object? obj) => Equals(obj as CredentialCacheKey);
 97
 98        public override string ToString() =>
 99            string.Create(CultureInfo.InvariantCulture, $"[{UriPrefixLength}]:{UriPrefix}:{AuthenticationType}");
 100    }
 101
 102    internal static class CredentialCacheHelper
 103    {
 104        public static bool TryGetCredential(Dictionary<CredentialCacheKey, NetworkCredential> cache, Uri uriPrefix, stri
 0105        {
 0106            int longestMatchPrefix = -1;
 0107            mostSpecificMatch = null;
 0108            mostSpecificMatchUri = null;
 109
 0110            if (cache.Count == 0)
 0111            {
 0112                return false;
 113            }
 114
 115            // precompute the length of the prefix
 0116            int uriPrefixLength = uriPrefix.AbsolutePath.LastIndexOf('/');
 117
 118            // Enumerate through every credential in the cache, get match with longest prefix
 0119            foreach ((CredentialCacheKey key, NetworkCredential value) in cache)
 0120            {
 0121                int prefixLen = key.UriPrefixLength;
 122
 0123                if (prefixLen <= longestMatchPrefix)
 0124                {
 125                    // this credential can't provide a longer prefix match
 0126                    continue;
 127                }
 128
 129                // Determine if this credential is applicable to the current Uri/AuthType
 0130                if (key.Match(uriPrefix, uriPrefixLength, authType))
 0131                {
 132                    // update the information about currently preferred match
 0133                    longestMatchPrefix = prefixLen;
 0134                    mostSpecificMatch = value;
 0135                    mostSpecificMatchUri = key.UriPrefix;
 136
 0137                    if (uriPrefixLength == prefixLen)
 0138                    {
 139                        // we can't get any better than this
 0140                        break;
 141                    }
 0142                }
 0143            }
 144
 0145            return mostSpecificMatch != null;
 0146        }
 147    }
 148}