开发插件:HTTP中间件

英文原文:https://github.com/mholt/caddy/wiki/Writing-a-Plugin:-HTTP-Middleware


加入Caddy交流论坛和其他开发者一起分享。

这个页面描述了如何开发一个向HTTP服务器添加中间件的插件。

重要提示:你应该首先阅读开发插件:指令。本教程建立在它的基础上。

在本教程中,你将了解到如下内容:

HTTP中间件在Caddy中如何工作

查看httpserver包的godoc。最重要的两种类型是httpserver.Handlerhttpserver.Middleware

Handler是一个处理HTTP请求的函数。

Middleware是一种连接Handler的方式。

Caddy将负责为你设置HTTP服务器的所有簿记(bookkeeping)工作,但是你需要实现这两种类型。

开发一个Handler

httpserver.Handler是一个几乎和http.Handler完全一样的接口,除了ServeHTTP方法返回(int, error)。这个方法签名遵循Go语言博客中关于与中间件相关的错误处理的建议int是HTTP状态码,error应该被处理和/或记录。有关这些返回值的详细信息,请参阅godoc。

Handler通常是一个结构体,至少包含一个Next字段,用来链接下一个Handler

type MyHandler struct {
    Next httpserver.Handler
}

为了实现httpserver.Handler接口,我们需要编写一个名为ServeHTTP的方法。这个方法是实际的处理程序函数,除非它自己完全处理请求,否则它应该调用链中的下一个Handler

func (h MyHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) (int, error) {
    return h.Next.ServeHTTP(w, r)
}

就是这样。

注意竞态条件——尽可能避免进入状态,使用Go的竞态探测器(-race)!

如何添加Handler到Caddy

回到设置函数。你刚刚解析了标识并使用所有适当的配置设置了中间件处理程序:

func setup(c *caddy.Controller) error {
    for c.Next() {
        // get configuration
    }
    // now what?
}

要在新的处理程序中进行链接,请从httpserver包中获取当前站点的配置,然后将处理程序包装到一个中间件函数中:

cfg := httpserver.GetConfig(c)
mid := func(next httpserver.Handler) httpserver.Handler {
    return MyHandler{Next: next}
}
cfg.AddMiddleware(mid)

你完成了!当然,在本例中,我们只是分配了一个没有特殊配置的MyHandler。在你的示例中,可能希望将配置存储在名为“rules”的结构中,这样就可以处理指令的多种用法并逐条添加规则。做与不做,这取决于你想做什么。只要你正确地链接了next,这真的不重要!