{"id":28385630,"url":"https://github.com/d-kistanov-parc/dotneturlpatternmatching","last_synced_at":"2026-03-17T17:37:11.661Z","repository":{"id":47231674,"uuid":"392363436","full_name":"d-kistanov-parc/DotNetUrlPatternMatching","owner":"d-kistanov-parc","description":"URL pattern matching","archived":false,"fork":false,"pushed_at":"2022-07-13T09:37:06.000Z","size":55,"stargazers_count":6,"open_issues_count":0,"forks_count":2,"subscribers_count":1,"default_branch":"develop","last_synced_at":"2025-10-09T06:16:43.188Z","etag":null,"topics":["compare","core","dotnet","match","matching","pattern","url","url-match","url-matching","url-pattern-matching","wildcard"],"latest_commit_sha":null,"homepage":"","language":"C#","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/d-kistanov-parc.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE.MD","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2021-08-03T15:28:37.000Z","updated_at":"2023-09-08T18:25:01.000Z","dependencies_parsed_at":"2022-09-10T14:01:53.595Z","dependency_job_id":null,"html_url":"https://github.com/d-kistanov-parc/DotNetUrlPatternMatching","commit_stats":null,"previous_names":[],"tags_count":1,"template":false,"template_full_name":null,"purl":"pkg:github/d-kistanov-parc/DotNetUrlPatternMatching","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/d-kistanov-parc%2FDotNetUrlPatternMatching","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/d-kistanov-parc%2FDotNetUrlPatternMatching/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/d-kistanov-parc%2FDotNetUrlPatternMatching/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/d-kistanov-parc%2FDotNetUrlPatternMatching/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/d-kistanov-parc","download_url":"https://codeload.github.com/d-kistanov-parc/DotNetUrlPatternMatching/tar.gz/refs/heads/develop","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/d-kistanov-parc%2FDotNetUrlPatternMatching/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":279000850,"owners_count":26082950,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-10-09T02:00:07.460Z","response_time":59,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["compare","core","dotnet","match","matching","pattern","url","url-match","url-matching","url-pattern-matching","wildcard"],"created_at":"2025-05-30T11:12:22.875Z","updated_at":"2025-10-09T06:16:43.604Z","avatar_url":"https://github.com/d-kistanov-parc.png","language":"C#","funding_links":[],"categories":[],"sub_categories":[],"readme":"# About DotNetUrlPatternMatching\n\nThe library allows you to match a URL to a pattern.\n\nHow it works \n- an url pattern is split into parts  \n- each non-empty part is matched with a similar one from the URL.\n\nYou can specify a Wildcard `*` or `~`  \nWhere `*` is any character set within the group (scheme, host, port, path, query, fragment)  \nWhere `~` any character set within a group segment (host, path)\n\nOnly supply parts of the URL you care about. Parts which are left out will match anything. E.g. if you don’t care about the host, then leave it out.\n\n\n- [Quick Start](#quick-start)\n    - [Installation](#installation)\n\t- [Simple Examples](#simple-examples)\n- [URL parts](#url-parts)\n    - [Scheme](#scheme)\n    - [Host](#host)\n    - [Port](#port)\n    - [Path](#path)\n    - [Query](#query)\n    - [Fragment](#fragment)\n    - [Basic Authentication](#basic-authentication)\n- [Behavior](#behavior)\n\t- [Сombining](#сombining)\n\t- [URL encoding \\ decoding](#url-encoding-\\-decoding)\n\t- [Config](#config)\n\t- [Exceptions](#exceptions)\n\n## Quick Start\n[![NuGet](https://img.shields.io/nuget/v/UrlPatternMatching.svg)](https://www.nuget.org/packages/UrlPatternMatching/)\n\n* supports all .NETStandard versions\n* no dependencies\n\n## Installation\n```\nPM\u003e Install-Package UrlPatternMatching\n```\n\n```\n.NET CLI\u003e dotnet add package UrlPatternMatching\n```\n\n## Simple Examples\n```cs\nusing UrlPatternMatching;\n\nstring pattern = \"http*://*.com/*/develop/README.md\";\nbool isMatch = \"https://github.com/DotNetUrlPatternMatching/edit/develop/README.md\".IsMatch(pattern);\n\n// Should be - true\n```\nTo achieve better performance, you can create an UrlPatternMatcher object and reuse it for multiple matches.\n\n```cs\nusing UrlPatternMatching;\n\nvar matcher = new UrlPatternMatcher(\"*:443/~/Dot~Matching\");\nbool isMatch = matcher.IsMatch(new Uri(\"https://github.com/org/DotNetUrlPatternMatching\"));  \n\n// Should be - true\n```\nThese objects are thread-safe and stateless, so you can create a global cache with them and reuse from different places.\n\n## URL parts\n```\nhttps://user:password@sub.domin.com:8081/info/main/base?withParam=one#navigate\n\\___/   \\___________/\\_____________/\\__/\\______________/\\___________/ \\______/\n  |           |             |        |         |              |           |\nscheme    base-auth        host     port      path          query      fragment\n```\n\nAll parts are optional. If a part is not specified, then an url can contain any value of a similar part.\n\n## Scheme\n\nPattern | Matched | Not matched\n--- |--- | ---\n```http://``` | `http://github.com/` | `ftp://github.com/`\n```https://github.com/``` | `https://github.com/` | `http://github.com/`\n```http*://github.com/``` | `https://github.com/` | `ftp://github.com/`\n\n## Host\n`~` any character in domain level  \n`*` any character in domain\n\nPattern | Matched | Not matched\n--- |--- | ---\n```github.com``` | `https://github.com/any` | `https://sub.github.com/`\n```*.microsoft.com``` | `https://some.any.microsoft.com` | `https://microsoft.com`\n```~soft.com``` | `https://microsoft.com` | `https://some.any.microsoft.com`\n```*ozon.com``` | `https://mozon.co` | `https://mozon.comic.com`\n```ya*.com``` | `https://ya.com` | `https://ya.co`\n```ya~.com``` | `https://yaz.com` | `https://www.yaz.com`\n```github*``` | `https://github.com` | `https://microsoft.com/github`\n```192.168.1.~``` | `https://192.168.1.1/anyPath/` | `https://192.168.11.11/`\n```192.*``` | `https://192.168.1.1/anyPath/` | `https://201.192.1.1`\n```[ffff:~:~:ffff:*]``` | `[ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff]:83` | `[aaa:bbbb:ffff:ffff:ffff:ffff:ffff:ffff]`\n\n## Port\nPattern | Matched | Not matched\n--- |--- | ---\n```http://github.com:80``` | `http://github.com` | `https://github.com`\n```http://github.com:2*``` | `http://github.com:23` | `http://github.com:65`\n```*:6564``` | `http://github.com:6564` | `http://github.com`\n\n## Path\n`~` any character in path  \n`*` any character in segment of path\n\nPattern | Matched | Not matched\n--- |--- | ---\n```/api/user/get``` | `https://github.com/api/user/get?w=1` | `https://github.com/api/user/get/45/`\n```/api/us~``` | `https://github.com/api/users` | `https://github.com/api/user/get`\n```/api/us*``` | `https://github.com/api/user/get` | `https://github.com/svc/api/user`\n```/api/user/~/get``` | `https://github.com/api/user/8787/get` | `https://github.com/api/user`\n```github.com/*api/users``` | `https://github.com/v3/api/users` | `https://github.com/v3/api/users/get`\n\n## Query\n\nTo match parameters in the template, you have to specify all of:\n* a parameter (or part of it)\n* the `=` sign\n* a value (or part of it)\n\nFor case sensitive comparison, you can set the parameters: `IsCaseSensitiveParamNames` or `IsCaseSensitiveParamValues` in config\n\nPattern | Matched | Not matched\n--- |--- | ---\n```?cc=33\u0026aa=1*``` | `http://github.com?aa=11\u0026bb=22\u0026cc=33` | `http://github.com`\n```?cc=33\u0026a*=11``` | `http://github.com?abs=11\u0026bb=22\u0026cc=33` | `http://github.com?cc=33\u0026bba=11`\n```http://github.com?text=%D0*``` | `http://github.com?text=%D0%BC%D0%BE%D0%BB` | `http://github.com?text=%BC%D0`\n\n## Fragment\nPattern | Matched | Not matched\n--- |--- | ---\n```http://github.com#main*``` | `http://github.com#maintable` | `https://github.com#table`\n```http://github.com#main*page*load``` | `http://github.com#mainAnyPageWillLoad` | `http://github.com#baseMainAnyPageWillLoad`\n```http://github.com#*load``` | `http://github.com#mainPageLoad` | `http://github.com#mainPageLoadThen`\n```#main``` | `http://github.com#main` | `https://main.com`\n\n## Basic Authentication\nYou can also check basic authentication, sent via URL (not all browsers are supported)\n\nPattern | Matched | Not matched\n--- |--- | ---\n```https://myUser:MyPassword@github.com``` | `https://myUser:MyPassword@github.com` | `https://github.com`\n```https://myUser:@github.com``` | `https://myUser:MyPassword@github.com` | `https://other:any@github.com`\n```https://mail*:@github.com``` | `https://mail1:pass@github.com` | `https://other:mail@github.com`\n\n## Behavior\nScheme and host are always case insensitive. \n\n## Сombining\nYou can combine different parts in the template and specify several wildcards\n\nExample: `*nuget*/~/~/?top=*` should be matched with `https://www.nuget.org/packages/UrlPatternMatching?top=100`\n\nAlso, you can skip any part and specify, for example, only a scheme and a fragment\n\nExample: `https://#page`\n\n## URL encoding \\ decoding\nYou can perform matching using URL encoded or URL decoded characters. \n\nPattern | will match\n--- |---\n```#молоко``` | `https://github.com#%D0%BC%D0%BE%D0%BB%D0%BE%D0%BA%D0%BE`\n```github.com#молоко``` | `https://github.com#молоко`\n```#%D0%BC%D0%BE%D0%BB%D0%BE%D0%BA%D0%BE``` | `https://github.com#молоко`\n```#%D0*``` | `https://github.com#D0%BC%D0%BE%D0%BB%D0%BE%D0%BA%D0%BE`\n\n## Config\nFor global settings use `Config.Default`. For local settings create a `new Config()`.\nIf a config is not specified, then the default config will be applied.\n\nConfig class contains case sensitivity settings for most parts (by default, match is case sensitive).\n```cs\npublic class Config\n{\n\tpublic bool IsCaseSensitivePathMatch { get; set; } = false;\n\tpublic bool IsCaseSensitiveFragmentMatch { get; set; } = false;\n\tpublic bool IsCaseSensitiveParamNames { get; set; } = false;\n\tpublic bool IsCaseSensitiveParamValues { get; set; } = false;\n\tpublic bool IsCaseSensitiveUserAndPassword { get; set; } = true;\n}\n```\n\nExample:\n\n```cs\nConfig.Default.IsCaseSensitiveParamValues = true; \n```\n\nExample:\n\n```cs\nvar config = new Config { IsCaseSensitivePathMatch = true };\nvar matcher = new UrlPatternMatcher(\"/atlassian.net/jira/your-work/\", config);\nbool result = matcher.IsMatch(\"https://any.atlassian.net/jira/Your-Work\");\n```\n\nA config can be passed as a parameter for `UrlExtensions.IsMatch`\nExample:\n```cs\nvar config = new Config();\nbool isMatch = \"https://github.com\".IsMatch(\"*.com\", config);\n```\n\n## Exceptions\n\nThe library may throw exceptions of type `InvalidPatternException` or `UriFormatException`\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fd-kistanov-parc%2Fdotneturlpatternmatching","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fd-kistanov-parc%2Fdotneturlpatternmatching","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fd-kistanov-parc%2Fdotneturlpatternmatching/lists"}