路由行为
Iris默认接受和注册形如/api/user这样的路径的路由,且尾部不带斜杠。如果客户端尝试访问$your_host/api/user/,Iris路由会自动永久重定向(301)到$your_host/api/user,以便注册的路由进行处理。这是设计APIs的现代化的方式。如果你想禁用请求的
路径更正的功能的话,你可以在app.Run传递iris.WithoutPathCorrection配置选项。例如
app.Run(iris.Addr(":8080"),iris.WithoutPathCorrection)//如果向/api/user和/api/user、在不重定向的情况下拥有相同的处理器,只需要`iris.WithoutPathCorrectionRedirection`选项即可app.Run(iris.Addr(":8080"),iris.WithoutPathCorrectionRedirection)Api
支持所有的HTTP方法,开发者也可以在相同的路径的不同的方法注册处理器(比如
/user的Get和POST)第一个参数是HTTP方法,第二个参数是请求的路径,第三个可变参数应包含一个或者多个
iris.Handler当客户端请求到特定的资源路径时,这些处理器将会按照注册的顺序依次执行。示例代码
app:=iris.New()app.Handle("GET","/contact",func(ctx iris.Context){ctx.HTML("<h1>hello from /contact</h1>")})为了让后端开发者做事更容易,
Iris为所有的HTTP方法提供了”帮手”。第一个参数是路由的请求路径,第二个可变参数是一个或者多个iris.Handler也会按照顺序依次执行离线路由
在
Iris中有一个特俗得方法可以使用。它被称为None.你可以使用它向外部隐藏一条路由,但仍然可以从其他路由处理中通过Context。Exec方法调用。每个API处理方法返回Route值。一个Route得IsOnline方法报告那个路由的当前状态。你可以通过它的Route.Method字段的值来改变路由离线状态为在线状态。每次需要调用app.RefreshRouter方法。```go package main
import ( “github.com/kataras/iris/v12” )
func main() { app := iris.New() //离线路由 none := app.None(“/leaveRouter”, func(context iris.Context) { context.Writef(“hello world %v”, context.Method()) }) //app.Get app.Get(“/change”, func(context iris.Context) { //如果在西安 if none.IsOnline() { none.Method = iris.MethodNone } else { none.Method = iris.MethodGet } }) app.Run(iris.Addr(“:8080”)) } //先采用 http://localhost:8080/leaveRouter 访问 返回 Not Found //http://localhost:8080/change //http://localhost:8080/leaveRoute hello world GET
> > <a name="14de92d5"></a>#### 路由组> 一些列路由可以通过路径的前缀分组。共享相同的中间件处理器和模板布局。一个组也可以有一个内嵌的组> ```gopackage mainimport "github.com/kataras/iris/v12"func main() {//初始化application := iris.New()v1 := application.Party("/v1")v1.Get("/getName", func(context iris.Context) {context.Writef("name:%v", "zhangsan")})v1.Get("/getAge", func(context iris.Context) {context.Writef("age:%v", 10)})application.Run(iris.Addr(":8080"))}//http://localhost:8080/v1/getAge//http://localhost:8080/v1/getName也可以使用PartyFunc方法编写相同的内容,它接受子路由器或者Partypackage mainimport "github.com/kataras/iris/v12"func main() {//初始化application := iris.New()application.PartyFunc("/v1", func(user iris.Party) {user.Get("/getName", func(context iris.Context) {context.Writef("name:%v", "zhangsan")})user.Get("/getAge", func(context iris.Context) {context.Writef("age:%v", 10)})})application.Run(iris.Addr(":8080"))}
路径参数
与你见到的其他路由器不同,Iris的路由器可以处理各种 路由路径而不会发生冲突
//只匹配到/app.Get("/")//匹配到所有的user/前缀的请求app.Get("/user/{user:path})//匹配以profile前缀的GET请求app.Get("/profile/{username:string}")//匹配profile/me的Get请求app.Get("/user/{userid:int min(1)}")//匹配前缀为user的delete请求app.DELETE("/user/{userId:int min(1)}")//除了被其他路由器处理的请求,其他的都可以匹配到app.Get("{root:path}")路径参数类型
Iris拥有你见过的最简单和强大路由处理
Iris自己拥有于路由路径语法解析和判定的解释器参数
一个路径的参数的名字应该仅仅包含
字母。数字和类似”_”这样的符号是不允许的不要迷惑于
ctx.Params()和ctx.Values()
- 路径的参数值可以通过
ctx.Params()取出ctx中用于处理器与中间件之间通信的本地存储可以存储在ctx.Values()中内建参数类型
参数类型 golang类型 取值范围 取值方式 :stringstring任何值(单个字段路径) Params().Get:intint-9223372036854775808 - 9223372036854775807 (x64)
-2147483648 - 2147483647 (x32)Params().GetInt:int8int8-128 - 127 Params().GetInt8:int16int16-32768 - 32767 Params().GetInt16:int32int32-2147483648 - 2147483647 Params().GetInt32:int64int64-9223372036854775808 - 9223372036854775807 Params().GetInt64:uint8uint80 - 255 Params().GetUint8:uint16uint160 - 65535 Params().GetUint16:uint32uint320 - 4294967295 Params().GetUint32:uint64uint640 - 18446744073709551615 Params().GetUint64:boolbool“1”,”t”,”T”,”TRUE”,”true”,”True”,”0”,”f”, “F”, “FALSE”,,”false”,”False” Params().GetBool:alphabeticalstring小写或大写字母 Params().Get:filestring大小写字母,数字,下划线(_),横线(-),点(.),以及没有空格或者其他对文件名无效的特殊字符 Params().Get:pathstring任何可以被斜线(/)分隔的路径段,但是应该为路由的最后一部分 Params().Get内建函数
内建函数 参数类型 regexp(expr string):stringprefix(prefix string):stringsuffix(suffix string):stringcontains(s string):stringmin(最小值),接收:int,int8,int16,int32,int64,uint8,uint16,uint32,uint64,float32,float64):string(字符长度),:int,:int16,:int32,:int64,:uint,:uint16,:uint32,:uint64max(最大值),接收:int,int8,int16,int32,int64,uint8,uint16,uint32,uint64,float32,float64):string(字符长度),:int,:int16,:int32,:int64,:uint,:uint16,:uint32,:uint64range(最小值,最大值),接收:int,int8,int16,int32,int64,uint8,uint16,uint32,uint64,float32,float64):int,:int16,:int32,:int64,:uint,:uint16,:uint32,:uint64自己做
RegisterFunc可以接受任何返回
func(paramValue string)bool的函数、如果验证失败则触发404或者任意else关键字拥有的状态码```go package main
import ( “fmt” “github.com/kataras/iris/v12” “regexp” )
func main() { //改正则表达式 匹配0次或者1次- //0-9匹配1位到3位 latLonExpr := “^-?[0-9]{1,3}(?:\.[0-9]{1,10})?$” latLonRegex, _ := regexp.Compile(latLonExpr)
app := iris.New()// 将您的自定义无参数宏函数注册到 :string 参数类型。// MatchString 是 func(string) bool 的一种类型,因此我们按原样使用它。app.Macros().Get("string").RegisterFunc("coordinate", latLonRegex.MatchString)//http://localhost:8080/coordinates/AAA/BBB 404 NOT found 因为正则表达式全是数字//http://localhost:8080/coordinates/111/222 通过app.Get("/coordinates/{lat:string coordinate()}/{lon:string coordinate()}",func(ctx iris.Context) {getString := ctx.Params().GetString("lat")fmt.Println(getString)ctx.Writef("Lat: %s | Lon: %s", ctx.Params().Get("lat"), ctx.Params().Get("lon"))})app.Run(iris.Addr(":8080"))
} //注册接受2个int类型的函数 package main
import ( “github.com/kataras/iris/v12” )
func main() { //改正则表达式 匹配0次或者1次- //0-9匹配1位到3位
app := iris.New()//这个函数接受2个数如果这个参数值 大于最小值 小于最大值 则通过 否则400app.Macros().Get("string").RegisterFunc("range", func(minLength, maxLength int) func(string) bool {return func(paramValue string) bool {return len(paramValue) >= minLength && len(paramValue) <= maxLength}})//limitchar后面的值在5,200的范围之内 否则400app.Get("/limitchar/{name:string range(5,200) else 400}", func(ctx iris.Context) {name := ctx.Params().Get("name")ctx.Writef(`Hello %s | the name should be between 1 and 200 characters length otherwise this handler will not be executed`, name)})app.Run(iris.Addr(":8080"))
}
> > <a name="3cbfec33"></a>##### 中间件> ```gopackage mainimport ("fmt""github.com/kataras/iris/v12")func main() {//改正则表达式 匹配0次或者1次-//0-9匹配1位到3位app := iris.New()//这个函数接受2个数如果这个参数值 大于最小值 小于最大值 则通过 否则400app.Get("/get", before, mainHanlder, after)app.Run(iris.Addr(":8080"))}func before(ctx iris.Context) {fmt.Println("before the main Hanlder")ctx.Next()}func mainHanlder(ctx iris.Context) {fmt.Println("business")ctx.Next()}func after(ctx iris.Context) {fmt.Println("after ")}//resultbefore the main Hanlderbusinessafter
处理HTTP错误
自定义处理器处理特定的http错误
func main(){app:=iris.New()app.OnErrorCode(iris.StatusNotFound,notFound)app.Run(iris.Addr(":8080"))}func notFound(){ctx.View("errors/404.html")}问题类型
Iris内建支持HTTP APIs的错误详情
Context.Problem编写一个JSON或者XML问题响应,行为完全类似Context.JSON但是默认ProblemOptions.JSON的缩进是””,响应的Content-Type为application/problem+json使用
options.RenderXML和XML字段来改变他的行为。用application/problem+xml的文本类型替代。```go package main
import ( “github.com/kataras/iris/v12” )
func newProductPoblem(productName, detail string) iris.Problem { return iris.NewProblem(). Type(“/product-error”). Title(“Product validation problem”). Detail(detail). Status(iris.StatusBadRequest). Key(“productName”, productName) } func main() { app := iris.New() app.Get(“/problem”, fireProblem) app.Run(iris.Addr(“:8080”)) }
func fireProblem(ctx iris.Context) { ctx.Problem(newProductPoblem(“productName”, “problem details”), iris.ProblemOptions{ JSON: iris.JSON{ Indent: “”, }, // OR // Render as XML: // RenderXML: true, // XML: iris.XML{Indent: “ “}, // Sets the “Retry-After” response header. // // Can accept: // time.Time for HTTP-Date, // time.Duration, int64, float64, int for seconds // or string for date or duration. // Examples: // time.Now().Add(5 time.Minute), // 300 time.Second, // “5m”, // RetryAfter: 300, // A function that, if specified, can dynamically set // retry-after based on the request. // Useful for ProblemOptions reusability. // Overrides the RetryAfter field. // // RetryAfterFunc: func(iris.Context) interface{} { […] } }) }
> > <a name="4fcf3af7"></a>##### API版本控制>
go get github.com/kataras/iris/v12/versioning
> - 对于每个路由版本匹配,一个普通的iris处理程序,带有"switch"案例通过版本 处理程序的映射> - 每组版本化的路由和启用API> - 版本匹配,例如">=1.0 ,<2.0"或仅仅是"2.0.1"等> - 找不到版本的处理程序(可以通过简单地添加versiong.NotFound)来自定义:customNotMatchVersionHandler在映射上> - 版本是从"Accept"和"Accept-Version"头中检索到地> - 如果版本找到,响应具有`X-API-Version`头> - 通过`Deprecated`包装器,弃用了自定义`X-API-Warn`,`X-API-Deprecation-Data`,`X-API-Deprecation-Info`头部的选项> > <a name="3f1e8309"></a>##### 获取版本> 当前请求的版本通过versiong.GetVersion(ctx)获得> ```gopackage mainimport ("fmt""github.com/kataras/iris/v12""github.com/kataras/iris/v12/versioning")func main() {app := iris.New()app.Get("/problem", func(context iris.Context) {//获取当前系统的版本号fmt.Println(versioning.GetVersion(context))})app.Run(iris.Addr(":8081"))}//我们可以通过中间件设置自定义版本func(ctx iris.Context){ctx.Values().Set(versiong.Key, ctx.URLParamDefault("version", "1.0"))ctx.Next()}
将版本与处理程序匹配
versioning.NewMatcher(versiong.Map)iris.Handler创建一个简单处理器,这个处理器决定基于请求的版本。哪个处理器需要执行。```go package main
import ( “github.com/kataras/iris/v12” “github.com/kataras/iris/v12/versioning” )
func main() {
application := iris.New()
myMiddle := func(ctx iris.Context) {
ctx.Next()
}
versionNotFound := func(ctx iris.Context) {
ctx.StatusCode(404)
ctx.Writef(“version %v”, versioning.GetVersion(ctx))
}
party := application.Party(“/version”)
party.Get(“/“, myMiddle, versioning.NewMatcher(versioning.Map{
“1.0”: func(context iris.Context) {
context.Writef(“1.0”)
},
“2.0”: func(context iris.Context) {
context.Writef(“2.0”)
},
versioning.NotFound: versionNotFound,
}))
application.Run(iris.Addr(“:8081”))
}
//请求
curl -H “Accept-Version:2” http://localhost:8081/version //2.0
curl -H “Accept-Version:1” http://localhost:8081/version //1.0
curl -H http://localhost:8081/version //not found
> > <a name="d0b600ac"></a>##### 弃用> 使用`Versioning.Deprecated(handler iris.Handler,options versioning.DeprecationOptions)iris.Handler`函数> 可以标记特定的处理器版本为被弃用的> ```gopackage mainimport ("github.com/kataras/iris/v12""github.com/kataras/iris/v12/versioning""time")func main() {application := iris.New()myMiddle := func(ctx iris.Context) {ctx.Next()}versionNotFound := func(ctx iris.Context) {ctx.StatusCode(404)ctx.Writef("version %v", versioning.GetVersion(ctx))}deprecated := versioning.Deprecated(sendHandler, versioning.DeprecationOptions{DeprecationDate: time.Now(),})party := application.Party("/version")party.Get("/", myMiddle, versioning.NewMatcher(versioning.Map{"1.0": deprecated,"2.0": func(context iris.Context) {context.Writef("2.0")},versioning.NotFound: versionNotFound,}))application.Run(iris.Addr(":8081"))}func sendHandler(ct iris.Context) {ct.Writef("AAAAAAKKKKKK")}
