{"id":13786717,"url":"https://github.com/golobby/router","last_synced_at":"2025-05-11T22:32:07.309Z","repository":{"id":43035129,"uuid":"454198173","full_name":"golobby/router","owner":"golobby","description":"A lightweight yet powerful HTTP router for the Go programming language","archived":false,"fork":false,"pushed_at":"2022-03-30T17:37:31.000Z","size":320,"stargazers_count":22,"open_issues_count":2,"forks_count":0,"subscribers_count":3,"default_branch":"master","last_synced_at":"2024-11-17T22:36:28.566Z","etag":null,"topics":["go","go-framework","golang","http","http-router","router"],"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/golobby.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":"2022-01-31T23:01:00.000Z","updated_at":"2024-11-11T11:21:01.000Z","dependencies_parsed_at":"2022-09-10T09:21:51.209Z","dependency_job_id":null,"html_url":"https://github.com/golobby/router","commit_stats":null,"previous_names":[],"tags_count":8,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/golobby%2Frouter","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/golobby%2Frouter/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/golobby%2Frouter/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/golobby%2Frouter/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/golobby","download_url":"https://codeload.github.com/golobby/router/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":253645414,"owners_count":21941315,"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":["go","go-framework","golang","http","http-router","router"],"created_at":"2024-08-03T19:01:30.558Z","updated_at":"2025-05-11T22:32:06.924Z","avatar_url":"https://github.com/golobby.png","language":"Go","funding_links":[],"categories":["Web Frameworks","Web框架"],"sub_categories":["Routers","路由器"],"readme":"[![Go Reference](https://pkg.go.dev/badge/github.com/golobby/router.svg)](https://pkg.go.dev/github.com/golobby/router)\n[![CI](https://github.com/golobby/router/actions/workflows/ci.yml/badge.svg)](https://github.com/golobby/router/actions/workflows/ci.yml)\n[![CodeQL](https://github.com/golobby/router/actions/workflows/codeql-analysis.yml/badge.svg)](https://github.com/golobby/router/actions/workflows/codeql-analysis.yml)\n[![Go Report Card](https://goreportcard.com/badge/github.com/golobby/router)](https://goreportcard.com/report/github.com/golobby/router)\n[![Coverage Status](https://coveralls.io/repos/github/golobby/router/badge.svg?r=2)](https://coveralls.io/github/golobby/router?branch=master)\n[![Mentioned in Awesome Go](https://awesome.re/mentioned-badge.svg)](https://github.com/avelino/awesome-go)  \n\n# GoLobby Router\nGoLobby Router is a lightweight yet powerful HTTP router for the Go programming language.\nIt's built on top of the Go HTTP package and uses radix tree to provide the following features:\n* Routing based on HTTP method and URI\n* Route parameters and parameter patterns\n* Route wildcards\n* Middleware\n* HTTP Responses (such as JSON, XML, Text, Empty, File, and Redirect)\n* Static file serving\n* No footprint!\n* Zero-dependency!\n\n## Documentation\n### Required Go Version\nIt requires Go `v1.11` or newer versions.\n\n### Installation\nTo install this package, run the following command in your project directory.\n\n```bash\ngo get github.com/golobby/router\n```\n\n### Quick Start\nThe following example demonstrates a simple example of using the router package.\n\n```go\npackage main\n\nimport (\n    \"github.com/golobby/router\"\n    \"log\"\n    \"net/http\"\n)\n\nfunc main() {\n    r := router.New()\n    \n    r.GET(\"/\", func(c router.Context) error {\n        // c.Request() is original http.Request\n        // c.Response() is original http.ResponseWriter\n        return c.Text(http.StatusOK, \"Hello from GoLobby Router!\")\n    })\n    \n    r.PUT(\"/products/:id\", func(c router.Context) error {\n        return c.Text(http.StatusOK, \"Update product with ID: \"+c.Parameter(\"id\"))\n    })\n    \n    log.Fatalln(r.Start(\":8000\"))\n}\n```\n\n### HTTP Methods\nYou can use the `Map()` method to declare routes.\nIt gets HTTP methods and paths (URIs).\nThere are also some methods available for the most used HTTP methods.\nThese methods are `GET`, `POST`, `PUT`, `PATCH`, `DELETE`, `HEAD`, and `OPTIONS`.\nThe `Any()` method defines routes that handles any HTTP method.\n\n```go\npackage main\n\nimport (\n    \"github.com/golobby/router\"\n    \"log\"\n    \"net/http\"\n)\n\nfunc Handler(c router.Context) error {\n    return c.Text(http.StatusOK, \"Hello from GoLobby Router!\")\n}\n\nfunc main() {\n    r := router.New()\n    \n    r.GET(\"/\", Handler)\n    r.POST(\"/\", Handler)\n    r.PUT(\"/\", Handler)\n    r.PATCH(\"/\", Handler)\n    r.DELETE(\"/\", Handler)\n    r.HEAD(\"/\", Handler)\n    r.OPTIONS(\"/\", Handler)\n    \n    r.Any(\"/page\", Handler)\n    \n    r.Map(\"GET\", \"/\", Handler)\n    r.Map(\"CUSTOM\", \"/\", Handler)\n        \n    log.Fatalln(r.Start(\":8000\"))\n}\n```\n\n### Route Parameters\nTo specify route parameters, prepend a colon like `:id`.\nIn default, parameters could be anything but you can determine a regex pattern using the `Define()` method. Of course, regex patterns slow down your application, and it is recommended not to use them if possible.\nTo catch and check route parameters in your handlers, you'll have the `Parameters()`, `Parameter()`, and `HasParameter()` methods.\n\n```go\npackage main\n\nimport (\n    \"github.com/golobby/router\"\n    \"log\"\n    \"net/http\"\n)\n\nfunc main() {\n    r := router.New()\n    \n    // \"id\" parameters must be numeric\n    r.Define(\"id\", \"[0-9]+\")\n   \n    // a route with one parameter\n    r.GET(\"/posts/:id\", func(c router.Context) error {\n        return c.Text(http.StatusOK, c.Parameter(\"id\"))\n    })\n    \n    // a route with multiple parameters\n    r.GET(\"/posts/:id/comments/:cid\", func(c router.Context) error {\n        return c.JSON(http.StatusOK, c.Parameters())\n    })\n    \n    log.Fatalln(r.Start(\":8000\"))\n}\n```\n\n### Wildcard Routes\nWildcard routes match any URI with the specified prefix.\nThe following example shows how it works.\n\n```go\npackage main\n\nimport (\n    \"github.com/golobby/router\"\n    \"log\"\n    \"net/http\"\n)\n\nfunc main() {\n    r := router.New()\n    \n    // Other routes with the same pattern should come first.\n    r.GET(\"/pages/contact\", ContactHandler)\n    \n    r.GET(\"/pages/*\", PagesHandler)\n    // It matches:\n    // - /pages/\n    // - /pages/about\n    // - /pages/about/us\n    // - /pages/help\n    \n    log.Fatalln(r.Start(\":8000\"))\n}\n```\n\n### Serving Static Files\nThe `Files` method is provided to serve static files directly.\nThe example below demonstrate how to use it.\n\n```go\npackage main\n\nimport (\n    \"github.com/golobby/router\"\n    \"log\"\n    \"net/http\"\n)\n\nfunc main() {\n    r := router.New()\n    \n    // Other routes with the same pattern should come first.\n    r.GET(\"/api\", YourApiHandler)\n    \n    // The path (URI) must end with `*`.\n    r.Files(\"/*\", \"./files\")\n    // example.com/            ==\u003e ./files/index.html\n    // example.com/photo.jpg   ==\u003e ./files/photo.jpg\n    // example.com/notes/1.txt ==\u003e ./files/notes/1.txt\n    \n    log.Fatalln(r.Start(\":8000\"))\n}\n```\n\n### Named Routes\nNamed routes allow the convenient generation of URLs or redirects for specific routes.\nYou may specify a name for a route by chaining the `SetName()` method onto the route definition:\n\n```go\npackage main\n\nimport (\n    \"github.com/golobby/router\"\n    \"github.com/golobby/router/pkg/response\"\n    \"log\"\n    \"net/http\"\n)\n\nfunc main() {\n    r := router.New()\n    \n    r.GET(\"/\", func(c router.Context) error {\n        return c.Text(http.StatusOK, \"I am the home!\")\n    }).SetName(\"home\")\n    \n    r.GET(\"/posts/:id\", func(c router.Context) error {\n        return c.Text(http.StatusOK, \"I am a post!\")\n    }).SetName(\"post\")\n    \n    r.GET(\"/links\", func(c router.Context) error {\n        return c.JSON(http.StatusOK, response.M{\n            \"home\": c.URL(\"home\", nil), // \"/\"\n            \"post-1\": c.URL(\"post\", map[string]string{\"id\": \"1\"}), // \"/posts/1\"\n            \"post-2\": c.URL(\"post\", map[string]string{\"id\": \"2\"}), // \"/posts/2\"\n        })\n    })\n    \n    log.Fatalln(r.Start(\":8000\"))\n}\n```\n\n### Responses\nThe router comes with `Empty`, `Redirect`, `Text`, `HTML`, `JSON`, `PrettyJSON`, `XML`, `PrettyXML`, and `Bytes` responses out of the box.\nThe examples below demonstrate how to use built-in and custom responses.\n\n```go\npackage main\n\nimport (\n    \"github.com/golobby/router\"\n    \"github.com/golobby/router/pkg/response\"\n    \"log\"\n    \"net/http\"\n)\n\nfunc main() {\n    r := router.New()\n\n    r.GET(\"/empty\", func(c router.Context) error {\n        return c.Empty(204)\n    })\n\n    r.GET(\"/redirect\", func(c router.Context) error {\n        return c.Redirect(301, \"https://github.com/golobby/router\")\n    })\n\n    r.GET(\"/text\", func(c router.Context) error {\n        return c.Text(200, \"A text response\")\n    })\n\n    r.GET(\"/html\", func(c router.Context) error {\n        return c.HTML(200, \"\u003cp\u003eA HTML response\u003c/p\u003e\")\n    })\n\n    r.GET(\"/json\", func(c router.Context) error {\n        return c.JSON(200, User{\"id\": 13})\n    })\n\n    r.GET(\"/json\", func(c router.Context) error {\n        return c.JSON(200, response.M{\"message\": \"Using response.M helper\"})\n    })\n\n    r.GET(\"/json-pretty\", func(c router.Context) error {\n        return c.PrettyJSON(200, response.M{\"message\": \"A pretty JSON response!\"})\n    })\n\n    r.GET(\"/xml\", func(c router.Context) error {\n        return c.XML(200, User{\"id\": 13})\n    })\n\n    r.GET(\"/xml-pretty\", func(c router.Context) error {\n        return c.PrettyXML(200, User{\"id\": 13})\n    })\n\n    r.GET(\"/bytes\", func(c router.Context) error {\n        return c.Bytes(200, []bytes(\"Some bytes!\"))\n    })\n\n    r.GET(\"/file\", func(c router.Context) error {\n\treturn c.File(200, \"text/plain\", \"text.txt\")\n    })\n\n    r.GET(\"/custom\", func(c router.Context) error {\n        c.Response().Header().Set(\"Content-Type\", \"text/csv\")\n        return c.Bytes(200, []bytes(\"Column 1, Column 2, Column 3\"))\n    })\n\n    log.Fatalln(r.Start(\":8000\"))\n}\n```\n\n### Groups\nYou may put routes with similar attributes in groups.\nCurrently, prefix and middleware attributes are supported.\n\n#### Group by prefix\nThe example below demonstrates how to group routes with the same prefix.\n\n```go\npackage main\n\nimport (\n    \"github.com/golobby/router\"\n    \"log\"\n    \"net/http\"\n)\n\nfunc main() {\n    r := router.New()\n    \n    r.WithPrefix(\"/blog\", func() {\n        r.GET(\"/posts\", PostsHandler)    // \"/blog/posts\"\n        r.GET(\"/posts/:id\", PostHandler) // \"/blog/posts/:id\"\n        r.WithPrefix(\"/pages\", func() {\n            r.GET(\"/about\", AboutHandler)     // \"/blog/pages/about\"\n            r.GET(\"/contact\", ContactHandler) // \"/blog/pages/contact\"\n        })\n    })\n    \n    log.Fatalln(r.Start(\":8000\"))\n}\n```\n\n#### Group by middleware\nThe example below demonstrates how to group routes with the same middleware.\n\n```go\npackage main\n\nimport (\n    \"github.com/golobby/router\"\n    \"log\"\n    \"net/http\"\n)\n\nfunc AdminMiddleware(next router.Handler) router.Handler {\n    return func(c router.Context) error {\n        // Check user roles...\n        return next(c)\n    }\n}\n\nfunc main() {\n    r := router.New()\n    \n    r.WithMiddleware(AdminMiddleware, func() {\n        r.GET(\"/admin/users\", UsersHandler)\n        r.GET(\"/admin/products\", ProductsHandler)\n    })\n    \n    log.Fatalln(r.Start(\":8000\"))\n}\n```\n\n#### Group by middlewares\nThe example below demonstrates how to group routes with the same middlewares.\n\n```go\npackage main\n\nimport (\n    \"github.com/golobby/router\"\n    \"log\"\n    \"net/http\"\n)\n\nfunc main() {\n    r := router.New()\n    \n    middlewares := []router.Middleware{Middleware1, Middleware2, Middleware3}\n    r.WithMiddlewares(middlewares, func() {\n        r.GET(\"/posts\", PostsIndexHandler)\n    })\n    \n    log.Fatalln(r.Start(\":8000\"))\n}\n```\n\n#### Group by multiple attributes\nThe `group()` method helps you create a group of routes with the same prefix and middlewares.\n\n```go\npackage main\n\nimport (\n    \"github.com/golobby/router\"\n    \"log\"\n    \"net/http\"\n)\n\nfunc main() {\n    r := router.New()\n    \n    r.Group(\"/blog\", []router.Middleware{Middleware1, Middleware2}, func() {\n        r.GET(\"/posts\", PostsHandler)\n        r.GET(\"/posts/:id/comments\", CommentsHandler)\n    })\n    \n    log.Fatalln(r.Start(\":8000\"))\n}\n```\n\n### Basic Attributes\nYour application might need a base prefix or global middlewares.\nIn this case, you can set up these base attributes before defining routes.\n\n#### Base prefix\nThe following example shows how to set a base prefix for all routes.\n\n```go\npackage main\n\nimport (\n    \"github.com/golobby/router\"\n    \"log\"\n    \"net/http\"\n)\n\nfunc main() {\n    r := router.New()\n    \n    // Add a prefix to all routes\n    r.AddPrefix(\"/blog\")\n\n    r.GET(\"/posts\", PostsHandler)\n    r.GET(\"/posts/:id/comments\", CommentsHandler)\n    \n    log.Fatalln(r.Start(\":8000\"))\n}\n```\n\n#### Base middlewares\nThe following example shows how to set a base middlewares for all routes.\n\n```go\npackage main\n\nimport (\n    \"github.com/golobby/router\"\n    \"log\"\n    \"net/http\"\n)\n\nfunc main() {\n    r := router.New()\n    \n    // Add a single middleware\n    r.AddMiddleware(LoggerMiddleware)\n    \n    // Add multiple middlewares at once\n    r.AddMiddlewares([]router.Middleware{AuthMiddleware, ThrottleMiddleware})\n\n    r.GET(\"/users\", UsersHandler)\n    r.GET(\"/users/:id/files\", FilesHandler)\n    \n    log.Fatalln(r.Start(\":8000\"))\n}\n```\n\n### 404 Handler\nIn default, the router returns the following HTTP 404 response when a requested URI doesn't match any route.\n\n```json\n{\"message\": \"Not found.\"}\n```\n\nYou can set your custom handler like the following example.\n\n```go\npackage main\n\nimport (\n    \"github.com/golobby/router\"\n    \"log\"\n    \"net/http\"\n)\n\nfunc main() {\n    r := router.New()\n    \n    // Custom (HTML) Not Found Handler\n    r.SetNotFoundHandler(func(c router.Context) error {\n        return c.HTML(404, \"\u003cp\u003e404 Not Found\u003c/p\u003e\")\n    })\n\n    r.GET(\"/\", Handler)\n    \n    log.Fatalln(r.Start(\":8000\"))\n}\n```\n\n### Error Handling\nYour handlers might return an error while processing the HTTP request.\nThis error can be produced by your application logic or failure in the HTTP response.\nBy default, the router logs it using Golang's built-in logger into the standard output and returns the HTTP 500 response below.\n\n```json\n{\"message\": \"Internal error.\"}\n```\n\nIt's a good practice to add a global middleware to catch all these errors, log and handle them the way you need.\nThe example below demonstrates how to add middleware for handling errors.\n\n```go\npackage main\n\nimport (\n    \"github.com/golobby/router\"\n    \"log\"\n    \"net/http\"\n)\n\nfunc main() {\n    r := router.New()\n    \n    // Error Handler\n    r.AddMiddleware(func (next router.Handler) router.Handler {\n        return func(c router.Context) error {\n            if err := next(c); err != nil {\n                myLogger.log(err)\n                return c.HTML(500, \"\u003cp\u003eSomething went wrong\u003c/p\u003e\")\n            }\n            \n            // No error will raise to the router base handler\n            return nil\n        }\n    })\n\n    r.GET(\"/\", Handler)\n    \n    log.Fatalln(r.Start(\":8000\"))\n}\n```\n\n## License\nGoLobby Router is released under the [MIT License](http://opensource.org/licenses/mit-license.php).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgolobby%2Frouter","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fgolobby%2Frouter","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgolobby%2Frouter/lists"}