起步
上一节总体说了 Iris 的路由、视图、中间件、模板,掌握了快速搭建 web 服务的基本技能。这一节将更深入路由相关知识。
简易的 API
相比于 func (api *APIBuilder) Get(relativePath string, handlers ...context.Handler) *Route
其实 Iris 有暴露更底层的接口,也就 Handle:
func main() {
app := iris.Default()
// 允许跨域访问
app.Use(func(ctx iris.Context) {
ctx.Header("Access-Control-Allow-Origin", "*")
ctx.Next()
})
// 注册 path = "/" 的 Get 方法
app.Handle("GET", "/", func(ctx iris.Context) {
ctx.HTML("This is Index")
})
// 注册 path = "/hername" 的 Post 方法
app.Handle("POST", "/hername", func(ctx iris.Context) {
name := ctx.FormValue("name")
ctx.JSON(iris.Map{
"herName": name,
})
})
app.Run(iris.Addr(":8080"))
}
Handle 接收三个参数,第一个是 http 请求方式,第二个是 http path,最后一个是 handler 函数。
打开 chrome 浏览器控制台,可键入以下代码测路由是否注册成功。
// 验证 path = "/" GET
fetch("http://0.0.0.0:8080/").then(resp => resp.text()).then(data => console.log(data))
// 验证 path = "/hername" POST
let f = new FormData()
f.append("name", "zhong")
fetch("http://0.0.0.0:8080/hername", {method: "POST", body:f}).then(resp => resp.json()).then(data => console.log(data))
而为方便起见,Iris 提供了更易用的上层接口,并满足各种 http 请求方式的需求。
app := iris.New()
// Method: "GET"
app.Get("/", handler)
// Method: "POST"
app.Post("/", handler)
// Method: "PUT"
app.Put("/", handler)
// Method: "DELETE"
app.Delete("/", handler)
// Method: "OPTIONS"
app.Options("/", handler)
// Method: "TRACE"
app.Trace("/", handler)
// Method: "CONNECT"
app.Connect("/", handler)
// Method: "HEAD"
app.Head("/", handler)
// Method: "PATCH"
app.Patch("/", handler)
// register the route for all HTTP Methods
app.Any("/", handler)
func handler(ctx iris.Context){
ctx.Writef("Hello from method: %s and path: %s\n", ctx.Method(), ctx.Path())
}
默认行为
对一个 http 的 url 来说,末尾要不要加上 /
总是傻傻分不清。Iris 的处理干净利落,认为一切不需要加末尾斜线。如果客户端访问了 $your_host/api/user/
,那么默认重定向到 $your_host/api/user
。
当然,你也可以选择关闭这种默认行为:
func main() {
app := iris.Default()
app.Get("/api/user", func(ctx iris.Context) {
// handle request
})
// 关闭 path 的修复功能
app.Run(iris.Addr(":8080"), iris.WithoutPathCorrection)
}
此时,访问 /api/user
与访问 /api/user/
的效果就有所不同了。
离线路由(Offline Routes)
离线路由是指,无法从外界访问这个 router,但你可以从其他 router 中借助 Context.Exec
方法访问。具体实现方式是:
func main() {
app := iris.Default()
// 注册离线路由
app.None("/hername", func(ctx iris.Context) {
ctx.HTML("zhong")
})
// 在 router 中调用离线路由
app.Get("/", func(ctx iris.Context) {
ctx.Exec("NONE", "/hername")
})
app.Run(iris.Addr(":8080"))
}
现在访问 http://127.0.0.1:8080/hername 页面报 404,访问 http://127.0.0.1:8080 页面展示“zhong”。
借助离线路由,我们就可以动态控制一个 url 能否被外界直接访问。完整实例如下:
func main() {
app := iris.Default()
// 注册离线路由
none := app.None("/hername", func(ctx iris.Context) {
ctx.HTML("zhong")
})
app.Get("/change", func(ctx iris.Context) {
var notifyString string
if none.IsOnline() {
// 如果在线就设置为离线
none.Method = iris.MethodNone
notifyString = "将 /hername 设置为离线"
} else {
// 如果离线就设置为在线
none.Method = iris.MethodGet
notifyString = "将 /hername 设置为在线,Get 访问"
}
// 运行时刷新路由
app.RefreshRouter()
ctx.HTML(notifyString)
})
app.Get("/", func(ctx iris.Context) {
if none.IsOnline() {
// 如果 /hername 在线,Get 方式请求
ctx.Exec("GET", "/hername")
} else {
// 如果 /hername 离线,None 方式请求
ctx.Exec("NONE", "/hername")
}
})
app.Run(iris.Addr(":8080"))
}
Router.IsOnline()
用于检测 router 是否在线。app.RefreshRouter()
可以运行时刷新 router 的状态。- 对
Router.Method
赋值可改变其 router 的 http 请求方法,但调用app.RefreshRouter()
后才能生效。
运行上述代码,不论 http://127.0.0.1/hername
处于离线还是在线,访问http://127.0.0.1
都能成功调用 /hername 的处理逻辑。通过访问 http://127.0.0.1/change
可改变 /hername 的访问状态。
分组路由(Grouping Routes)
路由可通过相同的 path 前缀进行分组,同一组路由可共享一个中间件以及模板。
具体使用示例:
func main() {
app := iris.Default()
// 如果想为 grouping routes 添加组件
// 其方式是:app.Party("user", MyMiddleware, ...)
user := app.Party("user")
user.Get("/id", func(ctx iris.Context) {
ctx.HTML("user id")
})
user.Get("/name", func(ctx iris.Context) {
ctx.HTML("user name")
})
app.Run(iris.Addr(":8080"))
}
- 访问 http://127.0.0.1:8080/user/id 页面返回 "user id"。
- 访问 http://127.0.0.1:8080/user/name 页面返回 “user name”。
其效果等同于 app.PartyFunc
。
func main() {
...
app.PartyFunc("/user", func(user iris.Party) {
user.Get("/id", func(ctx iris.Context) {
ctx.HTML("user id")
})
user.Get("/name", func(ctx iris.Context) {
ctx.HTML("user name")
})
})
...
}
路径参数(Path Parameters)
一般我把 url 的路径参数称之为 url 位置传参。Iris 提供的 path params 用法与 Flask 相似,简单也强大。简单在于,在 url 路径中,将 param 用花括号包起来即可,如/user/{name}
;强大则是,它支持类型限制,支持内嵌函数,对检验器(validation)还能自定义。
func main() {
...
// 当不对参数指定类型时,默认为 string 类型
// 即: "/user/{name}" 等同于 "/user/{name:int}"
app.Get("/user/{name}", func(ctx iris.Context) {
// 借助 ctx.Params() 暴露出来的端口,获取参数对应的值
str := fmt.Sprintf("Hello, %s", ctx.Params().GetString("name"))
ctx.HTML(str)
})
// 指定 id 为 int 型,并且要求 id 的值 > 10000
app.Get("/userid/{id:int min(1000)}", func(ctx iris.Context) {
// GetInt16Default("id", 1000)) 表示如果没有 id 键的存在,则返回 1000
str := fmt.Sprintf("Your id is %d", ctx.Params().GetInt16Default("id", 1000))
ctx.HTML(str)
})
...
}
- 此时访问
http://127.0.0.1:8080/userid/999
(404) 与http://127.0.0.1:8080/userid/1000
效果大不同。
以上就是 path 的简单应用。而受篇幅原因,关于 Iris 的 path params 更多知识将在下一节中继续阐述。
还不快抢沙发