{"id":13619804,"url":"https://github.com/ucarion/urlpath","last_synced_at":"2025-04-10T05:11:29.352Z","repository":{"id":56772392,"uuid":"187935458","full_name":"ucarion/urlpath","owner":"ucarion","description":"A Golang library for matching REST-like URL path patterns","archived":false,"fork":false,"pushed_at":"2020-04-24T17:08:22.000Z","size":18,"stargazers_count":45,"open_issues_count":1,"forks_count":12,"subscribers_count":4,"default_branch":"master","last_synced_at":"2024-10-20T01:20:01.789Z","etag":null,"topics":["golang","path","rest","url"],"latest_commit_sha":null,"homepage":"","language":"Go","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/ucarion.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}},"created_at":"2019-05-22T00:49:47.000Z","updated_at":"2024-04-18T07:14:46.000Z","dependencies_parsed_at":"2022-08-16T02:30:40.630Z","dependency_job_id":null,"html_url":"https://github.com/ucarion/urlpath","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ucarion%2Furlpath","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ucarion%2Furlpath/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ucarion%2Furlpath/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ucarion%2Furlpath/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/ucarion","download_url":"https://codeload.github.com/ucarion/urlpath/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248161276,"owners_count":21057555,"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","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":["golang","path","rest","url"],"created_at":"2024-08-01T21:00:48.959Z","updated_at":"2025-04-10T05:11:29.324Z","avatar_url":"https://github.com/ucarion.png","language":"Go","readme":"# urlpath [![GoDoc Badge][badge]][godoc] [![CI Badge][ci-badge]][ci-url]\n\n`urlpath` is a Golang library for matching paths against a template, or\nconstructing paths using a template. It's meant for applications that take in\nREST-like URL paths, and need to validate and extract data from those paths.\n\n[badge]: https://godoc.org/github.com/ucarion/urlpath?status.svg\n[godoc]: https://godoc.org/github.com/ucarion/urlpath\n[ci-badge]: https://github.com/ucarion/urlpath/workflows/.github/workflows/test.yml/badge.svg\n[ci-url]: https://github.com/ucarion/urlpath/actions\n\nThis is easiest explained with an example:\n\n```go\nimport \"github.com/ucarion/urlpath\"\n\nvar getBookPath = urlpath.New(\"/shelves/:shelf/books/:book\")\n\nfunc main() {\n  inputPath := \"/shelves/foo/books/bar\"\n  match, ok := getBookPath.Match(inputPath)\n  if !ok {\n    // handle the input not being valid\n    return\n  }\n\n  // Output:\n  //\n  // foo\n  // bar\n  fmt.Println(match.Params[\"shelf\"])\n  fmt.Println(match.Params[\"book\"])\n}\n```\n\nOne slightly fancier feature is support for trailing segments, like if you have\na path that ends with a filename. For example, a GitHub-like API might need to\ndeal with paths like:\n\n```text\n/ucarion/urlpath/blob/master/src/foo/bar/baz.go\n```\n\nYou can do this with a path that ends with \"*\". This works like:\n\n```go\npath := urlpath.New(\"/:user/:repo/blob/:branch/*\")\n\nmatch, ok := path.Match(\"/ucarion/urlpath/blob/master/src/foo/bar/baz.go\")\nfmt.Println(match.Params[\"user\"])   // ucarion\nfmt.Println(match.Params[\"repo\"])   // urlpath\nfmt.Println(match.Params[\"branch\"]) // master\nfmt.Println(match.Trailing)         // src/foo/bar/baz.go\n```\n\nAdditionally, you can call `Build` to construct a path from a template:\n\n```go\npath := urlpath.New(\"/:user/:repo/blob/:branch/*\")\n\nres, ok := path.Build(urlpath.Match{\n  Params: map[string]string{\n    \"user\": \"ucarion\",\n    \"repo\": \"urlpath\",\n    \"branch\": \"master\",\n  },\n  Trailing: \"src/foo/bar/baz.go\",\n})\n\nfmt.Println(res) // /ucarion/urlpath/blob/master/src/foo/bar/baz.go\n```\n\n## How it works\n\n`urlpath` operates on the basis of \"segments\", which is basically the result of\nsplitting a path by slashes. When you call `urlpath.New`, each of the segments\nin the input is treated as either:\n\n* A parameterized segment, like `:user`. All segments starting with `:` are\n  considered parameterized. Any corresponding segment in the input (even the\n  empty string!) will be satisfactory, and will be sent to `Params` in the\n  outputted `Match`. For example, data corresponding to `:user` would go in\n  `Params[\"user\"]`.\n* An exact-match segment, like `users`. Only segments exactly equal to `users`\n  will be satisfactory.\n* A \"trailing\" segment, `*`. This is only treated specially when it's the last\n  segment -- otherwise, it's just a usual exact-match segment. Any leftover data\n  in the input, after all previous segments were satisfied, goes into `Trailing`\n  in the outputted `Match`.\n\n## Performance\n\nAlthough performance wasn't the top priority for this library, `urlpath` does\ntypically perform better than an equivalent regular expression. In other words,\nthis:\n\n```go\npath := urlpath.New(\"/test/:foo/bar/:baz\")\nmatches := path.Match(...)\n```\n\nWill usually perform better than this:\n\n```go\nr := regexp.MustCompile(\"/test/(?P\u003cfoo\u003e[^/]+)/bar/(?P\u003cbaz\u003e[^/]+)\")\nmatches := r.FindStringSubmatch(...)\n```\n\nThe results of `go test -benchmem -bench .`:\n\n```text\ngoos: darwin\ngoarch: amd64\npkg: github.com/ucarion/urlpath\nBenchmarkMatch/without_trailing_segments/urlpath-8 \t 1436247\t       819 ns/op\t     784 B/op\t      10 allocs/op\nBenchmarkMatch/without_trailing_segments/regex-8   \t  693924\t      1816 ns/op\t     338 B/op\t      10 allocs/op\nBenchmarkMatch/with_trailing_segments/urlpath-8    \t 1454750\t       818 ns/op\t     784 B/op\t      10 allocs/op\nBenchmarkMatch/with_trailing_segments/regex-8      \t  592644\t      2365 ns/op\t     225 B/op\t       8 allocs/op\n```\n\nDo your own benchmarking if performance matters a lot to you. See\n`BenchmarkMatch` in `urlpath_test.go` for the code that gives these results.\n","funding_links":[],"categories":["Go"],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fucarion%2Furlpath","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fucarion%2Furlpath","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fucarion%2Furlpath/lists"}