Exemple #1
0
 public void TokenizeRequestPathTests()
 {
     AssertAreDeepEqual(HttpParsingHelper.TokenizeRequestPath("a/bb/ccc/dddd"), "a", "bb", "ccc", "dddd");
     AssertAreDeepEqual(HttpParsingHelper.TokenizeRequestPath("/a/bb/ccc/dddd"), "a", "bb", "ccc", "dddd");
     AssertAreDeepEqual(HttpParsingHelper.TokenizeRequestPath("/a/bb/ccc/dddd/"), "a", "bb", "ccc", "dddd", string.Empty);
     AssertAreDeepEqual(HttpParsingHelper.TokenizeRequestPath("/a/bb/ccc/dddd?ee"), "a", "bb", "ccc", "dddd");
     AssertAreDeepEqual(HttpParsingHelper.TokenizeRequestPath("/a/bb/ccc/dddd/?ee"), "a", "bb", "ccc", "dddd", string.Empty);
     AssertAreDeepEqual(HttpParsingHelper.TokenizeRequestPath("/a/bb/ccc/dddd#ee"), "a", "bb", "ccc", "dddd");
     AssertAreDeepEqual(HttpParsingHelper.TokenizeRequestPath("/a/bb/ccc/dddd?ee/ff"), "a", "bb", "ccc", "dddd");
 }
Exemple #2
0
 public void ParseResourcePathTests()
 {
     AssertRequestPathIsValid(HttpParsingHelper.ParseResourcePath("a/bb/ccc"), "a", "bb", "ccc", null);
     AssertRequestPathIsValid(HttpParsingHelper.ParseResourcePath("a/bb/ccc/"), "a", "bb", "ccc", string.Empty);
     AssertRequestPathIsValid(HttpParsingHelper.ParseResourcePath("/a/bb/ccc/dddd"), "a", "bb", "ccc", "dddd");
     AssertRequestPathIsValid(HttpParsingHelper.ParseResourcePath("/a/bb/ccc/dddd/"), "a", "bb", "ccc", "dddd");
     AssertRequestPathIsValid(HttpParsingHelper.ParseResourcePath("/a/bb/a/dddd"), "a", "bb", "a", "dddd");
     AssertRequestPathIsValid(HttpParsingHelper.ParseResourcePath("/a/bb/ccc/dddd?ee"), "a", "bb", "ccc", "dddd");
     AssertRequestPathIsValid(HttpParsingHelper.ParseResourcePath("/a/bb/ccc#ee/ff"), "a", "bb", "ccc", null);
     AssertRequestPathIsValid(HttpParsingHelper.ParseResourcePath("/a/bb/ccc/?ee/ff"), "a", "bb", "ccc", string.Empty);
 }
Exemple #3
0
        internal static string BuildOperationMoniker(string verb, List <KeyValuePair <string, string> > resourcePath)
        {
            var operation = HttpParsingHelper.BuildOperationMoniker(verb, resourcePath);

            // Do not generate asterisk for docs path
            if (resourcePath.Count > 1 && resourcePath[1].Key == "docs" && DocumentOperationNotMonikerActions.Contains(resourcePath[1].Value))
            {
                operation = operation.Remove(operation.Length - 1) + resourcePath[1].Value;
            }

            return(operation);
        }
Exemple #4
0
 public void ExtractQuryParametersTests()
 {
     Assert.IsNull(HttpParsingHelper.ExtractQuryParameters("a/bb/ccc/dddd"));
     Assert.IsNull(HttpParsingHelper.ExtractQuryParameters("a/bb/ccc/dddd?"));
     Assert.IsNull(HttpParsingHelper.ExtractQuryParameters("a/bb/ccc/dddd?#x=y"));
     AssertQueryParametersAreValid(HttpParsingHelper.ExtractQuryParameters("a/bb/ccc/dddd?x"), "x", null);
     AssertQueryParametersAreValid(HttpParsingHelper.ExtractQuryParameters("a/bb/ccc/dddd?x#y=z"), "x", null);
     AssertQueryParametersAreValid(HttpParsingHelper.ExtractQuryParameters("/a/bb/ccc/dddd?x=&w=z"), "x", string.Empty, "w", "z");
     AssertQueryParametersAreValid(HttpParsingHelper.ExtractQuryParameters("/a/bb/ccc/dddd?x=y&w=z"), "x", "y", "w", "z");
     AssertQueryParametersAreValid(HttpParsingHelper.ExtractQuryParameters("/a/bb/ccc/dddd?x=y&w=z#0=1"), "x", "y", "w", "z");
     AssertQueryParametersAreValid(HttpParsingHelper.ExtractQuryParameters("/a/bb/ccc/dddd/?x=y&w=z#0=1"), "x", "y", "w", "z");
 }
Exemple #5
0
        public void SplitTests()
        {
            var delimiters = new char[] { '/' };

            AssertAreDeepEqual(HttpParsingHelper.Split("a/bb/ccc/dddd", delimiters, 0, -1), "a", "bb", "ccc", "dddd");
            AssertAreDeepEqual(HttpParsingHelper.Split("/a/bb/ccc/dddd", delimiters, 0, -1), string.Empty, "a", "bb", "ccc", "dddd");
            AssertAreDeepEqual(HttpParsingHelper.Split("/a/bb/ccc/dddd", delimiters, 1, -1), "a", "bb", "ccc", "dddd");
            AssertAreDeepEqual(HttpParsingHelper.Split("/a/bb/ccc/dddd/", delimiters, 1, -1), "a", "bb", "ccc", "dddd", string.Empty);
            AssertAreDeepEqual(HttpParsingHelper.Split("/a/bb/ccc/dddd?ee", delimiters, 1, 14), "a", "bb", "ccc", "dddd");
            AssertAreDeepEqual(HttpParsingHelper.Split("/a/bb/ccc/dddd", delimiters, 3, 8), "bb", "cc");
            AssertAreDeepEqual(HttpParsingHelper.Split("/a//bb//ccc//dddd/", delimiters, 1, -1), "a", string.Empty, "bb", string.Empty, "ccc", string.Empty, "dddd", string.Empty);
        }
        /// <summary>
        /// Tries parsing given dependency telemetry item.
        /// </summary>
        /// <param name="httpDependency">Dependency item to parse. It is expected to be of HTTP type.</param>
        /// <returns><code>true</code> if successfully parsed dependency.</returns>
        internal static bool TryParse(ref DependencyTelemetry httpDependency)
        {
            string name = httpDependency.Name;
            string host = httpDependency.Target;
            string url  = httpDependency.Data;

            if (name == null || host == null || url == null)
            {
                return(false);
            }

            if (!HttpParsingHelper.EndsWithAny(host, DocumentDbHostSuffixes))
            {
                return(false);
            }

            ////
            //// DocumentDB REST API: https://docs.microsoft.com/en-us/rest/api/documentdb/
            ////

            string verb;
            string nameWithoutVerb;

            // try to parse out the verb
            HttpParsingHelper.ExtractVerb(name, out verb, out nameWithoutVerb, DocumentDbSupportedVerbs);

            List <KeyValuePair <string, string> > resourcePath = HttpParsingHelper.ParseResourcePath(nameWithoutVerb);

            // populate properties
            foreach (var resource in resourcePath)
            {
                if (resource.Value != null)
                {
                    string propertyName = GetPropertyNameForResource(resource.Key);
                    if (propertyName != null)
                    {
                        httpDependency.Properties[propertyName] = resource.Value;
                    }
                }
            }

            string operation     = HttpParsingHelper.BuildOperationMoniker(verb, resourcePath);
            string operationName = GetOperationName(httpDependency, operation);

            httpDependency.Type = RemoteDependencyConstants.AzureDocumentDb;
            httpDependency.Name = string.IsNullOrEmpty(operationName) ? httpDependency.Target : operationName;

            return(true);
        }
Exemple #7
0
        /// <summary>
        /// Tries parsing given dependency telemetry item.
        /// </summary>
        /// <param name="httpDependency">Dependency item to parse. It is expected to be of HTTP type.</param>
        /// <returns><code>true</code> if successfully parsed dependency.</returns>
        internal static bool TryParse(ref DependencyTelemetry httpDependency)
        {
            var name = httpDependency.Name;
            var host = httpDependency.Target;
            var url  = httpDependency.Data;

            if (name == null || host == null || url == null)
            {
                return(false);
            }

            if (!HttpParsingHelper.EndsWithAny(host, AzureSearchHostSuffixes))
            {
                return(false);
            }

            ////
            //// Azure Search REST API: https://docs.microsoft.com/en-us/rest/api/searchservice/
            ////

            HttpParsingHelper.ExtractVerb(name, out var verb, out var nameWithoutVerb, AzureSearchSupportedVerbs);

            var resourcePath = ParseResourcePath(nameWithoutVerb);

            // populate properties
            foreach (var resource in resourcePath)
            {
                if (resource.Value != null)
                {
                    var propertyName = GetPropertyNameForResource(resource.Key);
                    if (propertyName != null)
                    {
                        httpDependency.Properties[propertyName] = resource.Value;
                    }
                }
            }

            var operation     = BuildOperationMoniker(verb, resourcePath);
            var operationName = GetOperationName(operation);

            httpDependency.Type = RemoteDependencyConstants.AzureSearch;
            httpDependency.Name = string.IsNullOrEmpty(operationName) ? httpDependency.Target : operationName;

            return(true);
        }
        /// <summary>
        /// Tries parsing given dependency telemetry item.
        /// </summary>
        /// <param name="httpDependency">Dependency item to parse. It is expected to be of HTTP type.</param>
        /// <returns><code>true</code> if successfully parsed dependency.</returns>
        internal static bool TryParse(ref DependencyTelemetry httpDependency)
        {
            string name = httpDependency.Name;
            string host = httpDependency.Target;
            string url  = httpDependency.Data;

            if (name == null || host == null || url == null)
            {
                return(false);
            }

            if (!HttpParsingHelper.EndsWithAny(host, AzureTableHostSuffixes))
            {
                return(false);
            }

            ////
            //// Table Service REST API: https://msdn.microsoft.com/en-us/library/azure/dd179363.aspx
            ////

            string account = host.Substring(0, host.IndexOf('.'));

            string verb;
            string nameWithoutVerb;

            // try to parse out the verb
            HttpParsingHelper.ExtractVerb(name, out verb, out nameWithoutVerb, AzureTableSupportedVerbs);

            List <string> pathTokens = HttpParsingHelper.TokenizeRequestPath(nameWithoutVerb);
            string        tableName  = pathTokens.Count > 0 ? pathTokens[0] : string.Empty;
            int           idx        = tableName.IndexOf('(');

            if (idx >= 0)
            {
                tableName = tableName.Substring(0, idx);
            }

            httpDependency.Type = RemoteDependencyConstants.AzureTable;
            httpDependency.Name = string.IsNullOrEmpty(verb)
                                      ? account + '/' + tableName
                                      : verb + " " + account + '/' + tableName;

            return(true);
        }
Exemple #9
0
        /// <summary>
        /// Tries parsing given dependency telemetry item.
        /// </summary>
        /// <param name="httpDependency">Dependency item to parse. It is expected to be of HTTP type.</param>
        /// <returns><code>true</code> if successfully parsed dependency.</returns>
        internal static bool TryParse(ref DependencyTelemetry httpDependency)
        {
            string name = httpDependency.Name;
            string host = httpDependency.Target;
            string url  = httpDependency.Data;

            if (name == null || host == null || url == null)
            {
                return(false);
            }

            if (!HttpParsingHelper.EndsWithAny(host, AzureIotHubHostSuffixes))
            {
                return(false);
            }

            httpDependency.Type = RemoteDependencyConstants.AzureIotHub;

            return(true);
        }
Exemple #10
0
        internal static List <KeyValuePair <string, string> > ParseResourcePath(string requestPath)
        {
            if (!requestPath.Contains("("))
            {
                return(HttpParsingHelper.ParseResourcePath(requestPath));
            }

            // Parse OData v4 url format
            List <string> tokens = HttpParsingHelper.TokenizeRequestPath(requestPath);

            int pairCount = tokens.Count + 1;
            var results   = new List <KeyValuePair <string, string> >(pairCount);

            for (int i = 0; i < tokens.Count; i++)
            {
                var current = tokens[i];

                var valueStart = current.IndexOf('(');
                var valueEnd   = current.IndexOf(')');

                if (valueStart == -1)
                {
                    var next = tokens.Count < (i + 1) ? tokens[++i] : null;
                    results.Add(new KeyValuePair <string, string>(current, next));
                }
                else
                {
                    var key   = current.Substring(0, valueStart);
                    var value = current.Substring(valueStart + 2, valueEnd - valueStart - 3);

                    results.Add(new KeyValuePair <string, string>(key, value));
                }
            }

            return(results);
        }
        private void DocumentDbHttpParserConvertsValidDependencies(
            string operation,
            string verb,
            string url,
            Dictionary <string, string> properties,
            string resultCode)
        {
            Uri parsedUrl = new Uri(url);

            // Parse with verb
            var d = new DependencyTelemetry(
                dependencyTypeName: RemoteDependencyConstants.HTTP,
                target: parsedUrl.Host,
                dependencyName: verb + " " + parsedUrl.AbsolutePath,
                data: parsedUrl.OriginalString)
            {
                ResultCode = resultCode ?? "200"
            };

            bool success = DocumentDbHttpParser.TryParse(ref d);

            Assert.IsTrue(success, operation);
            Assert.AreEqual(RemoteDependencyConstants.AzureDocumentDb, d.Type, operation);
            Assert.AreEqual(parsedUrl.Host, d.Target, operation);
            Assert.AreEqual(operation, d.Name, operation);

            if (properties != null)
            {
                foreach (var property in properties)
                {
                    string value = null;
                    Assert.IsTrue(d.Properties.TryGetValue(property.Key, out value), operation);
                    Assert.AreEqual(property.Value, value, operation);
                }
            }

            // Parse without verb
            d = new DependencyTelemetry(
                dependencyTypeName: RemoteDependencyConstants.HTTP,
                target: parsedUrl.Host,
                dependencyName: parsedUrl.AbsolutePath,
                data: parsedUrl.OriginalString)
            {
                ResultCode = resultCode ?? "200"
            };

            success = DocumentDbHttpParser.TryParse(ref d);

            Assert.IsTrue(success, operation);
            Assert.AreEqual(RemoteDependencyConstants.AzureDocumentDb, d.Type, operation);
            Assert.AreEqual(parsedUrl.Host, d.Target, operation);
            string moniker = HttpParsingHelper.BuildOperationMoniker(null, HttpParsingHelper.ParseResourcePath(parsedUrl.AbsolutePath));

            Assert.AreEqual(moniker, d.Name, operation);

            if (properties != null)
            {
                foreach (var property in properties)
                {
                    string value = null;
                    Assert.IsTrue(d.Properties.TryGetValue(property.Key, out value), operation);
                    Assert.AreEqual(property.Value, value, operation);
                }
            }
        }
Exemple #12
0
        /// <summary>
        /// Tries parsing given dependency telemetry item.
        /// </summary>
        /// <param name="httpDependency">Dependency item to parse. It is expected to be of HTTP type.</param>
        /// <returns><code>true</code> if successfully parsed dependency.</returns>
        internal static bool TryParse(ref DependencyTelemetry httpDependency)
        {
            string name = httpDependency.Name;
            string host = httpDependency.Target;
            string url  = httpDependency.Data;

            if (name == null || host == null || url == null)
            {
                return(false);
            }

            if (!HttpParsingHelper.EndsWithAny(host, AzureBlobHostSuffixes))
            {
                return(false);
            }

            ////
            //// Blob Service REST API: https://msdn.microsoft.com/en-us/library/azure/dd135733.aspx
            ////

            string account = host.Substring(0, host.IndexOf('.'));

            string verb;
            string nameWithoutVerb;

            // try to parse out the verb
            HttpParsingHelper.ExtractVerb(name, out verb, out nameWithoutVerb, AzureBlobSupportedVerbs);

            List <string> pathTokens = HttpParsingHelper.TokenizeRequestPath(nameWithoutVerb);

            string container = null;
            string blob      = null;

            if (pathTokens.Count == 1)
            {
                container = pathTokens[0];
            }
            else if (pathTokens.Count > 1)
            {
                Dictionary <string, string> queryParameters = HttpParsingHelper.ExtractQuryParameters(url);
                string resType;
                if (queryParameters == null || !queryParameters.TryGetValue("restype", out resType) ||
                    !string.Equals(resType, "container", StringComparison.OrdinalIgnoreCase))
                {
                    // if restype != container then the last path entry is blob name
                    blob = pathTokens[pathTokens.Count - 1];
                    httpDependency.Properties["Blob"] = blob;

                    pathTokens.RemoveAt(pathTokens.Count - 1);
                }

                container = string.Join("/", pathTokens);
            }

            if (container != null)
            {
                httpDependency.Properties["Container"] = container;
            }

            // This is very naive overwriting of Azure Blob dependency that is compatible with the today's implementation
            //
            // Possible improvements:
            //
            // 1. Use specific name for specific operations. Like "Lease Blob" for "?comp=lease" query parameter
            // 2. Use account name as a target instead of "account.blob.core.windows.net"
            httpDependency.Type = RemoteDependencyConstants.AzureBlob;
            httpDependency.Name = string.IsNullOrEmpty(verb) ? account : verb + " " + account;

            return(true);
        }
Exemple #13
0
        private static void ValidateBuildOperationMoniker(string verb, string url, string expectedMoniker)
        {
            var resourcePath = HttpParsingHelper.ParseResourcePath(url);

            Assert.AreEqual(expectedMoniker, HttpParsingHelper.BuildOperationMoniker(verb, resourcePath));
        }