예제 #1
0
        public UriRegistration Match(Uri baseAddress, Uri uriToMatch)
        {
            if (uriToMatch == null)
            {
                return(null);
            }

            var tableMatches = _templates.Match(uriToMatch, baseAddress);

            if (tableMatches == null || tableMatches.Count == 0)
            {
                return(null);
            }


            var allResults = tableMatches
                             .Select(m =>
            {
                var descriptor = (UrlDescriptor)m.Data;
                return(new TemplatedUriMatch(
                           descriptor.Registration.ResourceModel,
                           descriptor.Registration.UriModel,
                           m));
            }).ToList();

            return(new UriRegistration(
                       allResults[0].ResourceModel,
                       allResults[0].UriModel)
            {
                Results = allResults
            });
        }
        public void FindPathTemplates(string url, string key)
        {
            var table = new UriTemplateTable();  // Shorter paths and literal path segments should be added to the table first.
            table.Add("root", new UriTemplate("/"));
            table.Add("foo", new UriTemplate("/foo/{bar}"));
            table.Add("kit", new UriTemplate("/baz/kit"));
            table.Add("baz", new UriTemplate("/baz/{bar}"));
            table.Add("blob", new UriTemplate("/baz/{bar}/blob"));
            table.Add("goo", new UriTemplate("/{goo}/{bar}/blob"));


            var result = table.Match(new Uri(url, UriKind.RelativeOrAbsolute));

            if (string.IsNullOrEmpty(key))
            {
                Assert.Null(result);
            }
            else
            {
                Assert.Equal(key, result.Key);
            }

            Assert.NotNull(table["goo"]);
            Assert.Null(table["goo1"]);
        }
예제 #3
0
        public void FindPathTemplates(string url, string key)
        {
            var table = new UriTemplateTable();  // Shorter paths and literal path segments should be added to the table first.

            table.Add("root", new UriTemplate("/"));
            table.Add("foo", new UriTemplate("/foo/{bar}"));
            table.Add("kit", new UriTemplate("/baz/kit"));
            table.Add("baz", new UriTemplate("/baz/{bar}"));
            table.Add("blob", new UriTemplate("/baz/{bar}/blob"));
            table.Add("goo", new UriTemplate("/{goo}/{bar}/blob"));


            var result = table.Match(new Uri(url, UriKind.RelativeOrAbsolute));

            if (string.IsNullOrEmpty(key))
            {
                Assert.Null(result);
            }
            else
            {
                Assert.Equal(key, result.Key);
            }

            Assert.NotNull(table["goo"]);
            Assert.Null(table["goo1"]);
        }
예제 #4
0
        /// <summary>
        /// 指定した <see cref="Uri"/> がテーマのリソースを指す URI かどうかをチェックします。
        /// </summary>
        /// <returns><paramref name="uri"/> がテーマのリソースを指す URI の場合は true、それ以外の場合は false。</returns>
        static bool CheckThemeResourceUri(Uri uri)
        {
            if (uri == null)
            {
                return(false);
            }
#if NETCOREAPP
            return(_templateTable.Match(uri)?.Key == "theme");
#else
#if false
            var result = _templateTable.Match(uri);
            return(result != null && result.Count == 1 && result.First().Data.ToString() == "theme");
#else
            return(_themeTemplate.Match(_templateBaseUri, uri) != null);
#endif
#endif
        }
예제 #5
0
        public void MatchTemplateWithDifferentOrderOfQueryStringParameters()
        {
            var table = new UriTemplateTable();   // More restrictive templates should have priority over less restrictive ones

            table.Add("fooxy3", new UriTemplate("/foo?x={x}&y={y}"));

            var result = table.Match(new Uri("/foo?y=a&x=b", UriKind.RelativeOrAbsolute), QueryStringParameterOrder.Any);

            Assert.Equal("fooxy3", result.Key);
        }
 public void out_of_two_templates_with_one_query_parameter_only_the_correct_one_is_used()
 {
     var table = new UriTemplateTable(new Uri("http://localhost"), new List<KeyValuePair<UriTemplate, object>>
     {
         new KeyValuePair<UriTemplate, object>(new UriTemplate("resource1?query={queryText}"), null),
         new KeyValuePair<UriTemplate, object>(new UriTemplate("resource1?query2={queryText}"), null)
     });
     Collection<UriTemplateMatch> match = table.Match(new Uri("http://localhost/resource1?query=testing a query"));
     match.Count.ShouldBe(1);
     match[0].QueryParameters["queryText"].ShouldBe("testing a query");
 }
        public void literal_takes_precedence_over_template()
        {
            var table = new UriTemplateTable(new Uri("http://localhost"),
                                             new List <KeyValuePair <UriTemplate, object> >
            {
                new KeyValuePair <UriTemplate, object>(new UriTemplate("resource1/{resourceId}"), null),
                new KeyValuePair <UriTemplate, object>(new UriTemplate("resource1/new"), null)
            });
            var match = table.Match("http://localhost/resource1/new".ToUri());

            match.Count().ShouldBe(2);
            match.First().Template.ToString().ShouldBe("/resource1/new");
        }
예제 #8
0
        static void Main(string[] args)
        {
            Snippets.Snippet2();
            // <Snippet0>
            // <Snippet1>
            // <Snippet3>
            Uri prefix = new Uri("http://localhost/");

            //Create a series of templates
            UriTemplate weatherByCity    = new UriTemplate("weather/{state}/{city}");
            UriTemplate weatherByCountry = new UriTemplate("weather/{country}/{village}");
            UriTemplate weatherByState   = new UriTemplate("weather/{state}");
            UriTemplate traffic          = new UriTemplate("traffic/*");
            UriTemplate wildcard         = new UriTemplate("*");

            //Create a template table
            UriTemplateTable table = new UriTemplateTable(prefix);

            //Add each template to the table with some associated data
            table.KeyValuePairs.Add(new KeyValuePair <UriTemplate, Object>(weatherByCity, "weatherByCity"));
            table.KeyValuePairs.Add(new KeyValuePair <UriTemplate, Object>(weatherByCountry, "weatherByCountry"));
            table.KeyValuePairs.Add(new KeyValuePair <UriTemplate, Object>(weatherByState, "weatherByState"));
            table.KeyValuePairs.Add(new KeyValuePair <UriTemplate, Object>(traffic, "traffic"));

            table.MakeReadOnly(true);
            // </Snippet3>
            // </Snippet1>
            Console.WriteLine("KeyValuePairs:");
            foreach (KeyValuePair <UriTemplate, Object> keyPair in table.KeyValuePairs)
            {
                Console.WriteLine($"{keyPair.Key}, {keyPair.Value}");
            }

            Console.WriteLine();

            //Call MatchSingle to retrieve some match results:
            ICollection <UriTemplateMatch> results = null;
            Uri weatherInSeattle = new Uri("http://localhost/weather/Washington/Seattle");

            results = table.Match(weatherInSeattle);
            if (results != null)
            {
                Console.WriteLine("Matching templates:");
                foreach (UriTemplateMatch match in results)
                {
                    Console.WriteLine(match.Template);
                }
            }
            // </Snippet0>
        }
        public void a_template_with_no_params_is_the_best_match_for_a_uri_with_no_params()
        {
            var table = new UriTemplateTable(new Uri("http://localhost"), new List <KeyValuePair <UriTemplate, object> >
            {
                new KeyValuePair <UriTemplate, object>(new UriTemplate("resource1?query={queryText}&query2={queryiestText}"),
                                                       null),
                new KeyValuePair <UriTemplate, object>(new UriTemplate("resource1"), null),
                new KeyValuePair <UriTemplate, object>(new UriTemplate("resource1?query={queryText}"), null)
            });
            Collection <UriTemplateMatch> match = table.Match(new Uri("http://localhost/resource1"));

            match.Count.ShouldBe(3);
            match[0].PathSegmentVariables.Count.ShouldBe(0);
            match[0].PathSegmentVariables.Count.ShouldBe(0);
        }
예제 #10
0
        public void FindTemplatesWithArrayQueryParameters()
        {
            var table = new UriTemplateTable();   // More restrictive templates should have priority over less restrictive ones

            table.Add("fooxy3", new UriTemplate("/foo?x={x}&y={y}"));
            table.Add("fooxy2", new UriTemplate("/foo?x={x}{&y}"));
            table.Add("fooxy4", new UriTemplate("/foo?x={x}{&z}"));
            table.Add("fooxy", new UriTemplate("/foo{?x,y}"));
            table.Add("foo", new UriTemplate("/foo"));


            var result = table.Match(new Uri("/foo?x=a,b,c,d", UriKind.RelativeOrAbsolute));

            Assert.Equal("fooxy2", result.Key);
        }
예제 #11
0
        public void out_of_two_templates_with_one_query_parameter_only_the_correct_one_is_listed_first()
        {
            var table = new UriTemplateTable(new Uri("http://localhost"), new List <KeyValuePair <UriTemplate, object> >
            {
                new KeyValuePair <UriTemplate, object>(new UriTemplate("resource1?query={queryText}"), null),
                new KeyValuePair <UriTemplate, object>(new UriTemplate("resource1?query2={queryText}"), null)
            });
            var match = table.Match(new Uri("http://localhost/resource1?query=testing a query"));

            match.Count.ShouldBe(2);

            match[0].QueryStringVariables.Count.ShouldBe(1);
            match[1].QueryStringVariables.Count.ShouldBe(0);

            match[0].QueryStringVariables["queryText"].ShouldBe("testing a query");
        }
예제 #12
0
        public void equidistant_matches_are_ordered_by_bound_params()
        {
            var table = new UriTemplateTable(new Uri("http://localhost"), new List <KeyValuePair <UriTemplate, object> >
            {
                new KeyValuePair <UriTemplate, object>(new UriTemplate("resource1/{resourceId}"), null),
                new KeyValuePair <UriTemplate, object>(
                    new UriTemplate("resource1/{resourceId}?query={queryText}&query2={queryiestText}"), null),
            });

            var match =
                table.Match(new Uri("http://localhost/resource1/123?query=ceci_nest_pas_un_value"));

            match.Count.ShouldBe(2);
            match.First().QueryStringVariables.Count.ShouldBe(1);
            match.First().PathSegmentVariables.Count.ShouldBe(1);
            match.First().QueryParameters.Count.ShouldBe(2);
        }
예제 #13
0
        public void a_template_with_one_param_is_the_best_match_for_a_uri_with_one_param()
        {
            var table = new UriTemplateTable(new Uri("http://localhost"), new List <KeyValuePair <UriTemplate, object> >
            {
                new KeyValuePair <UriTemplate, object>(new UriTemplate("resource1?query={queryText}&query2={queryiestText}"),
                                                       null),
                new KeyValuePair <UriTemplate, object>(new UriTemplate("resource1"), null),
                new KeyValuePair <UriTemplate, object>(new UriTemplate("resource1?query={quasiText}"), null)
            });
            var match =
                table.Match(new Uri("http://localhost/resource1?query=ceci_nest_pas_un_value"));

            match.Count.ShouldBe(3);
            match[0].QueryStringVariables.Count.ShouldBe(1);
            match[0].QueryParameters.Count.ShouldBe(1);
            match[0].QueryStringVariables["quasiText"].ShouldBe("ceci_nest_pas_un_value");
        }
예제 #14
0
        public void irrelevant_params_do_not_affect_the_ordering()
        {
            var table = new UriTemplateTable(new Uri("http://localhost"), new List <KeyValuePair <UriTemplate, object> >
            {
                new KeyValuePair <UriTemplate, object>(new UriTemplate("resource1?query={queryText}&query2={queryiestText}"),
                                                       null),
                new KeyValuePair <UriTemplate, object>(new UriTemplate("resource1?query={queryText}&query3={queryiestText}"),
                                                       null),
                new KeyValuePair <UriTemplate, object>(new UriTemplate("resource1"), null),
                new KeyValuePair <UriTemplate, object>(new UriTemplate("resource1?query={quasiText}"), null)
            });
            var match =
                table.Match(new Uri("http://localhost/resource1?query=ceci_nest_pas_un_value&irrelevant=value"));

            match.Count.ShouldBe(4);
            match[0].QueryStringVariables.Count.ShouldBe(1);
            match[0].QueryParameters.Count.ShouldBe(1);
            match[0].QueryStringVariables["quasiText"].ShouldBe("ceci_nest_pas_un_value");
        }
예제 #15
0
        public IHttpRouteData GetRouteData(string virtualPathRoot, System.Net.Http.HttpRequestMessage request)
        {
            var routeData = new HttpRouteData(this);

            var match = _UriTemplateTable.Match(new Uri(request.RequestUri.PathAndQuery, UriKind.Relative));


            if (match == null)
            {
                return(routeData);
            }

            routeData.Values.Add("controller", match.Key);
            foreach (var p in match.Parameters)
            {
                routeData.Values.Add(p.Key, p.Value);
            }
            return(routeData);
        }
        public void FindTemplatesInGamesApi(string url, string key)
        {
            var table = new UriTemplateTable();
            table.Add("games", new UriTemplate("/games"));
            table.Add("gamessetup", new UriTemplate("/games/{gametitle}/Setup/{gamesid}"));
            table.Add("resource", new UriTemplate("/games/{gametitle}/Resources/{resourcetype}/{resourceid}"));
            table.Add("chat", new UriTemplate("/games/{gametitle}/{gameid}/Chat/{chatid}"));
            table.Add("state", new UriTemplate("/games/{gametitle}/{gameid}/State/{stateid}"));


            var result = table.Match(new Uri(url, UriKind.RelativeOrAbsolute));

            if (string.IsNullOrEmpty(key))
            {
                Assert.Null(result);
            }
            else
            {
                Assert.Equal(key, result.Key);
            }
        }
예제 #17
0
        public void FindTemplatesInGamesApi(string url, string key)
        {
            var table = new UriTemplateTable();

            table.Add("games", new UriTemplate("/games"));
            table.Add("gamessetup", new UriTemplate("/games/{gametitle}/Setup/{gamesid}"));
            table.Add("resource", new UriTemplate("/games/{gametitle}/Resources/{resourcetype}/{resourceid}"));
            table.Add("chat", new UriTemplate("/games/{gametitle}/{gameid}/Chat/{chatid}"));
            table.Add("state", new UriTemplate("/games/{gametitle}/{gameid}/State/{stateid}"));


            var result = table.Match(new Uri(url, UriKind.RelativeOrAbsolute));

            if (string.IsNullOrEmpty(key))
            {
                Assert.Null(result);
            }
            else
            {
                Assert.Equal(key, result.Key);
            }
        }
예제 #18
0
        public void FindTemplatesWithQueryStrings(string url, string key)
        {
            var table = new UriTemplateTable();   // More restrictive templates should have priority over less restrictive ones

            table.Add("fooxy3", new UriTemplate("/foo?x={x}&y={y}"));
            table.Add("fooxy2", new UriTemplate("/foo?x={x}{&y}"));
            table.Add("fooxy4", new UriTemplate("/foo?x={x}{&z}"));
            table.Add("fooxy", new UriTemplate("/foo{?x,y}"));
            table.Add("foo", new UriTemplate("/foo"));


            var result = table.Match(new Uri(url, UriKind.RelativeOrAbsolute));

            if (string.IsNullOrEmpty(key))
            {
                Assert.Null(result);
            }
            else
            {
                Assert.Equal(key, result.Key);
            }
        }
예제 #19
0
        public static void Snippet9()
        {
            // <Snippet9>
            Uri prefix = new Uri("http://localhost/");

            //Create a series of templates
            UriTemplate weatherByCity    = new UriTemplate("weather/ state}/ city}");
            UriTemplate weatherByCountry = new UriTemplate("weather/ country}/ village}");
            UriTemplate weatherByState   = new UriTemplate("weather/ state}");
            UriTemplate traffic          = new UriTemplate("traffic/*");
            UriTemplate wildcard         = new UriTemplate("*");

            //Create a template table
            UriTemplateTable table = new UriTemplateTable(prefix);

            //Add each template to the table with some associated data
            table.KeyValuePairs.Add(new KeyValuePair <UriTemplate, Object>(weatherByCity, "weatherByCity"));
            table.KeyValuePairs.Add(new KeyValuePair <UriTemplate, Object>(weatherByCountry, "weatherByCountry"));
            table.KeyValuePairs.Add(new KeyValuePair <UriTemplate, Object>(weatherByState, "weatherByState"));
            table.KeyValuePairs.Add(new KeyValuePair <UriTemplate, Object>(traffic, "traffic"));

            table.MakeReadOnly(true);

            //Call Match to retrieve some match results:
            ICollection <UriTemplateMatch> results = null;
            Uri weatherInSeattle = new Uri("http://localhost/weather/Washington/Seattle");

            results = table.Match(weatherInSeattle);
            if (results != null)
            {
                Console.WriteLine("Matching templates:");
                foreach (UriTemplateMatch match in results)
                {
                    Console.WriteLine("    0}", match.Template);
                }
            }
            // </Snippet9>
        }
        /// <summary>
        /// Retrieves permissions scopes.
        /// </summary>
        /// <param name="scopeType">The type of scope to be retrieved for the target request url.</param>
        /// <param name="locale">The language code for the preferred localized file.</param>
        /// <param name="requestUrl">The target request url whose scopes are to be retrieved.</param>
        /// <param name="method">The target http verb of the request url whose scopes are to be retrieved.</param>
        /// <returns>A list of scopes for the target request url given a http verb and type of scope.</returns>
        public async Task <List <ScopeInformation> > GetScopesAsync(string scopeType  = "DelegatedWork",
                                                                    string locale     = DefaultLocale,
                                                                    string requestUrl = null,
                                                                    string method     = null)
        {
            try
            {
                /* Add multiple checks to ensure thread that
                 * populated scopes information successfully
                 * completed seeding.
                 */
                if (RefreshPermissionsTables() ||
                    _scopesListTable == null ||
                    !_scopesListTable.Any())
                {
                    /* Permissions tables are not localized, so no need to keep different localized cached copies.
                    *  Refresh tables only after the specified time duration has elapsed or no cached copy exists. */
                    lock (_permissionsLock)
                    {
                        /* Ensure permissions tables are seeded by only one executing thread,
                         * once per refresh cycle. */
                        if (!_permissionsRefreshed)
                        {
                            SeedPermissionsTables();
                        }
                    }
                }

                var scopesInformationDictionary = await GetOrCreatePermissionsDescriptionsAsync(locale);

                if (string.IsNullOrEmpty(requestUrl))  // fetch all permissions
                {
                    List <ScopeInformation> scopesListInfo = new List <ScopeInformation>();

                    if (scopeType.Contains(Delegated))
                    {
                        if (scopesInformationDictionary.ContainsKey(Delegated))
                        {
                            foreach (var scopesInfo in scopesInformationDictionary[Delegated])
                            {
                                scopesListInfo.Add(scopesInfo.Value);
                            }
                        }
                    }
                    else // Application scopes
                    {
                        if (scopesInformationDictionary.ContainsKey(Application))
                        {
                            foreach (var scopesInfo in scopesInformationDictionary[Application])
                            {
                                scopesListInfo.Add(scopesInfo.Value);
                            }
                        }
                    }

                    return(scopesListInfo);
                }
                else // fetch permissions for a given request url and method
                {
                    if (string.IsNullOrEmpty(method))
                    {
                        throw new ArgumentNullException(nameof(method), "The HTTP method value cannot be null or empty.");
                    }

                    requestUrl = Regex.Replace(requestUrl, @"\?.*", string.Empty);    // remove any query params
                    requestUrl = Regex.Replace(requestUrl, @"\(.*?\)", string.Empty); // remove any '(...)' resource modifiers

                    // Check if requestUrl is contained in our Url Template table
                    TemplateMatch resultMatch = _urlTemplateTable.Match(new Uri(requestUrl.ToLower(), UriKind.RelativeOrAbsolute));

                    if (resultMatch == null)
                    {
                        return(null);
                    }

                    JArray resultValue = new JArray();
                    resultValue = (JArray)_scopesListTable[int.Parse(resultMatch.Key)];

                    var scopes = resultValue.FirstOrDefault(x => x.Value <string>("HttpVerb") == method)?
                                 .SelectToken(scopeType)?
                                 .Select(s => (string)s)
                                 .ToArray();

                    if (scopes == null)
                    {
                        return(null);
                    }

                    List <ScopeInformation> scopesList = new List <ScopeInformation>();

                    foreach (string scopeName in scopes)
                    {
                        ScopeInformation scopeInfo = null;
                        if (scopeType.Contains(Delegated))
                        {
                            if (scopesInformationDictionary[Delegated].ContainsKey(scopeName))
                            {
                                scopeInfo = scopesInformationDictionary[Delegated][scopeName];
                            }
                        }
                        else // Application scopes
                        {
                            if (scopesInformationDictionary[Application].ContainsKey(scopeName))
                            {
                                scopeInfo = scopesInformationDictionary[Application][scopeName];
                            }
                        }

                        if (scopeInfo == null)
                        {
                            scopesList.Add(new ScopeInformation
                            {
                                ScopeName = scopeName
                            });
                        }
                        else
                        {
                            scopesList.Add(scopeInfo);
                        }
                    }

                    return(scopesList);
                }
            }
            catch (ArgumentNullException exception)
            {
                throw exception;
            }
            catch (ArgumentException)
            {
                return(null); // equivalent to no match for the given requestUrl
            }
        }
        /// <summary>
        /// Processes the HTTP request.
        /// </summary>
        /// <param name="request">The request.</param>
        /// <returns></returns>
        private async Task <HttpResponse> ProcessAsync(HttpRequest request)
        {
            HttpResponse response;

            try
            {
                var match = _uriTemplateTable
                            .Match(request.Uri)
                            .FirstOrDefault(m => ((IHttpProcessor)m.Data).Methods.Contains(request.Method));

                if (match != null)
                {
                    using (var cts = new CancellationTokenSource(_requestTimeout))
                    {
                        var cancellationToken = cts.Token;

                        var closeSession = !string.IsNullOrEmpty(request.Headers.Get(Constants.SESSION_HEADER)) &&
                                           request.Headers.Get(Constants.SESSION_HEADER)
                                           .Equals(Constants.CLOSE_HEADER_VALUE, StringComparison.OrdinalIgnoreCase);

                        if (request.User != null)
                        {
                            var transport = _httpTransportProvider.GetTransport(request.User, !closeSession);

                            Exception exception = null;
                            try
                            {
                                // Authenticate the request session
                                var session = await transport.GetSessionAsync(cancellationToken).ConfigureAwait(false);

                                if (session.State == SessionState.Established)
                                {
                                    var processor = (IHttpProcessor)match.Data;
                                    response =
                                        await
                                        processor.ProcessAsync(request, match, transport, cancellationToken)
                                        .ConfigureAwait(false);
                                }
                                else if (session.Reason != null)
                                {
                                    response = new HttpResponse(request.CorrelatorId, session.Reason.ToHttpStatusCode(),
                                                                session.Reason.Description);
                                }
                                else
                                {
                                    response = new HttpResponse(request.CorrelatorId, HttpStatusCode.ServiceUnavailable);
                                }

                                response.Headers.Add(Constants.SESSION_ID_HEADER, session.Id.ToString());
                            }
                            catch (Exception ex)
                            {
                                response  = null;
                                exception = ex;
                            }

                            if (closeSession)
                            {
                                await
                                transport.FinishAsync(_listenerCancellationTokenSource.Token).ConfigureAwait(false);
                            }
                            else if (response != null)
                            {
                                response.Headers.Add(Constants.SESSION_EXPIRATION_HEADER,
                                                     transport.Expiration.ToString("r"));
                            }

                            if (exception != null)
                            {
                                throw exception;
                            }
                        }
                        else
                        {
                            response = new HttpResponse(request.CorrelatorId, HttpStatusCode.Unauthorized);
                        }
                    }
                }
                else
                {
                    response = new HttpResponse(request.CorrelatorId, HttpStatusCode.NotFound);
                }
            }
            catch (LimeException ex)
            {
                response = new HttpResponse(request.CorrelatorId, ex.Reason.ToHttpStatusCode(), ex.Reason.Description);
            }
            catch (OperationCanceledException)
            {
                response = new HttpResponse(request.CorrelatorId, HttpStatusCode.RequestTimeout);
            }
            catch (Exception ex)
            {
                string body = null;

                if (_writeExceptionsToOutput)
                {
                    body = ex.ToString();
                }

                response = new HttpResponse(request.CorrelatorId, HttpStatusCode.InternalServerError, body: body);
            }

            return(response);
        }
        public void FindTemplatesWithArrayQueryParameters()
        {
            var table = new UriTemplateTable();   // More restrictive templates should have priority over less restrictuve ones
            table.Add("fooxy3", new UriTemplate("/foo?x={x}&y={y}"));
            table.Add("fooxy2", new UriTemplate("/foo?x={x}{&y}"));
            table.Add("fooxy4", new UriTemplate("/foo?x={x}{&z}"));
            table.Add("fooxy", new UriTemplate("/foo{?x,y}"));
            table.Add("foo", new UriTemplate("/foo"));


            var result = table.Match(new Uri("/foo?x=a,b,c,d", UriKind.RelativeOrAbsolute));

            Assert.Equal("fooxy2", result.Key);
            
        }
        /// <summary>
        /// Create predicate function based on passed query parameters
        /// </summary>
        /// <param name="operationIds">Comma delimited list of operationIds or * for all operations.</param>
        /// <param name="tags">Comma delimited list of tags or a single regex.</param>
        /// <param name="url">Url path to match with Operation Ids.</param>
        /// <param name="graphVersion">Version of Microsoft Graph.</param>
        /// <param name="forceRefresh">Don't read from in-memory cache.</param>
        /// <returns>A predicate</returns>
        public static async Task <Func <OpenApiOperation, bool> > CreatePredicate(string operationIds, string tags, string url,
                                                                                  string graphVersion, bool forceRefresh)
        {
            if (operationIds != null && tags != null)
            {
                return(null); // Cannot filter by operationIds and tags at the same time
            }
            if (url != null && (operationIds != null || tags != null))
            {
                return(null); // Cannot filter by url and either 0perationIds and tags at the same time
            }

            Func <OpenApiOperation, bool> predicate;

            if (operationIds != null)
            {
                if (operationIds == "*")
                {
                    predicate = (o) => true;  // All operations
                }
                else
                {
                    var operationIdsArray = operationIds.Split(',');
                    predicate = (o) => operationIdsArray.Contains(o.OperationId);
                }
            }
            else if (tags != null)
            {
                var tagsArray = tags.Split(',');
                if (tagsArray.Length == 1)
                {
                    var regex = new Regex(tagsArray[0]);

                    predicate = (o) => o.Tags.Any(t => regex.IsMatch(t.Name));
                }
                else
                {
                    predicate = (o) => o.Tags.Any(t => tagsArray.Contains(t.Name));
                }
            }
            else if (url != null)
            {
                /* Extract the respective Operation Id(s) that match the provided url path */

                if (!_openApiOperationsTable.Any() || forceRefresh)
                {
                    _uriTemplateTable       = new UriTemplateTable();
                    _openApiOperationsTable = new Dictionary <int, OpenApiOperation[]>();

                    await PopulateReferenceTablesAync(graphVersion, forceRefresh);
                }

                url = url.Replace('-', '_');

                TemplateMatch resultMatch = _uriTemplateTable.Match(new Uri(url.ToLower(), UriKind.RelativeOrAbsolute));

                if (resultMatch == null)
                {
                    return(null);
                }

                /* Fetch the corresponding Operations Id(s) for the matched url */

                OpenApiOperation[] openApiOps        = _openApiOperationsTable[int.Parse(resultMatch.Key)];
                string[]           operationIdsArray = openApiOps.Select(x => x.OperationId).ToArray();

                predicate = (o) => operationIdsArray.Contains(o.OperationId);
            }
            else
            {
                predicate = null;
            }

            return(predicate);
        }
        public void literal_takes_precedence_over_template()
        {
            var table = new UriTemplateTable(new Uri("http://localhost"),
                                             new List<KeyValuePair<UriTemplate, object>>
                                             {
                                                 new KeyValuePair<UriTemplate,object>(new UriTemplate("resource1/{resourceId}"), null),
                                                 new KeyValuePair<UriTemplate, object>(new UriTemplate("resource1/new"), null)
                                             });
            var match = table.Match("http://localhost/resource1/new".ToUri());

            match.ShouldHaveCountOf(2)
                    .First().Template.ToString().ShouldBe("/resource1/new");
        }
        public static long Run()
        {
            long      ran        = 0;
            const int Iterations = 1000000; // 100 * 1000 * 1000;

            var baseUri = new Uri("http://x");
            var table   = new UriTemplateTable(
                baseUri,
                new[] { "devices/{deviceId}/messages/events/{*subTopic}", "devices/{deviceId}/messages/log/{level=info}/{subject=n%2Fa}" }.Select(x => new KeyValuePair <UriTemplate, object>(new UriTemplate(x, false), x)));

            table.MakeReadOnly(true);
            Regex[] regexes = new[] { "^devices/(?<deviceId>[^/]*)/messages/events/(?<subTopic>.*)$", "^devices/(?<deviceId>[^/]*)/messages/log(/(?<level>[^/]*)(/(?<level>[^/]*))?)?$" }.Select(x => new Regex(x, RegexOptions.Compiled | RegexOptions.Singleline | RegexOptions.CultureInvariant)).ToArray();

            var values = new[] { "devices/WAUCB28D7XA451194/messages/events/some/other/segments", "devices/WAUCB28D7XA451194/messages/log/warning/oilPressureAlert" };

            CodeTimer.Time(true, "table", Iterations, () =>
            {
                foreach (string value in values)
                {
                    Collection <UriTemplateMatch> matches = table.Match(new Uri(baseUri, value));
                    if (matches.Count == 0)
                    {
                        continue;
                    }
                    if (matches.Count > 1)
                    {
                        //
                    }
                    UriTemplateMatch match = matches[0];
                    string deviceId        = match.BoundVariables["deviceId"];
                    if (deviceId[0] == 'W')
                    {
                        unchecked
                        {
                            ran++;
                        }
                    }
                }
            });

            CodeTimer.Time(true, "regex", Iterations, () =>
            {
                foreach (string value in values)
                {
                    foreach (Regex regex in regexes)
                    {
                        Match match = regex.Match(value);
                        if (!match.Success)
                        {
                            continue;
                        }
                        string deviceId = match.Groups["deviceId"].Value;
                        if (deviceId[0] == 'W')
                        {
                            unchecked
                            {
                                ran++;
                            }
                        }
                        break;
                    }
                }
            });

            return(ran);
        }
        public void FindTemplatesWithQueryStrings(string url, string key)
        {
            var table = new UriTemplateTable();   // More restrictive templates should have priority over less restrictuve ones
            table.Add("fooxy3", new UriTemplate("/foo?x={x}&y={y}"));
            table.Add("fooxy2", new UriTemplate("/foo?x={x}{&y}"));
            table.Add("fooxy4", new UriTemplate("/foo?x={x}{&z}"));
            table.Add("fooxy", new UriTemplate("/foo{?x,y}"));
            table.Add("foo", new UriTemplate("/foo"));
 

            var result = table.Match(new Uri(url, UriKind.RelativeOrAbsolute));

            if (string.IsNullOrEmpty(key))
            {
                Assert.Null(result);
            }
            else
            {
                Assert.Equal(key, result.Key);
            }
        }
        /// <summary>
        /// Retrieves the permission scopes for a given request url.
        /// </summary>
        /// <param name="requestUrl">The target request url whose scopes are to be retrieved.</param>
        /// <param name="method">The target http verb of the request url whose scopes are to be retrieved.</param>
        /// <param name="scopeType">The type of scope to be retrieved for the target request url.</param>
        /// <returns>A list of scopes for the target request url given a http verb and type of scope.</returns>
        public List <ScopeInformation> GetScopes(string requestUrl, string method = "GET", string scopeType = "DelegatedWork")
        {
            if (!_scopesListTable.Any())
            {
                throw new InvalidOperationException($"The permissions and scopes data sources are empty; " +
                                                    $"check the source file or check whether the file path is properly set. File path: {_permissionsFilePaths}");
            }
            if (string.IsNullOrEmpty(requestUrl))
            {
                throw new ArgumentNullException(nameof(requestUrl), "The request url cannot be null or empty.");
            }

            try
            {
                requestUrl = Regex.Replace(requestUrl, @"\?.*", string.Empty);    // remove any query params
                requestUrl = Regex.Replace(requestUrl, @"\(.*?\)", string.Empty); // remove any '(...)' resource modifiers

                // Check if requestUrl is contained in our Url Template table
                TemplateMatch resultMatch = _urlTemplateTable.Match(new Uri(requestUrl.ToLower(), UriKind.RelativeOrAbsolute));

                if (resultMatch == null)
                {
                    return(null);
                }

                JArray resultValue = (JArray)_scopesListTable[int.Parse(resultMatch.Key)];

                string[] scopes = resultValue.FirstOrDefault(x => x.Value <string>("HttpVerb") == method)?
                                  .SelectToken(scopeType)?
                                  .Select(s => (string)s)
                                  .ToArray();

                List <ScopeInformation> scopesList = null;

                if (scopes != null)
                {
                    scopesList = new List <ScopeInformation>();

                    foreach (string scopeName in scopes)
                    {
                        ScopeInformation scopeInfo = null;
                        if (scopeType.Contains("Delegated"))
                        {
                            if (_delegatedScopesInfoTable.ContainsKey(scopeName))
                            {
                                scopeInfo = _delegatedScopesInfoTable[scopeName];
                            }
                        }
                        else // Application scopes
                        {
                            if (_applicationScopesInfoTable.ContainsKey(scopeName))
                            {
                                scopeInfo = _applicationScopesInfoTable[scopeName];
                            }
                        }

                        if (scopeInfo == null)
                        {
                            scopesList.Add(new ScopeInformation
                            {
                                ScopeName = scopeName
                            });
                        }
                        else
                        {
                            scopesList.Add(scopeInfo);
                        }
                    }
                }

                return(scopesList ?? null);
            }
            catch (ArgumentException)
            {
                return(null); // equivalent to no match for the given requestUrl
            }
        }