< Summary

Class:Azure.Storage.UriExtensions
Assembly:Azure.Storage.Files.Shares
File(s):C:\Git\azure-sdk-for-net\sdk\storage\Azure.Storage.Common\src\Shared\UriExtensions.cs
Covered lines:33
Uncovered lines:6
Coverable lines:39
Total lines:139
Line coverage:84.6% (33 of 39)
Covered branches:19
Total branches:28
Branch coverage:67.8% (19 of 28)

Metrics

MethodCyclomatic complexity Line coverage Branch coverage
AppendToPath(...)-100%50%
GetQueryParameters(...)-91.67%80%
GetAccountNameFromDomain(...)-100%100%
GetAccountNameFromDomain(...)-100%100%
GetPath(...)-100%50%
IsHostIPEndPointStyle(...)-100%50%
AppendQueryParameter(...)-0%0%

File(s)

C:\Git\azure-sdk-for-net\sdk\storage\Azure.Storage.Common\src\Shared\UriExtensions.cs

#LineLine coverage
 1// Copyright (c) Microsoft Corporation. All rights reserved.
 2// Licensed under the MIT License.
 3
 4using System;
 5using System.Collections.Generic;
 6using System.Globalization;
 7using System.Net;
 8using System.Text;
 9
 10namespace Azure.Storage
 11{
 12    /// <summary>
 13    /// Extension methods used to manipulate URIs.
 14    /// </summary>
 15    internal static class UriExtensions
 16    {
 17        /// <summary>
 18        /// Append a segment to a URIs path.
 19        /// </summary>
 20        /// <param name="uri">The URI.</param>
 21        /// <param name="segment">The relative segment to append.</param>
 22        /// <returns>The combined URI.</returns>
 23        public static Uri AppendToPath(this Uri uri, string segment)
 24        {
 55725            var builder = new UriBuilder(uri);
 55726            var path = builder.Path;
 55727            var seperator = (path.Length == 0 || path[path.Length - 1] != '/') ? "/" : "";
 28            // In URLs, the percent sign is used to encode special characters, so if the segment
 29            // has a percent sign in their URL path, we have to encode it before adding it to the path
 55730            segment = segment.Replace(Constants.PercentSign, Constants.EncodedPercentSign);
 55731            builder.Path += seperator + segment;
 55732            return builder.Uri;
 33        }
 34
 35        /// <summary>
 36        /// Get the (already encoded) query parameters on a URI.
 37        /// </summary>
 38        /// <param name="uri">The URI.</param>
 39        /// <returns>Dictionary mapping query parameters to values.</returns>
 40        public static IDictionary<string, string> GetQueryParameters(this Uri uri)
 41        {
 329242            var parameters = new Dictionary<string, string>();
 329243            var query = uri.Query ?? "";
 329244            if (!string.IsNullOrEmpty(query))
 45            {
 288246                if (query.StartsWith("?", true, CultureInfo.InvariantCulture))
 47                {
 288248                    query = query.Substring(1);
 49                }
 1187450                foreach (var param in query.Split(new[] { '&' }, StringSplitOptions.RemoveEmptyEntries))
 51                {
 305552                    var parts = param.Split(new[] { '=' }, 2);
 305553                    var name = WebUtility.UrlDecode(parts[0]);
 305554                    if (parts.Length == 1)
 55                    {
 056                        parameters.Add(name, default);
 57                    }
 58                    else
 59                    {
 305560                        parameters.Add(name, WebUtility.UrlDecode(parts[1]));
 61                    }
 62                }
 63            }
 329264            return parameters;
 65        }
 66
 67        /// <summary>
 68        /// Get the account name from the domain portion of a Uri.
 69        /// </summary>
 70        /// <param name="uri">The Uri.</param>
 71        /// <param name="serviceSubDomain">The service subdomain used to validate that the
 72        /// domain is in the expected format. This should be "blob" for blobs, "file" for files,
 73        /// "queue" for queues, "blob" and "dfs" for datalake.</param>
 74        /// <returns>Account name or null if not able to be parsed.</returns>
 75        public static string GetAccountNameFromDomain(this Uri uri, string serviceSubDomain) =>
 116176            GetAccountNameFromDomain(uri.Host, serviceSubDomain);
 77
 78        /// <summary>
 79        /// Get the account name from the host.
 80        /// </summary>
 81        /// <param name="host">Host.</param>
 82        /// <param name="serviceSubDomain">The service subdomain used to validate that the
 83        /// domain is in the expected format. This should be "blob" for blobs, "file" for files,
 84        /// "queue" for queues, "blob" and "dfs" for datalake.</param>
 85        /// <returns>Account name or null if not able to be parsed.</returns>
 86        public static string GetAccountNameFromDomain(string host, string serviceSubDomain)
 87        {
 116188            var accountEndIndex = host.IndexOf(".", StringComparison.InvariantCulture);
 116189            if (accountEndIndex >= 0)
 90            {
 116191                var serviceStartIndex = accountEndIndex + 1;
 116192                var serviceEndIndex = host.IndexOf(".", serviceStartIndex, StringComparison.InvariantCulture);
 116193                if (serviceEndIndex > serviceStartIndex)
 94                {
 115995                    var service = host.Substring(serviceStartIndex, serviceEndIndex - serviceStartIndex);
 115996                    if (service == serviceSubDomain)
 97                    {
 115198                        return host.Substring(0, accountEndIndex);
 99                    }
 100                }
 101            }
 10102            return null;
 103        }
 104
 105        /// <summary>
 106        /// If path starts with a slash, remove it
 107        /// </summary>
 108        /// <param name="uri">The Uri.</param>
 109        /// <returns>Sanitized Uri.</returns>
 110        public static string GetPath(this Uri uri) =>
 1167111            (uri.AbsolutePath[0] == '/') ?
 1167112                uri.AbsolutePath.Substring(1) :
 1167113                uri.AbsolutePath;
 114
 115        // See remarks at https://docs.microsoft.com/en-us/dotnet/api/system.net.ipaddress.tryparse?view=netframework-4.
 116        /// <summary>
 117        /// Check to see if Uri is using IP Endpoint style.
 118        /// </summary>
 119        /// <param name="uri">The Uri.</param>
 120        /// <returns>True if using IP Endpoint style.</returns>
 121        public static bool IsHostIPEndPointStyle(this Uri uri) =>
 1167122           !string.IsNullOrEmpty(uri.Host) &&
 1167123            uri.Host.IndexOf(".", StringComparison.InvariantCulture) >= 0 &&
 1167124            IPAddress.TryParse(uri.Host, out _);
 125
 126        /// <summary>
 127        /// Appends a query parameter to the string builder.
 128        /// </summary>
 129        /// <param name="sb">string builder instance.</param>
 130        /// <param name="key">query parameter key.</param>
 131        /// <param name="value">query parameter value.</param>
 132        internal static void AppendQueryParameter(this StringBuilder sb, string key, string value) =>
 0133            sb
 0134            .Append(sb.Length > 0 ? "&" : "")
 0135            .Append(key)
 0136            .Append('=')
 0137            .Append(value);
 138    }
 139}