< Summary

Information
Class: System.Net.CredentialCacheKey
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: 44
Coverable lines: 44
Total lines: 148
Line coverage: 0%
Branch coverage
0%
Covered branches: 0
Total branches: 22
Branch coverage: 0%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

MethodBranch coverage Cyclomatic complexity NPath complexity Sequence coverage
.ctor(...)100%110%
Match(...)0%880%
IsPrefix(...)0%880%
GetHashCode()100%110%
Equals(...)0%660%
Equals(...)100%110%
ToString()100%110%

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;
 015        public readonly int UriPrefixLength = -1;
 16        public readonly string AuthenticationType;
 17
 018        internal CredentialCacheKey(Uri uriPrefix, string authenticationType)
 019        {
 020            Debug.Assert(uriPrefix != null);
 021            Debug.Assert(authenticationType != null);
 22
 023            UriPrefix = uriPrefix;
 024            UriPrefixLength = UriPrefix.AbsolutePath.LastIndexOf('/');
 025            AuthenticationType = authenticationType;
 026        }
 27
 28        internal bool Match(Uri uri, int prefixLen, string authenticationType)
 029        {
 030            if (uri == null || authenticationType == null)
 031            {
 032                return false;
 33            }
 34
 35            // If the protocols don't match, this credential is not applicable for the given Uri.
 036            if (!string.Equals(authenticationType, AuthenticationType, StringComparison.OrdinalIgnoreCase))
 037            {
 038                return false;
 39            }
 40
 041            if (NetEventSource.Log.IsEnabled()) NetEventSource.Info(this, $"Match({UriPrefix} & {uri})");
 42
 043            return IsPrefix(uri, prefixLen);
 044        }
 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)
 059        {
 060            Debug.Assert(uri != null);
 061            Uri uriPrefix = UriPrefix;
 62
 063            if (uriPrefix.Scheme != uri.Scheme || uriPrefix.Host != uri.Host || uriPrefix.Port != uri.Port)
 064            {
 065                return false;
 66            }
 67
 068            if (UriPrefixLength > prefixLen)
 069            {
 070                return false;
 71            }
 72
 073            return string.Compare(uri.AbsolutePath, 0, uriPrefix.AbsolutePath, 0, UriPrefixLength, StringComparison.Ordi
 074        }
 75
 76        public override int GetHashCode() =>
 077            StringComparer.OrdinalIgnoreCase.GetHashCode(AuthenticationType) ^
 078            UriPrefix.GetHashCode();
 79
 80        public bool Equals([NotNullWhen(true)] CredentialCacheKey? other)
 081        {
 082            if (other == null)
 083            {
 084                return false;
 85            }
 86
 087            bool equals =
 088                string.Equals(AuthenticationType, other.AuthenticationType, StringComparison.OrdinalIgnoreCase) &&
 089                UriPrefix.Equals(other.UriPrefix);
 90
 091            if (NetEventSource.Log.IsEnabled()) NetEventSource.Info(this, $"Equals({this},{other}) returns {equals}");
 92
 093            return equals;
 094        }
 95
 096        public override bool Equals([NotNullWhen(true)] object? obj) => Equals(obj as CredentialCacheKey);
 97
 98        public override string ToString() =>
 099            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
 105        {
 106            int longestMatchPrefix = -1;
 107            mostSpecificMatch = null;
 108            mostSpecificMatchUri = null;
 109
 110            if (cache.Count == 0)
 111            {
 112                return false;
 113            }
 114
 115            // precompute the length of the prefix
 116            int uriPrefixLength = uriPrefix.AbsolutePath.LastIndexOf('/');
 117
 118            // Enumerate through every credential in the cache, get match with longest prefix
 119            foreach ((CredentialCacheKey key, NetworkCredential value) in cache)
 120            {
 121                int prefixLen = key.UriPrefixLength;
 122
 123                if (prefixLen <= longestMatchPrefix)
 124                {
 125                    // this credential can't provide a longer prefix match
 126                    continue;
 127                }
 128
 129                // Determine if this credential is applicable to the current Uri/AuthType
 130                if (key.Match(uriPrefix, uriPrefixLength, authType))
 131                {
 132                    // update the information about currently preferred match
 133                    longestMatchPrefix = prefixLen;
 134                    mostSpecificMatch = value;
 135                    mostSpecificMatchUri = key.UriPrefix;
 136
 137                    if (uriPrefixLength == prefixLen)
 138                    {
 139                        // we can't get any better than this
 140                        break;
 141                    }
 142                }
 143            }
 144
 145            return mostSpecificMatch != null;
 146        }
 147    }
 148}