{"id":13478247,"url":"https://github.com/ibraheemdev/matchit","last_synced_at":"2026-04-08T06:01:29.511Z","repository":{"id":38017420,"uuid":"323396731","full_name":"ibraheemdev/matchit","owner":"ibraheemdev","description":"A high performance, zero-copy URL router.","archived":false,"fork":false,"pushed_at":"2025-12-30T22:28:59.000Z","size":402,"stargazers_count":506,"open_issues_count":10,"forks_count":45,"subscribers_count":5,"default_branch":"master","last_synced_at":"2026-01-03T21:38:50.619Z","etag":null,"topics":["prefix-tree","radix-tree","router","url"],"latest_commit_sha":null,"homepage":"https://docs.rs/matchit","language":"Rust","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/ibraheemdev.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2020-12-21T16:55:26.000Z","updated_at":"2026-01-03T05:23:40.000Z","dependencies_parsed_at":"2024-02-03T19:29:40.543Z","dependency_job_id":"d8621112-d61e-4179-ac76-ca826f614bc1","html_url":"https://github.com/ibraheemdev/matchit","commit_stats":{"total_commits":260,"total_committers":10,"mean_commits":26.0,"dds":"0.32307692307692304","last_synced_commit":"9ae70361ab66b3cbfa7380c6e979304ec9a26c39"},"previous_names":[],"tags_count":27,"template":false,"template_full_name":null,"purl":"pkg:github/ibraheemdev/matchit","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ibraheemdev%2Fmatchit","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ibraheemdev%2Fmatchit/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ibraheemdev%2Fmatchit/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ibraheemdev%2Fmatchit/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/ibraheemdev","download_url":"https://codeload.github.com/ibraheemdev/matchit/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ibraheemdev%2Fmatchit/sbom","scorecard":{"id":479427,"data":{"date":"2025-08-11","repo":{"name":"github.com/ibraheemdev/matchit","commit":"83da71717fc57a0b0486893ec9cb580f4be90f25"},"scorecard":{"version":"v5.2.1-40-gf6ed084d","commit":"f6ed084d17c9236477efd66e5b258b9d4cc7b389"},"score":5.8,"checks":[{"name":"Binary-Artifacts","score":10,"reason":"no binaries found in the repo","details":null,"documentation":{"short":"Determines if the project has generated executable (binary) artifacts in the source repository.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#binary-artifacts"}},{"name":"Dangerous-Workflow","score":10,"reason":"no dangerous workflow patterns detected","details":null,"documentation":{"short":"Determines if the project's GitHub Action workflows avoid dangerous patterns.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#dangerous-workflow"}},{"name":"Code-Review","score":3,"reason":"Found 11/29 approved changesets -- score normalized to 3","details":null,"documentation":{"short":"Determines if the project requires human code review before pull requests (aka merge requests) are merged.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#code-review"}},{"name":"Packaging","score":-1,"reason":"packaging workflow not detected","details":["Warn: no GitHub/GitLab publishing workflow detected."],"documentation":{"short":"Determines if the project is published as a package that others can easily download, install, easily update, and uninstall.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#packaging"}},{"name":"Maintained","score":6,"reason":"5 commit(s) and 3 issue activity found in the last 90 days -- score normalized to 6","details":null,"documentation":{"short":"Determines if the project is \"actively maintained\".","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#maintained"}},{"name":"Token-Permissions","score":10,"reason":"GitHub workflow tokens follow principle of least privilege","details":["Info: jobLevel 'contents' permission set to 'read': .github/workflows/check.yml:41","Warn: jobLevel 'checks' permission set to 'write': .github/workflows/check.yml:42","Info: topLevel 'contents' permission set to 'read': .github/workflows/check.yml:9","Info: topLevel 'contents' permission set to 'read': .github/workflows/safety.yml:7","Info: topLevel 'contents' permission set to 'read': .github/workflows/test.yml:8"],"documentation":{"short":"Determines if the project's workflows follow the principle of least privilege.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#token-permissions"}},{"name":"Pinned-Dependencies","score":0,"reason":"dependency not pinned by hash detected -- score normalized to 0","details":["Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/check.yml:28: update your workflow using https://app.stepsecurity.io/secureworkflow/ibraheemdev/matchit/check.yml/master?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/check.yml:32: update your workflow using https://app.stepsecurity.io/secureworkflow/ibraheemdev/matchit/check.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/check.yml:49: update your workflow using https://app.stepsecurity.io/secureworkflow/ibraheemdev/matchit/check.yml/master?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/check.yml:53: update your workflow using https://app.stepsecurity.io/secureworkflow/ibraheemdev/matchit/check.yml/master?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/check.yml:58: update your workflow using https://app.stepsecurity.io/secureworkflow/ibraheemdev/matchit/check.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/check.yml:67: update your workflow using https://app.stepsecurity.io/secureworkflow/ibraheemdev/matchit/check.yml/master?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/check.yml:71: update your workflow using https://app.stepsecurity.io/secureworkflow/ibraheemdev/matchit/check.yml/master?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/check.yml:75: update your workflow using https://app.stepsecurity.io/secureworkflow/ibraheemdev/matchit/check.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/check.yml:83: update your workflow using https://app.stepsecurity.io/secureworkflow/ibraheemdev/matchit/check.yml/master?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/check.yml:87: update your workflow using https://app.stepsecurity.io/secureworkflow/ibraheemdev/matchit/check.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/check.yml:98: update your workflow using https://app.stepsecurity.io/secureworkflow/ibraheemdev/matchit/check.yml/master?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/check.yml:102: update your workflow using https://app.stepsecurity.io/secureworkflow/ibraheemdev/matchit/check.yml/master?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/check.yml:104: update your workflow using https://app.stepsecurity.io/secureworkflow/ibraheemdev/matchit/check.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/check.yml:119: update your workflow using https://app.stepsecurity.io/secureworkflow/ibraheemdev/matchit/check.yml/master?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/check.yml:123: update your workflow using https://app.stepsecurity.io/secureworkflow/ibraheemdev/matchit/check.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/safety.yml:21: update your workflow using https://app.stepsecurity.io/secureworkflow/ibraheemdev/matchit/safety.yml/master?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/safety.yml:25: update your workflow using https://app.stepsecurity.io/secureworkflow/ibraheemdev/matchit/safety.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/safety.yml:58: update your workflow using https://app.stepsecurity.io/secureworkflow/ibraheemdev/matchit/safety.yml/master?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/safety.yml:64: update your workflow using https://app.stepsecurity.io/secureworkflow/ibraheemdev/matchit/safety.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/test.yml:28: update your workflow using https://app.stepsecurity.io/secureworkflow/ibraheemdev/matchit/test.yml/master?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/test.yml:32: update your workflow using https://app.stepsecurity.io/secureworkflow/ibraheemdev/matchit/test.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/test.yml:55: update your workflow using https://app.stepsecurity.io/secureworkflow/ibraheemdev/matchit/test.yml/master?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/test.yml:59: update your workflow using https://app.stepsecurity.io/secureworkflow/ibraheemdev/matchit/test.yml/master?enable=pin","Info:   0 out of  10 GitHub-owned GitHubAction dependencies pinned","Info:   0 out of  13 third-party GitHubAction dependencies pinned"],"documentation":{"short":"Determines if the project has declared and pinned the dependencies of its build process.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#pinned-dependencies"}},{"name":"CII-Best-Practices","score":0,"reason":"no effort to earn an OpenSSF best practices badge detected","details":null,"documentation":{"short":"Determines if the project has an OpenSSF (formerly CII) Best Practices Badge.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#cii-best-practices"}},{"name":"Security-Policy","score":0,"reason":"security policy file not detected","details":["Warn: no security policy file detected","Warn: no security file to analyze","Warn: no security file to analyze","Warn: no security file to analyze"],"documentation":{"short":"Determines if the project has published a security policy.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#security-policy"}},{"name":"Vulnerabilities","score":10,"reason":"0 existing vulnerabilities detected","details":null,"documentation":{"short":"Determines if the project has open, known unfixed vulnerabilities.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#vulnerabilities"}},{"name":"Fuzzing","score":10,"reason":"project is fuzzed","details":["Info: RustCargoFuzzer integration found: fuzz/fuzz_targets/insert_and_match.rs:2"],"documentation":{"short":"Determines if the project uses fuzzing.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#fuzzing"}},{"name":"License","score":10,"reason":"license file detected","details":["Info: project has a license file: LICENSE:0","Info: FSF or OSI recognized license: MIT License: LICENSE:0"],"documentation":{"short":"Determines if the project has defined a license.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#license"}},{"name":"Signed-Releases","score":-1,"reason":"no releases found","details":null,"documentation":{"short":"Determines if the project cryptographically signs release artifacts.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#signed-releases"}},{"name":"Branch-Protection","score":0,"reason":"branch protection not enabled on development/release branches","details":["Warn: branch protection not enabled for branch 'master'"],"documentation":{"short":"Determines if the default and release branches are protected with GitHub's branch protection settings.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#branch-protection"}},{"name":"SAST","score":0,"reason":"SAST tool is not run on all commits -- score normalized to 0","details":["Warn: 0 commits out of 15 are checked with a SAST tool"],"documentation":{"short":"Determines if the project uses static code analysis.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#sast"}}]},"last_synced_at":"2025-08-19T16:13:16.256Z","repository_id":38017420,"created_at":"2025-08-19T16:13:16.256Z","updated_at":"2025-08-19T16:13:16.256Z"},"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":31542384,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-07T16:28:08.000Z","status":"online","status_checked_at":"2026-04-08T02:00:06.127Z","response_time":54,"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":["prefix-tree","radix-tree","router","url"],"created_at":"2024-07-31T16:01:54.549Z","updated_at":"2026-04-08T06:01:29.501Z","avatar_url":"https://github.com/ibraheemdev.png","language":"Rust","funding_links":[],"categories":["Rust"],"sub_categories":[],"readme":"# `matchit`\n\n[\u003cimg alt=\"crates.io\" src=\"https://img.shields.io/crates/v/matchit?style=for-the-badge\" height=\"25\"\u003e](https://crates.io/crates/matchit)\n[\u003cimg alt=\"github\" src=\"https://img.shields.io/badge/github-matchit-blue?style=for-the-badge\" height=\"25\"\u003e](https://github.com/ibraheemdev/matchit)\n[\u003cimg alt=\"docs.rs\" src=\"https://img.shields.io/docsrs/matchit?style=for-the-badge\" height=\"25\"\u003e](https://docs.rs/matchit)\n\nA high performance, zero-copy URL router.\n\n```rust\nuse matchit::Router;\n\nfn main() -\u003e Result\u003c(), Box\u003cdyn std::error::Error\u003e\u003e {\n    let mut router = Router::new();\n    router.insert(\"/home\", \"Welcome!\")?;\n    router.insert(\"/users/{id}\", \"A User\")?;\n\n    let matched = router.at(\"/users/978\")?;\n    assert_eq!(matched.params.get(\"id\"), Some(\"978\"));\n    assert_eq!(*matched.value, \"A User\");\n\n    Ok(())\n}\n```\n\n## Parameters\n\nThe router supports dynamic route segments. These can either be named or catch-all parameters.\n\nNamed parameters like `/{id}` match anything until the next static segment or the end of the path.\n\n```rust,ignore\nlet mut router = Router::new();\nrouter.insert(\"/users/{id}\", 42)?;\n\nlet matched = router.at(\"/users/1\")?;\nassert_eq!(matched.params.get(\"id\"), Some(\"1\"));\n\nlet matched = router.at(\"/users/23\")?;\nassert_eq!(matched.params.get(\"id\"), Some(\"23\"));\n\nassert!(router.at(\"/users\").is_err());\n```\n\nPrefixes and suffixes within a segment are also supported. However, there may only be a single named parameter per route segment.\n```rust,ignore\nlet mut router = Router::new();\nrouter.insert(\"/images/img-{id}.png\", true)?;\n\nlet matched = router.at(\"/images/img-1.png\")?;\nassert_eq!(matched.params.get(\"id\"), Some(\"1\"));\n\nassert!(router.at(\"/images/img-1.jpg\").is_err());\n```\n\nCatch-all parameters start with a `*` and match anything until the end of the path. They must always be at the *end* of the route.\n\n```rust,ignore\nlet mut router = Router::new();\nrouter.insert(\"/{*rest}\", true)?;\n\nlet matched = router.at(\"/foo.html\")?;\nassert_eq!(matched.params.get(\"rest\"), Some(\"foo.html\"));\n\nlet matched = router.at(\"/static/bar.css\")?;\nassert_eq!(matched.params.get(\"rest\"), Some(\"static/bar.css\"));\n\n// Note that this would lead to an empty parameter value.\nassert!(router.at(\"/\").is_err());\n```\n\nThe literal characters `{` and `}` may be included in a static route by escaping them with the same character.\nFor example, the `{` character is escaped with `{{`, and the `}` character is escaped with `}}`.\n\n```rust,ignore\nlet mut router = Router::new();\nrouter.insert(\"/{{hello}}\", true)?;\nrouter.insert(\"/{hello}\", true)?;\n\n// Match the static route.\nlet matched = router.at(\"/{hello}\")?;\nassert!(matched.params.is_empty());\n\n// Match the dynamic route.\nlet matched = router.at(\"/hello\")?;\nassert_eq!(matched.params.get(\"hello\"), Some(\"hello\"));\n```\n\n## Conflict Rules\n\nStatic and dynamic route segments are allowed to overlap. If they do, static segments will be given higher priority:\n\n```rust,ignore\nlet mut router = Router::new();\nrouter.insert(\"/\", \"Welcome!\").unwrap();       // Priority: 1\nrouter.insert(\"/about\", \"About Me\").unwrap();  // Priority: 1\nrouter.insert(\"/{*filepath}\", \"...\").unwrap();  // Priority: 2\n```\n\nFormally, a route consists of a list of segments separated by `/`, with an optional leading and trailing slash: `(/)\u003csegment_1\u003e/.../\u003csegment_n\u003e(/)`.\n\nGiven set of routes, their overlapping segments may include, in order of priority:\n\n- Any number of static segments (`/a`, `/b`, ...).\n- *One* of the following:\n  - Any number of route parameters with a suffix (`/{x}a`, `/{x}b`, ...), prioritizing the longest suffix.\n  - Any number of route parameters with a prefix (`/a{x}`, `/b{x}`, ...), prioritizing the longest prefix.\n  - A single route parameter with both a prefix and a suffix (`/a{x}b`).\n- *One* of the following;\n  - A single standalone parameter (`/{x}`).\n  - A single standalone catch-all parameter (`/{*rest}`). Note this only applies to the final route segment.\n\nAny other combination of route segments is considered ambiguous, and attempting to insert such a route will result in an error.\n\nThe one exception to the above set of rules is that catch-all parameters are always considered to conflict with suffixed route parameters, i.e. that `/{*rest}`\nand `/{x}suffix` are overlapping. This is due to an implementation detail of the routing tree that may be relaxed in the future.\n\n## How does it work?\n\nThe router takes advantage of the fact that URL routes generally follow a hierarchical structure.\nRoutes are stored them in a radix trie that makes heavy use of common prefixes.\n\n```text\nPriority   Path             Value\n9          \\                1\n3          ├s               None\n2          |├earch\\         2\n1          |└upport\\        3\n2          ├blog\\           4\n1          |    └{post}     None\n1          |          └\\    5\n2          ├about-us\\       6\n1          |        └team\\  7\n1          └contact\\        8\n```\n\nThis allows us to reduce the route search to a small number of branches. Child nodes on the same level of the tree are also\nprioritized by the number of children with registered values, increasing the chance of choosing the correct branch of the first try.\n\n## Benchmarks\n\nAs it turns out, this method of routing is extremely fast. Below are the benchmark results matching against 130 registered routes.\nYou can view the benchmark code [here](https://github.com/ibraheemdev/matchit/blob/master/benches/bench.rs). \n\n```text\nCompare Routers/matchit \ntime:   [2.4451 µs 2.4456 µs 2.4462 µs]\n\nCompare Routers/gonzales\ntime:   [4.2618 µs 4.2632 µs 4.2646 µs]\n\nCompare Routers/path-tree\ntime:   [4.8666 µs 4.8696 µs 4.8728 µs]\n\nCompare Routers/wayfind\ntime:   [4.9440 µs 4.9539 µs 4.9668 µs]\n\nCompare Routers/route-recognizer\ntime:   [49.203 µs 49.214 µs 49.226 µs]\n\nCompare Routers/routefinder\ntime:   [70.598 µs 70.636 µs 70.670 µs]\n\nCompare Routers/actix\ntime:   [453.91 µs 454.01 µs 454.11 µs]\n\nCompare Routers/regex\ntime:   [421.76 µs 421.82 µs 421.89 µs]\n```\n\n## Credits\n\nA lot of the code in this package was inspired by Julien Schmidt's [`httprouter`](https://github.com/julienschmidt/httprouter).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fibraheemdev%2Fmatchit","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fibraheemdev%2Fmatchit","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fibraheemdev%2Fmatchit/lists"}