golang HTTP处理器链式包装插件库catena的使用
golang HTTP处理器链式包装插件库catena的使用
简介
catena是一个用于gRPC拦截器链式包装的Go语言库,它可以帮助开发者更方便地管理和组合多个gRPC拦截器。
安装
使用以下命令安装catena库:
go get -u github.com/codemodus/catena
使用示例
下面是一个完整的示例,展示如何使用catena创建和管理gRPC拦截器链:
package main
import (
"context"
"log"
"net"
"github.com/codemodus/catena"
"google.golang.org/grpc"
)
// 示例gRPC服务
type server struct{}
// 示例gRPC方法
func (s *server) SayHello(ctx context.Context, req *HelloRequest) (*HelloReply, error) {
return &HelloReply{Message: "Hello " + req.Name}, nil
}
// 第一个拦截器
func interceptor1(ctx context.Context, req interface{}, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (resp interface{}, err error) {
log.Println("Interceptor 1 - before handler")
resp, err = handler(ctx, req)
log.Println("Interceptor 1 - after handler")
return resp, err
}
// 第二个拦截器
func interceptor2(ctx context.Context, req interface{}, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (resp interface{}, err error) {
log.Println("Interceptor 2 - before handler")
resp, err = handler(ctx, req)
log.Println("Interceptor 2 - after handler")
return resp, err
}
func main() {
// 创建拦截器链
chain := catena.NewUnaryServerCatena(interceptor1, interceptor2)
// 可以继续添加更多拦截器
chain.Append(
func(ctx context.Context, req interface{}, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (resp interface{}, err error) {
log.Println("Interceptor 3 - before handler")
resp, err = handler(ctx, req)
log.Println("Interceptor 3 - after handler")
return resp, err
},
)
// 创建gRPC服务器并应用拦截器链
s := grpc.NewServer(chain.ServerOption())
// 注册服务
RegisterGreeterServer(s, &server{})
// 启动服务器
lis, err := net.Listen("tcp", ":50051")
if err != nil {
log.Fatalf("failed to listen: %v", err)
}
if err := s.Serve(lis); err != nil {
log.Fatalf("failed to serve: %v", err)
}
}
主要功能
catena提供了以下主要功能:
type UnaryServerCatena
// 创建新的拦截器链
func NewUnaryServerCatena(is ...grpc.UnaryServerInterceptor) *UnaryServerCatena
// 向链中添加更多拦截器
func (c *UnaryServerCatena) Append(is ...grpc.UnaryServerInterceptor) *UnaryServerCatena
// 复制拦截器链
func (c *UnaryServerCatena) Copy(catena *UnaryServerCatena)
// 获取组合后的拦截器
func (c *UnaryServerCatena) Interceptor() grpc.UnaryServerInterceptor
// 合并多个拦截器链
func (c *UnaryServerCatena) Merge(cs ...*UnaryServerCatena) *UnaryServerCatena
// 获取gRPC服务器选项
func (c *UnaryServerCatena) ServerOption() grpc.ServerOption
更多信息
catena库主要用于简化gRPC拦截器的管理和组合,特别适合需要多个拦截器协同工作的场景。通过链式调用,可以更清晰地组织和维护拦截器逻辑。
更多关于golang HTTP处理器链式包装插件库catena的使用的实战教程也可以访问 https://www.itying.com/category-94-b0.html
1 回复
更多关于golang HTTP处理器链式包装插件库catena的使用的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html
Catena - Golang HTTP处理器链式包装插件库
Catena是一个轻量级的Go语言HTTP处理器链式包装库,它允许你以优雅的方式组合多个中间件和处理函数。下面我将详细介绍如何使用Catena。
安装
go get github.com/go-catena/catena
基本用法
package main
import (
"net/http"
"github.com/go-catena/catena"
)
func main() {
// 创建一个新的Catena链
chain := catena.New()
// 添加中间件和处理函数
chain.Use(loggerMiddleware)
chain.Use(authMiddleware)
chain.Handle("/", homeHandler)
// 启动HTTP服务器
http.ListenAndServe(":8080", chain)
}
func loggerMiddleware(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
// 记录请求信息
log.Printf("%s %s", r.Method, r.URL.Path)
// 调用下一个处理器
next.ServeHTTP(w, r)
})
}
func authMiddleware(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
// 简单的认证检查
if r.Header.Get("Authorization") != "valid-token" {
http.Error(w, "Unauthorized", http.StatusUnauthorized)
return
}
next.ServeHTTP(w, r)
})
}
func homeHandler(w http.ResponseWriter, r *http.Request) {
w.Write([]byte("Welcome to the home page!"))
}
高级特性
1. 分组路由
func main() {
chain := catena.New()
// 公共路由组
public := chain.Group()
public.Use(loggerMiddleware)
public.Handle("/", homeHandler)
// 私有路由组
private := chain.Group()
private.Use(authMiddleware)
private.Handle("/dashboard", dashboardHandler)
http.ListenAndServe(":8080", chain)
}
2. 条件中间件
func main() {
chain := catena.New()
// 只在特定路径上应用中间件
chain.UseIf(loggerMiddleware, func(r *http.Request) bool {
return r.URL.Path != "/health"
})
chain.Handle("/health", healthHandler)
chain.Handle("/", homeHandler)
http.ListenAndServe(":8080", chain)
}
3. 错误处理
func main() {
chain := catena.New()
// 添加错误处理中间件
chain.Use(errorHandlerMiddleware)
chain.Handle("/", func(w http.ResponseWriter, r *http.Request) {
// 模拟错误
panic("something went wrong")
})
http.ListenAndServe(":8080", chain)
}
func errorHandlerMiddleware(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
defer func() {
if err := recover(); err != nil {
// 处理panic
w.WriteHeader(http.StatusInternalServerError)
fmt.Fprintf(w, "Error: %v", err)
}
}()
next.ServeHTTP(w, r)
})
}
4. 自定义配置
func main() {
// 创建带有自定义配置的Catena实例
chain := catena.NewWithConfig(catena.Config{
Recover: true, // 自动恢复panic
LogRequests: true, // 记录请求日志
LogRecoveries: true, // 记录恢复的panic
})
chain.Handle("/", homeHandler)
http.ListenAndServe(":8080", chain)
}
最佳实践
-
中间件顺序:将全局中间件(如日志、恢复)放在前面,特定中间件(如认证)放在后面。
-
错误处理:使用专门的错误处理中间件捕获和处理错误。
-
性能考虑:避免在中间件中进行昂贵的操作,如频繁的数据库查询。
-
测试:为每个中间件编写单元测试,确保它们按预期工作。
// 测试示例
func TestAuthMiddleware(t *testing.T) {
req := httptest.NewRequest("GET", "/", nil)
rec := httptest.NewRecorder()
// 测试未授权请求
handler := authMiddleware(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
t.Error("Should not reach here")
}))
handler.ServeHTTP(rec, req)
if rec.Code != http.StatusUnauthorized {
t.Errorf("Expected status %d, got %d", http.StatusUnauthorized, rec.Code)
}
// 测试授权请求
req.Header.Set("Authorization", "valid-token")
rec = httptest.NewRecorder()
handler.ServeHTTP(rec, req)
if rec.Code != http.StatusOK {
t.Errorf("Expected status %d, got %d", http.StatusOK, rec.Code)
}
}
Catena提供了一种简洁而强大的方式来组织你的HTTP中间件和处理逻辑,使代码更易于维护和扩展。