golang轻量级net/http中间件插件库interpose的使用
Golang轻量级net/http中间件插件库interpose的使用
介绍
Interpose是一个用于Golang的简约net/http中间件框架。它使用http.Handler
作为其核心功能单元,最大限度地减少了复杂性,并最大限度地提高了与其他中间件框架的互操作性。
它只做一件事:管理中间件。它没有任何内置功能,你需要自己提供路由器等组件。因为它基于net/http标准,Interpose可以与Gorilla框架、goji、nosurf以及许多其他框架和独立中间件开箱即用。
基本用法示例
以下是一个使用Interpose的示例,该中间件为每个响应添加HTTP头"X-Server-Name"。
创建一个main.go
文件,内容如下:
package main
import (
"fmt"
"net/http"
"github.com/carbocation/interpose"
)
func main() {
middle := interpose.New()
// 发送一个header告诉世界这个响应来自Interpose测试服务器
// 你可以想象在其他情况下设置Content-type application/json或其他有用的headers
middle.UseHandler(http.HandlerFunc(func(rw http.ResponseWriter, req *http.Request) {
rw.Header().Set("X-Server-Name", "Interpose Test Server")
}))
// 在这个例子中,我们使用一个基本路由器,它有一个匹配任何路径的catchall路由
// 最后添加的中间件最后执行,所以通过最后添加路由器,我们的其他中间件有机会在路由器写入HTTP Body之前修改HTTP headers
router := http.NewServeMux()
middle.UseHandler(router)
router.Handle("/", http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
fmt.Fprintf(w, "Welcome to %s!", req.URL.Path)
}))
http.ListenAndServe(":3001", middle)
}
在同一目录下运行go run main.go
,然后访问http://localhost:3001/world
查看输出。
路由、优雅关闭和headers
在这个例子中,我们使用graceful
包在遇到关闭信号后优雅地释放连接。使用比前一个例子更强大的路由器Gorilla mux。我们还向浏览器发送headers,指示这是来自名为"Interpose Test Server"的服务器。
package main
import (
"fmt"
"net/http"
"time"
"github.com/carbocation/interpose"
"github.com/gorilla/mux"
"github.com/stretchr/graceful"
)
func main() {
middle := interpose.New()
// 告诉浏览器这个响应来自哪个服务器
// 这修改了headers,所以我们希望在可能修改body的任何中间件之前调用它
middle.Use(func(next http.Handler) http.Handler {
return http.HandlerFunc(func(rw http.ResponseWriter, req *http.Request) {
rw.Header().Set("X-Server-Name", "Interpose Test Server")
next.ServeHTTP(rw, req)
})
})
// 应用路由器。通过最后添加它,我们的其他中间件将在路由器之前执行,
// 允许我们在任何输出生成之前修改headers
router := mux.NewRouter()
middle.UseHandler(router)
router.HandleFunc("/{user}", func(w http.ResponseWriter, req *http.Request) {
fmt.Fprintf(w, "Welcome to the home page, %s!", mux.Vars(req)["user"])
})
// 启动并允许优雅关闭,给现有连接最多10秒时间结束
graceful.Run(":3001", 10*time.Second, middle)
}
组合日志和gzip压缩
打印Apache CombinedLog兼容的日志语句到StdOut,并在客户端具有gzip能力时gzip压缩HTTP响应:
package main
import (
"compress/gzip"
"fmt"
"net/http"
"github.com/carbocation/interpose"
"github.com/carbocation/interpose/middleware"
"github.com/gorilla/mux"
)
func main() {
middle := interpose.New()
// 首先应用不会写入HTTP body输出的中间件
// 使用Gorilla框架的组合日志
middle.Use(middleware.GorillaLog())
// 使用Negroni的Gzip功能
middle.Use(middleware.NegroniGzip(gzip.DefaultCompression))
// 现在应用可以修改HTTP body的中间件
router := mux.NewRouter()
middle.UseHandler(router)
router.HandleFunc("/{user}", func(w http.ResponseWriter, req *http.Request) {
fmt.Fprintf(w, "Welcome to the home page, %s!", mux.Vars(req)["user"])
})
http.ListenAndServe(":3001", middle)
}
嵌套中间件:只为某些路由添加headers
在最后一个例子中,我们为不同的路由应用了不同的中间件。在这里,我们将扩展这个想法,在不同的路由中创建完全嵌套的中间件堆栈。这种方法虽然比上一个例子更详细,但功能强大。在这个例子中,以/green开头的路由被赋予一个特殊的HTTP头X-Favorite-Color: green,但你可以想象使用相同的方法自动为JSON请求应用JSON内容头,在受保护的路径前添加认证等。
package main
import (
"compress/gzip"
"fmt"
"net/http"
"github.com/carbocation/interpose"
"github.com/carbocation/interpose/middleware"
"github.com/gorilla/mux"
)
func main() {
middle := interpose.New()
// 首先调用可能操作HTTP headers的中间件,因为它们必须在HTTP body被操作之前调用
// 使用Gorilla框架的组合日志
middle.Use(middleware.GorillaLog())
// 使用Negroni的Gzip功能
middle.Use(middleware.NegroniGzip(gzip.DefaultCompression))
// 现在调用可以操作HTTP body的中间件
// 定义路由器。注意,如果我们愿意,可以在定义路由之前将路由器添加到我们的中间件堆栈中
router := mux.NewRouter()
middle.UseHandler(router)
// 配置我们的路由器
router.HandleFunc("/{user}", func(w http.ResponseWriter, req *http.Request) {
fmt.Fprintf(w, "Welcome to the home page, %s!", mux.Vars(req)["user"])
})
// 定义仅适用于某些路由的中间件
greenMiddle := interpose.New()
// 告诉主路由器将/green请求发送到我们的子路由器
// 同样,我们可以在定义完整的中间件堆栈之前完成此操作
router.Methods("GET").PathPrefix("/green").Handler(greenMiddle)
// 在二级中间件中,就像上面一样,我们希望调用任何会修改HTTP headers的东西,然后才修改body
greenMiddle.UseHandler(http.HandlerFunc(func(rw http.ResponseWriter, req *http.Request) {
rw.Header().Set("X-Favorite-Color", "green")
}))
// 最后,基于我们对绿色的热爱定义一个子路由器
// 当你调用任何URL如http://localhost:3001/green/man时,
// 你还会看到一个名为X-Favorite-Color的HTTP头,值为"green"
greenRouter := mux.NewRouter().Methods("GET").PathPrefix("/green").Subrouter()
greenMiddle.UseHandler(greenRouter)
greenRouter.HandleFunc("/{user}", func(w http.ResponseWriter, req *http.Request) {
fmt.Fprintf(w, "Welcome to the home page, green %s!", mux.Vars(req)["user"])
})
http.ListenAndServe(":3001", middle)
}
适配器
一些不完全兼容http.Handler
的框架使用的中间件可以很容易地转换为Interpose兼容的中间件。目前已经为Martini和Negoni创建了适配器。
例如,要在Interpose中使用github.com/urfave/negroni中间件,你可以使用adaptors.FromNegroni
:
middle := interpose.New()
// 有签名`negroni.Handler`
negroniMiddleware := negronilogrus.NewMiddleware()
// 在Interpose中使用Negroni中间件
middle.Use(adaptors.FromNegroni(negroniMiddleware))
更多示例可以在examples
文件夹及其子文件夹menagerie
中找到。
更多关于golang轻量级net/http中间件插件库interpose的使用的实战教程也可以访问 https://www.itying.com/category-94-b0.html
更多关于golang轻量级net/http中间件插件库interpose的使用的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html
Golang轻量级中间件库Interpose使用指南
Interpose是一个轻量级的Golang HTTP中间件库,它提供了简单的方式来组织和链式调用中间件。下面我将详细介绍Interpose的使用方法。
基本安装
首先安装interpose库:
go get github.com/carbocation/interpose
基础使用示例
package main
import (
"fmt"
"net/http"
"github.com/carbocation/interpose"
)
func main() {
middle := interpose.New()
// 添加简单的中间件
middle.Use(func(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
fmt.Println("Before handler")
next.ServeHTTP(w, r)
fmt.Println("After handler")
})
})
// 设置最终处理程序
middle.UseHandler(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.Write([]byte("Hello, Interpose!"))
}))
http.ListenAndServe(":8080", middle)
}
常用功能
1. 多个中间件链式调用
func main() {
middle := interpose.New()
// 中间件1 - 日志记录
middle.Use(func(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
log.Printf("Request: %s %s", r.Method, r.URL.Path)
next.ServeHTTP(w, r)
})
})
// 中间件2 - 认证检查
middle.Use(func(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
if r.Header.Get("X-Auth-Token") != "secret" {
http.Error(w, "Unauthorized", http.StatusUnauthorized)
return
}
next.ServeHTTP(w, r)
})
})
// 最终处理程序
middle.UseHandler(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.Write([]byte("Authenticated content"))
}))
http.ListenAndServe(":8080", middle)
}
2. 路由分组
Interpose支持路由分组,可以为不同的路由路径应用不同的中间件:
func main() {
middle := interpose.New()
// 全局中间件
middle.Use(func(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.Header().Set("X-Frame-Options", "DENY")
next.ServeHTTP(w, r)
})
})
// API路由组
apiRouter := interpose.New()
apiRouter.Use(func(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "application/json")
next.ServeHTTP(w, r)
})
})
apiRouter.UseHandler(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.Write([]byte(`{"status":"ok"}`))
}))
// 将路由组挂载到特定路径
middle.UseHandler(http.StripPrefix("/api", apiRouter))
// 默认路由
middle.UseHandler(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.Write([]byte("Welcome to homepage"))
}))
http.ListenAndServe(":8080", middle)
}
3. 从第三方库导入中间件
Interpose兼容标准的http.Handler
接口,可以轻松集成其他中间件:
import (
"github.com/gorilla/handlers"
)
func main() {
middle := interpose.New()
// 使用gorilla/handlers的日志中间件
middle.UseHandler(handlers.LoggingHandler(os.Stdout, http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.Write([]byte("Hello with logging"))
})))
http.ListenAndServe(":8080", middle)
}
高级用法
1. 上下文传递
func main() {
middle := interpose.New()
// 中间件设置值
middle.Use(func(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
// 创建一个新的context
ctx := context.WithValue(r.Context(), "user", "admin")
next.ServeHTTP(w, r.WithContext(ctx))
})
})
// 处理程序读取值
middle.UseHandler(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
user := r.Context().Value("user").(string)
w.Write([]byte("Hello, " + user))
}))
http.ListenAndServe(":8080", middle)
}
2. 错误处理中间件
func main() {
middle := interpose.New()
// 错误处理中间件
middle.Use(func(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
defer func() {
if err := recover(); err != nil {
http.Error(w, "Internal Server Error", http.StatusInternalServerError)
log.Printf("Panic: %v", err)
}
}()
next.ServeHTTP(w, r)
})
})
// 可能panic的处理程序
middle.UseHandler(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
panic("something went wrong")
}))
http.ListenAndServe(":8080", middle)
}
总结
Interpose是一个简单而强大的中间件库,主要特点包括:
- 轻量级,API简洁
- 兼容标准
http.Handler
接口 - 支持中间件链式调用
- 支持路由分组
- 易于集成其他中间件
虽然Interpose不如一些更全面的框架(如Gin或Echo)功能丰富,但对于需要轻量级中间件解决方案的项目来说,它是一个很好的选择。