lris路由

作者: TZX_0710 | 来源:发表于2021-08-24 15:22 被阅读0次

    路由行为

    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方法。

    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
    
    

    路由组

    一些列路由可以通过路径的前缀分组。共享相同的中间件处理器和模板布局。一个组也可以有一个内嵌的组

    package main
    
    import "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方法编写相同的内容,它接受子路由器或者Party
    package main
    
    import "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类型 取值范围 取值方式
    :string string 任何值(单个字段路径) Params().Get
    :int int -9223372036854775808 - 9223372036854775807 (x64) </br>-2147483648 - 2147483647 (x32) Params().GetInt
    :int8 int8 -128 - 127 Params().GetInt8
    :int16 int16 -32768 - 32767 Params().GetInt16
    :int32 int32 -2147483648 - 2147483647 Params().GetInt32
    :int64 int64 -9223372036854775808 - 9223372036854775807 Params().GetInt64
    :uint8 uint8 0 - 255 Params().GetUint8
    :uint16 uint16 0 - 65535 Params().GetUint16
    :uint32 uint32 0 - 4294967295 Params().GetUint32
    :uint64 uint64 0 - 18446744073709551615 Params().GetUint64
    :bool bool "1","t","T","TRUE","true","True","0","f", "F", "FALSE",,"false","False" Params().GetBool
    :alphabetical string 小写或大写字母 Params().Get
    :file string 大小写字母,数字,下划线(_),横线(-),点(.),以及没有空格或者其他对文件名无效的特殊字符 Params().Get
    :path string 任何可以被斜线(/)分隔的路径段,但是应该为路由的最后一部分 Params().Get
    内建函数
    内建函数 参数类型
    regexp(expr string) :string
    prefix(prefix string) :string
    suffix(suffix string) :string
    contains(s string) :string
    min(最小值),接收:int,int8,int16,int32,int64,uint8uint16,uint32,uint64,float32,float64) :string(字符长度),:int,:int16,:int32,:int64,</br>:uint,:uint16,:uint32,:uint64
    max(最大值),接收:int,int8,int16,int32,int64,uint8uint16,uint32,uint64,float32,float64) :string(字符长度),:int,:int16,:int32,:int64,</br>:uint,:uint16,:uint32,:uint64
    range(最小值,最大值),接收:int,int8,int16,int32,int64,uint8uint16,uint32,uint64,float32,float64) :int,:int16,:int32,:int64,</br>:uint,:uint16,:uint32,:uint64
    自己做

    RegisterFunc可以接受任何返回func(paramValue string)bool的函数、如果验证失败则触发404或者任意else关键字拥有的状态码

    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个数如果这个参数值 大于最小值 小于最大值 则通过 否则400
      app.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的范围之内 否则400 
      app.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"))
    }
    
    
    中间件
    package main
    
    import (
      "fmt"
      "github.com/kataras/iris/v12"
    )
    
    func main() {
      //改正则表达式 匹配0次或者1次-
      //0-9匹配1位到3位
    
      app := iris.New()
      //这个函数接受2个数如果这个参数值 大于最小值 小于最大值 则通过 否则400
      app.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 ")
    }
    //result
    before the main Hanlder
    business
    after 
    
    处理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-Typeapplication/problem+json

    使用options.RenderXMLXML字段来改变他的行为。用application/problem+xml的文本类型替代。

    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{} { [...] }
          })
    }
    
    
    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-WarnX-API-Deprecation-DataX-API-Deprecation-Info头部的选项
    获取版本

    当前请求的版本通过versiong.GetVersion(ctx)获得

    package main
    
    import (
      "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创建一个简单处理器,这个处理器决定基于请求的版本。哪个处理器需要执行。

    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
    
    
    弃用

    使用Versioning.Deprecated(handler iris.Handler,options versioning.DeprecationOptions)iris.Handler函数

    可以标记特定的处理器版本为被弃用的

    package main
    
    import (
      "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")
    }
    
    

    相关文章

      网友评论

        本文标题:lris路由

        本文链接:https://www.haomeiwen.com/subject/fidliltx.html