{"id":13764087,"url":"https://github.com/husobee/vestigo","last_synced_at":"2025-07-22T23:07:00.567Z","repository":{"id":51566645,"uuid":"42908179","full_name":"husobee/vestigo","owner":"husobee","description":"Echo Inspired Stand Alone URL Router","archived":false,"fork":false,"pushed_at":"2020-10-08T16:23:52.000Z","size":160,"stargazers_count":267,"open_issues_count":13,"forks_count":31,"subscribers_count":15,"default_branch":"master","last_synced_at":"2025-05-10T17:41:36.059Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"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/husobee.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":"2015-09-22T03:08:03.000Z","updated_at":"2024-12-27T18:32:19.000Z","dependencies_parsed_at":"2022-09-26T17:41:23.196Z","dependency_job_id":null,"html_url":"https://github.com/husobee/vestigo","commit_stats":null,"previous_names":[],"tags_count":5,"template":false,"template_full_name":null,"purl":"pkg:github/husobee/vestigo","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/husobee%2Fvestigo","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/husobee%2Fvestigo/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/husobee%2Fvestigo/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/husobee%2Fvestigo/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/husobee","download_url":"https://codeload.github.com/husobee/vestigo/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/husobee%2Fvestigo/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":266586905,"owners_count":23952205,"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-07-22T02:00:09.085Z","response_time":66,"last_error":null,"robots_txt_status":null,"robots_txt_updated_at":null,"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":[],"created_at":"2024-08-03T15:01:13.402Z","updated_at":"2025-07-22T23:07:00.543Z","avatar_url":"https://github.com/husobee.png","language":"Go","funding_links":[],"categories":["Web框架","Web Frameworks","路由","Routers"],"sub_categories":["Routers","路由器","创建http中间件的代码库","Advanced Console UIs"],"readme":"# Vestigo - A Standalone Golang URL Router\n\n[![Join the chat at https://gitter.im/husobee/vestigo](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/husobee/vestigo?utm_source=badge\u0026utm_medium=badge\u0026utm_campaign=pr-badge\u0026utm_content=badge)\n[![Build Status](https://travis-ci.org/husobee/vestigo.svg)](https://travis-ci.org/husobee/vestigo)\n[![Coverage Status](https://coveralls.io/repos/husobee/vestigo/badge.svg?branch=master\u0026service=github)](https://coveralls.io/github/husobee/vestigo?branch=master)\n[![GoDoc](https://godoc.org/github.com/husobee/vestigo?status.svg)](https://godoc.org/github.com/husobee/vestigo)\n\n## Abstract\n\nMany fast Golang URL routers are often embedded inside frameworks.  Vestigo is a stand alone url router\nwhich has respectable performance that passes URL parameters to handlers by embedding them into the request's\nForm.\n\nThere is such an abundance of parts and pieces that can be fit together for go web services, it seems like a\nshame to have a very fast URL router require the use of one framework, and one context model.  This library\naims to give the world a fast, and featureful URL router that can stand on it's own, without being forced into\na particular web framework.\n\n## Design\n\n1. Radix Tree Based\n2. Attach URL Parameters into Request (PAT style) instead of context\n3. HTTP Compliance (TRACE, OPTIONS, HEAD)\n4. CORS Enabled (per resource access-controls)\n\n### TODOs for V1\n\n- [x] Router functioning with a resource concept attached to leaf nodes\n- [x] Use resources to drive responses to particular Methods (not found v not allowed)\n- [x] Implement Resource and Globally scoped CORS preflights\n- [x] Fix bug in router where handler.allowedMethods is getting populated where it shouldn't be\n- [x] Validate with Tests RFC 2616 Compliance (OPTIONS, etc)\n\n### TODOs for V2\n- [ ] Validators for URL params\n- [ ] Implement RFC 6570 URI Parameters\n\n## Performance\n\nInitial implementation on a fork of [standard http performance testing library][http-perf-test] shows the following:\n\n```\nBenchmarkVestigo_GithubAll         20000             75763 ns/op            9280 B/op        339 allocs/op\n```\n\nI should mention that the above performance is about 2x slower than the fastest URL router I have tested (Echo/Gin), and\nis slightly worse than HTTPRouter, but I am happy with this performance considering this implementation is the fastest\nimplementation that can handle standard http.HandlerFunc handlers, without forcing end users to use a particular context,\nor use a non-standard handler function, locking them into an implementation.\n\n## Examples\n\n```go\npackage main\n\nimport (\n\t\"log\"\n\t\"net/http\"\n\t\"time\"\n\n\t\"github.com/husobee/vestigo\"\n)\n\nfunc main() {\n\trouter := vestigo.NewRouter()\n\t// you can enable trace by setting this to true\n\tvestigo.AllowTrace = true\n\n\t// Setting up router global  CORS policy\n\t// These policy guidelines are overriddable at a per resource level shown below\n\trouter.SetGlobalCors(\u0026vestigo.CorsAccessControl{\n\t\tAllowOrigin:      []string{\"*\", \"test.com\"},\n\t\tAllowCredentials: true,\n\t\tExposeHeaders:    []string{\"X-Header\", \"X-Y-Header\"},\n\t\tMaxAge:           3600 * time.Second,\n\t\tAllowHeaders:     []string{\"X-Header\", \"X-Y-Header\"},\n\t})\n\n\t// setting two methods on the same resource\n\trouter.Get(\"/welcome\", GetWelcomeHandler)\n\trouter.Post(\"/welcome\", PostWelcomeHandler)\n\n\t// URL parameter \"name\"\n\trouter.Post(\"/welcome/:name\", PostWelcomeHandler)\n\n\t// Catch-All methods to allow easy migration from http.ServeMux\n\trouter.HandleFunc(\"/general\", GeneralHandler)\n\n\t// Below Applies Local CORS capabilities per Resource (both methods covered)\n\t// by default this will merge the \"GlobalCors\" settings with the resource\n\t// cors settings.  Without specifying the AllowMethods, the router will\n\t// accept any Request-Methods that have valid handlers associated\n\trouter.SetCors(\"/welcome\", \u0026vestigo.CorsAccessControl{\n\t\tAllowMethods: []string{\"GET\"},                    // only allow cors for this resource on GET calls\n\t\tAllowHeaders: []string{\"X-Header\", \"X-Z-Header\"}, // Allow this one header for this resource\n\t})\n\n\tlog.Fatal(http.ListenAndServe(\":1234\", router))\n}\n\nfunc PostWelcomeHandler(w http.ResponseWriter, r *http.Request) {\n\tname := vestigo.Param(r, \"name\") // url params live in the request\n\tw.WriteHeader(200)\n\tw.Write([]byte(\"welcome \" + name + \"!\"))\n}\n\nfunc GetWelcomeHandler(w http.ResponseWriter, r *http.Request) {\n\tw.WriteHeader(200)\n\tw.Write([]byte(\"welcome!\"))\n}\n\nfunc GeneralHandler(w http.ResponseWriter, r *http.Request) {\n\tw.WriteHeader(200)\n\tw.Write([]byte(\"Gotta catch em all!\"))\n}\n```\n\n## Middleware\n\nRouter helper methods (Get, Post, ...) support optional middleware (vestigo provides only middleware type, it is up to\nthe user to create one).\n\n```go\nrouter.Get(\"/welcome\", GetWelcomeHandler, someMiddleware)\n\nsomeMiddleware := func(f http.HandlerFunc) http.HandlerFunc {\n\treturn func(w http.ResponseWriter, r *http.Request) {\n\t\t// before\n\t\tf(w, r)\n\t\t// after\n\t}\n}\n```\n\nTo break the chain (for example in case of authentication middleware, we don't want to continue execution), just do not\ncall passed handler function. Example:\n\n```go\nauth := func(f http.HandlerFunc) http.HandlerFunc {\n\treturn func(w http.ResponseWriter, r *http.Request) {\n\t\tif authSuccessful() {\n\t\t\tf(w, r)\n\t\t}\n\t}\n}\n```\n\n## App Performance with net/http/pprof\n\nIt is often very helpful to view profiling information from your web application.\nBelow is an example of hooking up net/http/pprof with vestigo serving the routes:\n\n```go\n// Load the routes.\nfunc Load(router *vestigo.Router) {\n\trouter.Get(\"/debug/pprof/\", Index)\n\trouter.Get(\"/debug/pprof/:pprof\", Profile)\n}\n\n// Index shows the profile index.\nfunc Index(w http.ResponseWriter, r *http.Request) {\n\tpprof.Index(w, r)\n}\n\n// Profile shows the individual profiles.\nfunc Profile(w http.ResponseWriter, r *http.Request) {\n\tswitch vestigo.Param(r, \"pprof\") {\n\tcase \"cmdline\":\n\t\tpprof.Cmdline(w, r)\n\tcase \"profile\":\n\t\tpprof.Profile(w, r)\n\tcase \"symbol\":\n\t\tpprof.Symbol(w, r)\n\tcase \"trace\":\n\t\tpprof.Trace(w, r)\n\tdefault:\n\t\tIndex(w, r)\n\t}\n}\n```\n\nNote on wildcards: if you want to get the actual path matched by the wildcard\nyou can perform `vestigo.Param(*http.Request, \"_name\")` to get the matched path, example below:\n\n```go\nrouter.Get(\"/*\", func(w http.ResponseWriter, r *http.Request) {\n\tfmt.Println(vestigo.Param(r, \"_name\"))\n})\n```\n\n## Licensing\n\n* Portions of the URL Router were taken from [Echo][echo-main] and are covered under their [License][echo-main-license].\n* Portions of the Tests were taken from [julienschmidt's go-http-routing-benchmark][http-perf-test] and are covered under\nthis [license][http-perf-test-license]\n* The rest of the implementation is covered under *The MIT License* covered under this [License][vestigo-main-license].\n\n# Contributing\n\nIf you wish to contribute, please fork this repository, submit an issue, or pull request with your suggestions.\n_Please use gofmt and golint before trying to contribute._\n\n\n[echo-main]: https://github.com/labstack/echo\n[echo-main-license]: https://github.com/labstack/echo/blob/master/LICENSE\n[vestigo-main-license]: https://github.com/husobee/vestigo/blob/master/LICENSE\n[http-perf-test]: https://github.com/julienschmidt/go-http-routing-benchmark\n[http-perf-test-license]: https://github.com/julienschmidt/go-http-routing-benchmark/blob/master/LICENSE\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fhusobee%2Fvestigo","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fhusobee%2Fvestigo","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fhusobee%2Fvestigo/lists"}