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"]); }
/// <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 }
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"); }
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); }
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); }
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"); }
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); }
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"); }
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"); }
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); } }
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); } }
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 } }