rux 简单且快速的 Go web 框架,支持中间件,兼容 http.Handler 接口。
NOTICE: v1.3.x 不完全兼容 v1.2.x 版本
- go get github.com/gookit/rux
- package main
-
- import (
- "github.com/gookit/rux"
- )
-
- func main() {
- r := rux.New()
-
- // ===== 静态资源
- // 单个文件
- r.StaticFile("/site.js", "testdata/site.js")
- // 静态资源目录
- r.StaticDir("/static", "testdata")
- // 静态资源目录,但是有后缀限制
- r.StaticFiles("/assets", "testdata", "css|js")
-
- // ===== 添加路由
-
- r.GET("/", func(c *rux.Context) {
- c.Text(200, "hello")
- })
- r.GET("/hello/{name}", func(c *rux.Context) {
- c.Text(200, "hello " + c.Param("name"))
- })
- r.POST("/post", func(c *rux.Context) {
- c.Text(200, "hello")
- })
- r.Group("/articles", func() {
- r.GET("", func(c *rux.Context) {
- c.Text(200, "view list")
- })
- r.POST("", func(c *rux.Context) {
- c.Text(200, "create ok")
- })
- r.GET(`/{id:\d+}`, func(c *rux.Context) {
- c.Text(200, "view detail, id: " + c.Param("id"))
- })
- })
-
- // 快速添加多个METHOD支持
- r.Add("/post[/{id}]", func(c *rux.Context) {
- if c.Param("id") == "" {
- // do create post
- c.Text(200, "created")
- return
- }
-
- id := c.Params.Int("id")
- // do update post
- c.Text(200, "updated " + fmt.Sprint(id))
- }, rux.POST, rux.PUT)
-
- // 启动服务并监听
- r.Listen(":8080")
- // 也可以
- // http.ListenAndServe(":8080", r)
- }
支持使用中间件:
调用优先级: 全局中间件 -> 路由组中间件 -> 路由中间件
使用示例:
- package main
-
- import (
- "fmt"
-
- "github.com/gookit/rux"
- )
-
- func main() {
- r := rux.New()
-
- // 添加一个全局中间件
- r.Use(func(c *rux.Context) {
- // do something ...
- })
-
- // 通过参数添加中间件
- route := r.GET("/middle", func(c *rux.Context) { // main handler
- c.WriteString("-O-")
- }, func(c *rux.Context) { // middle 1
- c.WriteString("a")
- c.Next() // Notice: call Next()
- c.WriteString("A")
- // if call Abort(), will abort at the end of this middleware run
- // c.Abort()
- })
-
- // 通过 Use() 添加中间件
- route.Use(func(c *rux.Context) { // middle 2
- c.WriteString("b")
- c.Next()
- c.WriteString("B")
- })
-
- // 启动server访问: /middle
- // 将会看到输出: ab-O-BA
- }
- +-----------------------------+
- | middle 1 |
- | +----------------------+ |
- | | middle 2 | |
- start | | +----------------+ | | end
- ------->| | | main handler | | |--->----
- | | |________________| | |
- | |______________________| |
- |_____________________________|
-
更多的使用请查看 middleware_test.go 中间件测试
rux 支持通用的 http.Handler 接口中间件
你可以使用 rux.WrapHTTPHandler() 转换 http.Handler 为 rux.HandlerFunc
- package main
-
- import (
- "net/http"
-
- "github.com/gookit/rux"
- // 这里我们使用 gorilla/handlers,它提供了一些通用的中间件
- "github.com/gorilla/handlers"
- )
-
- func main() {
- r := rux.New()
-
- // create a simple generic http.Handler
- h0 := http.HandlerFunc(func (w http.ResponseWriter, r *http.Request) {
- w.Header().Set("new-key", "val")
- })
-
- r.Use(rux.WrapHTTPHandler(h0), rux.WrapHTTPHandler(handlers.ProxyHeaders()))
-
- r.GET("/", func(c *rux.Context) {
- c.Text(200, "hello")
- })
- // add routes ...
-
- // Wrap our server with our gzip handler to gzip compress all responses.
- http.ListenAndServe(":8000", handlers.CompressHandler(r))
- }
rux 中你可以添加命名路由,根据名称可以从路由器里拿到对应的路由实例 rux.Route。
有几种方式添加命名路由:
- r := rux.New()
-
- // Method 1
- myRoute := rux.NewNamedRoute("name1", "/path4/some/{id}", emptyHandler, "GET")
- r.AddRoute(myRoute)
-
- // Method 2
- rux.AddNamed("name2", "/", func(c *rux.Context) {
- c.Text(200, "hello")
- })
-
- // Method 3
- r.GET("/hi", func(c *rux.Context) {
- c.Text(200, "hello")
- }).NamedTo("name3", r)
-
- // get route by name
- myRoute = r.GetRoute("name1")
- r.GET("/", func(c *rux.Context) {
- c.AbortThen().Redirect("/login", 302)
- })
-
- // Or
- r.GET("/", func(c *rux.Context) {
- c.Redirect("/login", 302)
- c.Abort()
- })
-
- r.GET("/", func(c *rux.Context) {
- c.Back()
- c.Abort()
- })
您可以通过以下方式快速操作Cookies FastSetCookie() DelCookie()
注意:您必须先设置或删除Cookies,然后再调用写入BODY内容的相关方法
- r.GET("/setcookie", func(c *rux.Context) {
- c.FastSetCookie("rux_cookie2", "test-value2", 3600)
- c.SetCookie("rux_cookie", "test-value1", 3600, "/", c.Req.URL.Host, false, true)
- c.WriteString("hello, in " + c.URL().Path)
- })
-
- r.GET("/delcookie", func(c *rux.Context) {
- val := ctx.Cookie("rux_cookie") // "test-value1"
- c.DelCookie("rux_cookie", "rux_cookie2")
- })
code is ref from julienschmidt/httprouter
- package main
-
- import (
- "log"
- "net/http"
-
- "github.com/gookit/rux"
- )
-
- type HostSwitch map[string]http.Handler
-
- // Implement the ServeHTTP method on our new type
- func (hs HostSwitch) ServeHTTP(w http.ResponseWriter, r *http.Request) {
- // Check if a http.Handler is registered for the given host.
- // If yes, use it to handle the request.
- if router := hs[r.Host]; router != nil {
- router.ServeHTTP(w, r)
- } else {
- // Handle host names for which no handler is registered
- http.Error(w, "Forbidden", 403) // Or Redirect?
- }
- }
-
- func main() {
- // Initialize a router as usual
- router := rux.New()
- router.GET("/", Index)
- router.GET("/hello/{name}", func(c *rux.Context) {})
-
- // Make a new HostSwitch and insert the router (our http handler)
- // for example.com and port 12345
- hs := make(HostSwitch)
- hs["example.com:12345"] = router
-
- // Use the HostSwitch to listen and serve on port 12345
- log.Fatal(http.ListenAndServe(":12345", hs))
- }
- package main
-
- import (
- "log"
- "net/http"
-
- "github.com/gookit/rux"
- )
-
- type Product struct {
- }
-
- // middlewares [optional]
- func (Product) Uses() map[string][]rux.HandlerFunc {
- return map[string][]rux.HandlerFunc{
- // function name: handlers
- "Delete": []rux.HandlerFunc{
- handlers.HTTPBasicAuth(map[string]string{"test": "123"}),
- handlers.GenRequestID(),
- },
- }
- }
-
- // all products [optional]
- func (p *Product) Index(c *rux.Context) {
- // do something ...
- }
-
- // create product [optional]
- func (p *Product) Create(c *rux.Context) {
- // do something ...
- }
-
- // save new product [optional]
- func (p *Product) Store(c *rux.Context) {
- // do something ...
- }
-
- // show product with {id} [optional]
- func (p *Product) Show(c *rux.Context) {
- // do something ...
- }
-
- // edit product [optional]
- func (p *Product) Edit(c *rux.Context) {
- // do something ...
- }
-
- // save edited product [optional]
- func (p *Product) Update(c *rux.Context) {
- // do something ...
- }
-
- // delete product [optional]
- func (p *Product) Delete(c *rux.Context) {
- // do something ...
- }
-
- func main() {
- router := rux.New()
-
- // methods Path Action Route Name
- // GET /product index product_index
- // GET /product/create create product_create
- // POST /product store product_store
- // GET /product/{id} show product_show
- // GET /product/{id}/edit edit product_edit
- // PUT/PATCH /product/{id} update product_update
- // DELETE /product/{id} delete product_delete
- // resetful style
- router.Resource("/", new(Product))
-
- log.Fatal(http.ListenAndServe(":12345", router))
- }
- package main
-
- import (
- "log"
- "net/http"
-
- "github.com/gookit/rux"
- )
-
- // News controller
- type News struct {
- }
-
- func (n *News) AddRoutes(g *rux.Router) {
- g.GET("/", n.Index)
- g.POST("/", n.Create)
- g.PUT("/", n.Edit)
- }
-
- func (n *News) Index(c *rux.Context) {
- // Do something
- }
-
- func (n *News) Create(c *rux.Context) {
- // Do something
- }
-
- func (n *News) Edit(c *rux.Context) {
- // Do something
- }
-
-
- func main() {
- router := rux.New()
-
- // controller style
- router.Controller("/news", new(News))
-
- log.Fatal(http.ListenAndServe(":12345", router))
- }
- package main
-
- import (
- "log"
- "net/http"
- "net/url"
-
- "github.com/gookit/rux"
- )
-
- func main() {
- // Initialize a router as usual
- router := rux.New()
- router.GET(`/news/{category_id}/{new_id:\d+}/detail`, func(c *rux.Context) {
- var u = make(url.Values)
- u.Add("username", "admin")
- u.Add("password", "12345")
-
- b := rux.NewBuildRequestURL()
- // b.Scheme("https")
- // b.Host("www.mytest.com")
- b.Queries(u)
- b.Params(rux.M{"{category_id}": "100", "{new_id}": "20"})
- // b.Path("/dev")
- // println(b.Build().String())
-
- println(c.Router().BuildRequestURL("new_detail", b).String())
- // result: /news/100/20/detail?username=admin&password=12345
- // get current route name
- if c.MustGet(rux.CTXCurrentRouteName) == "new_detail" {
- // post data etc....
- }
- }).NamedTo("new_detail", router)
-
- // Use the HostSwitch to listen and serve on port 12345
- log.Fatal(http.ListenAndServe(":12345", router))
- }
github 地址:https://github.com/gookit/rux