路由

未匹配的标注

Buffalo 使用 github.com/gorilla/mux 作为app的路由实现,同时也再封装了一层API。下面就是介绍路由相关的使用方法。

创建一个Buffalo应用(和路由)

应用的配置在app.go文件中:

a := buffalo.New(buffalo.Options{
  Env:         ENV,
  SessionName: "_coke_session",
})

默认的配置满足大部分的需求,如果你需要自定义更多的选项,可以参照 godoc.org/github.com/gobuffalo/buf...

映射handler

所有的路由都应该对应一个buffalo.Handler的函数,这样的handler函数类似这样的:

func (c buffalo.Context) error {
  // do some work
}

在MVC的模式中对应的其实就是Controller部分,主要app的逻辑实现部分。这些handler函数默认带了buffalo.Context结构,这个结构体包含了当前请求的所有信息。
上下文 去了解更多的关于该结构体的知识。

Buffalo支持如下http方法:

  • GET
  • POST
  • PUT
  • PATCH
  • DELETE
  • OPTIONS
  • HEAD

也可以使用ANY来匹配所有的HTTP方法。
映射HTTP方法到handler的方法如下:

a.GET("/some/path", SomeHandler)
a.POST("/some/path", func (c buffalo.Context) error {
  // do some work
})
// etc...

用内联的handler函数是一个推荐的方法。同时为了提高代码的可读性,我们也可以将一组相关的handler函数写到一个文件中,比如和用户相关的handler可以放在actions目录下一个user.go的文件中。需要自建,可以通过命令行创建,后面又介绍。

命名路由

默认情况下Buffalo是用路由的路径加上Path来命名的。比如 a.GET("/coke", CokeHandler) 的路由名称就是 cokePath。

a.GET("/coke", CokeHandler) // cokePath()

在视图中就可以使用路由名称来直接连接和跳转了。

<a href="<%= cokePath() %>">Coke</a>

我们可以通过命令行buffalo routes 来查看当前app下所有的路由及名称。

$ buffalo routes

METHOD | PATH                       | ALIASES | NAME           | HANDLER
------ | ----                       | ------- | ----           | -------
GET    | /                          |         | rootPath       | github.com/markbates/coke/actions.HomeHandler
GET    | /widgets/                  |         | widgetsPath    | github.com/markbates/coke/actions.WidgetsResource.List
POST   | /widgets/                  |         | widgetsPath    | github.com/markbates/coke/actions.WidgetsResource.Create
GET    | /widgets/new/              |         | newWidgetsPath | github.com/markbates/coke/actions.WidgetsResource.New
GET    | /widgets/{widget_id}/      |         | widgetPath     | github.com/markbates/coke/actions.WidgetsResource.Show
PUT    | /widgets/{widget_id}/      |         | widgetPath     | github.com/markbates/coke/actions.WidgetsResource.Update
DELETE | /widgets/{widget_id}/      |         | widgetPath     | github.com/markbates/coke/actions.WidgetsResource.Destroy
GET    | /widgets/{widget_id}/edit/ |         | editWidgetPath | github.com/markbates/coke/actions.WidgetsResource.Edit

重要提示:由于默认的路由名称是根据路径来命名的,所以即使是对应的handler没有变只是路径变了,路由的名称也会跟着变。

app.Resource("/fooz", WidgetsResource{})
$ buffalo routes

METHOD | PATH                    | ALIASES | NAME         | HANDLER
------ | ----                    | ------- | ----         | -------
GET    | /                       |         | rootPath     | github.com/markbates/coke/actions.HomeHandler
GET    | /fooz/                  |         | foozPath     | github.com/markbates/coke/actions.WidgetsResource.List
POST   | /fooz/                  |         | foozPath     | github.com/markbates/coke/actions.WidgetsResource.Create
GET    | /fooz/new/              |         | newFoozPath  | github.com/markbates/coke/actions.WidgetsResource.New
GET    | /fooz/{widget_id}/      |         | foozPath     | github.com/markbates/coke/actions.WidgetsResource.Show
PUT    | /fooz/{widget_id}/      |         | foozPath     | github.com/markbates/coke/actions.WidgetsResource.Update
DELETE | /fooz/{widget_id}/      |         | foozPath     | github.com/markbates/coke/actions.WidgetsResource.Destroy
GET    | /fooz/{widget_id}/edit/ |         | editFoozPath | github.com/markbates/coke/actions.WidgetsResource.Edit

自定义路由名称 来查看如何改变默认生成的路由名称。

在视图模板中使用路由的助手方法

路由的助手方法可以直接在模板中使用:

<%= widgetsPath() %> // /widgets

也可以给路由助手类传参:

<%= editWidgetPath({widget_id: 1}) %> // /widgets/1/edit

在action中使用路由助手

直接跳转

可以通过路由的名称直接跳转到相应的地址

func MyHandler(c buffalo.Context) error {
  return c.Redirect(307, "widgetsPath()")
  // Or with parameters
  return c.Redirect(307, "widgetPath()", render.Data{"widget_id": "1"})
}

查找和调用 路由助手

直接上代码:

func MyHandler(c buffalo.Context) error {
  ri, err := App().Routes().Lookup("widgetPath")
  if err != nil {
    return errors.WithStack(err)
  }
  h := ri.BuildPathHelper()
  u, err := h(render.Data{"widget_id": 1})
  if err != nil {
    return errors.WithStack(err)
  }
  return c.Redirect(307, string(u))
}

自定义路由

我们可以通过buffalo.RouteInfo#Name 方法来自定义路由的名称。

a.GET("/coke", CokeHandler).Name("customPath")

在视图模板中就可以直接调用了。

<a href="<%= customPath() %>">Coke</a>

参数

请求的参数可以用 buffalo.Context 中获取到:

a.GET("/users", func (c buffalo.Context) error {
  return c.Render(200, r.String(c.Param("name")))
})

对于以上给出的例子,如果请求是 GET /users?name=ringo,那么将返回 200: ringo.

命名的参数

在路由的路径中指定名称的参数,也是通过 buffalo.Context#Param 方法获取的。

a.GET("/users/{name}", func (c buffalo.Context) error {
  return c.Render(200, r.String(c.Param("name")))
})

对于以上的例子,如果请求是 GET /users/ringo, 那么也将返回 200: ringo.

a.GET("/users/new", func (c buffalo.Context) error {
  return c.Render(200, r.String("new"))
})
a.GET("/users/{name}", func (c buffalo.Context) error {
  return c.Render(200, r.String(c.Param("name")))
})

这两个路由非常相似,但是也没有问题。系统会优先匹配安全相等的路由。

正则表达式

github.com/gorilla/mux也支持正则表达式来匹配路由。

a.GET("/articles/{id:[0-9]+}", func (c buffalo.Context) error {
  return c.Render(200, r.String(c.Param("id")))
})

路由组

在一些场景下,我们会用到路由组,比如一组路由使用一个中间件,或者api接口不用的版本。

g1 := a.Group("/api/v1")
g1.Use(APIAuthorizer)
g1.GET("/users", func (c buffalo.Context) error {
  // responds to GET /api/v1/users
})
g2 := a.Group("/api/v2")
g2.Use(APIAuthorizer)
g2.GET("/users", func (c buffalo.Context) error {
  // responds to GET /api/v2/users
})

默认的路由组也会继承自父的app。

a.Use(SomeMiddleware)
g := a.Group("/api/v1")
g.Use(APIAuthorizer)

在这种情况下 /api/v1 实际上是有两个中间件的,一个是自己的APIAuthorizer,另一个是继承来的SomeMiddleware。更多的中间配置,见中间件 章节。

本文章首发在 LearnKu.com 网站上。

上一篇 下一篇
superwen
讨论数量: 0
发起讨论 只看当前版本


暂无话题~