iris 打包 Router

有时你需要覆盖某个路由,抑或是根据收到的请求决定是否使用这个路由。 如果你以前有过使用 net / http 和其他web框架的经验, 这个函数你会很熟悉(它和net / http 中间件的格式相同,但不能接受下一个处理程序,而是接受Router 作为函数 是否被执行)。

// WrapperFunc 用作预期的输入参数签名。
//用于 WrapRouter。 它是一个“低级”签名,与 net / http 兼容。
// 它用于运行或不运行基于自定义逻辑的路由器。
type WrapperFunc func(w http.ResponseWriter, r *http.Request, firstNextIsTheRouter http.HandlerFunc)

// WrapRouter 方法在主路由的顶部添加一个包装器
// 通常,它对第三方中间件非常有用
//比如,当需要使用 CORS 这样的中间件去包装整个应用程序的时候。
// 开发者可以添加多个包装器,
// 这些包装器是从后向前执行的。
//这意味着第二个包装器会封装第一个包装器,依此类推。
// 在构建之前。
func WrapRouter(wrapperFunc WrapperFunc)

Iris 的路由器基于HTTP方法搜索其路由,路由器包装器可以覆盖该行为并执行自定义代码。

示例代码:

package main

import (
    "net/http"
    "strings"

    "github.com/kataras/iris"
)

//在这个实例中,你可以看到一个使用 WrapRouter 的例子.
// 当路由器执行或者不执行已经注册的路由处理程序的时候,你可以使用 WrapRouter 添加自定义的逻辑。
// 如何不使用自定义封装器,直接在根目录 "/" 启动服务。请查看 "file-server/single-page-application" 示例。
//这教程只是为了证明观点,如果它对你来说太多了,你可以跳过这个教程。

func main() {
    app := iris.New()

    app.OnErrorCode(iris.StatusNotFound, func(ctx iris.Context) {
        ctx.HTML("<b>Resource Not found</b>")
    })

    app.Get("/", func(ctx iris.Context) {
        ctx.ServeFile("./public/index.html", false)
    })

    app.Get("/profile/{username}", func(ctx iris.Context) {
        ctx.Writef("Hello %s", ctx.Params().Get("username"))
    })

    // 如果我们使用了 “/” 指向服务根目录。
        //静态网站将会覆盖所有路由,因为下划线需要通配符。
    // 在这里,我们将看到如何绕过这种行为。
        //通过创建新的文件服务
        //和为路由器建立一个包装器(就像一个低优先级中间件),
        //去手动检查路由器是否正常的处理
        //和执行文件服务器的处理程序。

    // 使用 StaticHandler 方法和 StaticWeb 一样,
        //但它没有注册路由,它只返回了处理程序。
    fileServer := app.StaticHandler("./public", false, false)

    // 用本地 net/http 处理程序包装路由器。
    // 如果 url 不包含任何  "." 符号。 (如: .css, .js...)
    // (取决应用程序,你可以需要添加更多的文件服务器异常),
    // 那么,处理程序将执行为路由器服务的已经注册的路由 (查找 "/" 和 "/profile/{username}")
    //如果没有注册的路由,那么它将使用 “/” 根目录作为服务路径。 
    app.WrapRouter(func(w http.ResponseWriter, r *http.Request, router http.HandlerFunc) {
        path := r.URL.Path
        // 注意,如果路径具有 "index.html" 后缀,它将自动重定向到 “/” 路径。
        // 所以我们的第一个处理程序将被执行。

        if !strings.Contains(path, ".") {
            // 如果它不是一个资源,则继续执行 router 方法。
            router(w, r)
            return
        }
        // 获取和释放上下文 ,用来执行我们的文件服务器。
        // 记住:我们使用 net/http.Handler 因为在路由器之前,我们是在一个 比较低的优先级。
        ctx := app.ContextPool.Acquire(w, r)
        fileServer(ctx)
        app.ContextPool.Release(ctx)
    })

    // http://localhost:8080
    // http://localhost:8080/index.html
    // http://localhost:8080/app.js
    // http://localhost:8080/css/main.css
    // http://localhost:8080/profile/anyusername
    app.Run(iris.Addr(":8080"))

    // 注意:在这个例子中,我们只使用了一个用例,
    // 你可能想使用 WrapRouter 或者 Downgrade 来代替 iris  默认的路由, 例如:
    //你可以使用此方法设置自定义代理。
    //
    //如果只想在其他路径上,而不是根目录上提供静态文件 ,你可以使用 StaticWeb方法。 例如:
    //                          .StaticWeb("/static", "./public")
    // ________________________________requestPath, systemPath
}

到这里已经介绍的差不多了,它只是一个接受本地响应编定器和请求的函数包装器,下一个处理程序是 irisRouter 本身, 不管调用与否,它都正执行或者不执行,它是整个 Router 的中间件。

下一章:iris 错误处理

当程序产生了一个特定的 http 错误的时候,你可以定义你自己的错误处理代码。错误代码是大于或者等于 400 的 http 状态码,像 404 not found 或者 500 服务器内部错误。代码例子:package ...