一、自定义中间件
-
1、在
api
中在服务中定义一个中间件,名字随便取type PostDemoReq { Name string `json:"name" validate:"required"` // 姓名 Age int64 `json:"age" validate:"required,gte=1,lte=130"` // 年龄 // optional 表示可选,omitempty如果为空的时候不走后面 Mobile string `json:"mobile,optional" validate:"omitempty,checkMobile"` // 手机号码 Email string `json:"email,optional" validate:"omitempty,checkEmail"` // 邮箱地址 Date string `json:"date" validate:"omitempty,checkDate,checkAfterDate"` // 时间 Password string `json:"password" validate:"required"` // 密码 ConfimPassword string `json:"confimPassword" validate:"eqfield=Password"` // 确认密码 } // 一般返回 type Response { Name string `json:"name"` Age int64 `json:"age"` } // 分页显示的 type UserPageResp { Data []Response `json:"data"` // 数据 Total int64 `json:"total"` // 总条数 PageSize int64 `json:"pageSize"` // 当前条数 PageNumber int64 `json:"pageNumber"` // 当前页数 } type GetUserPageReq { PageNumber int64 `query:"pageNumber"` PageSize int64 `query:"pageSize"` } @server ( prefix: demo/v1 group: demo middleware: AuthMiddleware ) service demo-api { @doc "添加" @handler PostDemoHandler post /postDemo (PostDemoReq) returns (Response) @doc "分页获取用户" @handler GetUserPageApi get /user/page (GetUserPageReq) returns (UserPageResp) }
-
2、使用命令生成文件
goctl api go -api *.api -dir . --style=gozero
-
3、查看路由中是否使用了中间件,还生成了中间件文件
-
4、在中间件中补充内容
package middleware import ( "github.com/zeromicro/go-zero/core/logx" "net/http" ) type AuthMiddleware struct { } func NewAuthMiddleware() *AuthMiddleware { return &AuthMiddleware{} } func (m *AuthMiddleware) Handle(next http.HandlerFunc) http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { logx.Info("请求之前") // 填充逻辑 next(w, r) logx.Info("请求之后") } }
-
5、请求日志输出
二、全局中间件
-
1、上面的方式只能在使用路由的时候才生效
-
2、在路由中取消中间件
-
3、自定义中间件
package middleware import ( "github.com/zeromicro/go-zero/core/logx" "net/http" ) func LogMiddleware(next http.HandlerFunc) http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { logx.Info("请求前...") next(w, r) logx.Info("请求后....") } }
-
4、在启动文件中加入自定义中间件
func main() { flag.Parse() var c config.Config conf.MustLoad(*configFile, &c) server := rest.MustNewServer(c.RestConf) defer server.Stop() ctx := svc.NewServiceContext(c) handler.RegisterHandlers(server, ctx) // 全局中间件 server.Use(middleware.LogMiddleware) fmt.Printf("Starting server at %s:%d...\n", c.Host, c.Port) server.Start() }
三、自定义跨域全局中间件
-
1、创建中间件
package middleware import ( "net/http" ) func CorsMiddleware(next http.HandlerFunc) http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { //指定允许其他域名访问 //ctx.Writer.Header().Set("Access-Control-Allow-Origin", "http://localhost:8080") w.Header().Set("Access-Control-Allow-Origin", "*") //跨域:CORS(跨来源资源共享)策略 //预检结果缓存时间 w.Header().Set("Access-Control-Max-Age", "86400") //允许的请求类型(GET,POST等) w.Header().Set("Access-Control-Allow-Methods", "*") //允许的请求头字段 w.Header().Set("Access-Control-Allow-Headers", "*") //是否允许后续请求携带认证信息(cookies),该值只能是true,否则不返回 w.Header().Set("Access-Control-Allow-Credentials", "true") if r.Method == http.MethodOptions { w.WriteHeader(http.StatusOK) return } next(w, r) } }
-
2、使用中间件
// 全局中间件 server.Use(middleware.LogMiddleware) server.Use(middleware.CorsMiddleware)
四、自定义Auth
鉴权中间件
-
1、这里不使用
jwt
的方式,采用登录后自己根据规则生成唯一识别的存到redis
中,jwt
的方式可以自己网上搜索 -
2、项目中安装
redis
github.com/go-redis/redis/v8
-
3、配置文件中写上配置
Name: demo-api Host: 0.0.0.0 Port: 8888 # redis配置 RedisConfig: Host: localhost Port: 6379 Pass: "" Tls: false
-
4、配置文件中添加配置
package config import "github.com/zeromicro/go-zero/rest" type Config struct { rest.RestConf // 使用redis RedisConfig struct { Host string Port int Pass string Tls bool } }
-
5、定义一个
redisDb.go
的文件package database import ( "fmt" "github.com/go-redis/redis/v8" ) func NewRedisDB(host, pass string, port int) *redis.Client { redisDb := redis.NewClient(&redis.Options{ Addr: fmt.Sprintf("%s:%d", host, port), Password: pass, DB: 0, }) return redisDb }
-
6、在
internal\svc\servicecontext.go
中注册redis
package svc import ( "github.com/go-redis/redis/v8" "github.com/zeromicro/go-zero/rest" "go_zero_demo06/internal/config" "go_zero_demo06/internal/database" "go_zero_demo06/internal/middleware" ) type ServiceContext struct { Config config.Config AuthMiddleware rest.Middleware RedisDb *redis.Client } func NewServiceContext(c config.Config) *ServiceContext { redisDb := database.NewRedisDB(c.RedisConfig.Host, c.RedisConfig.Pass, c.RedisConfig.Port) return &ServiceContext{ Config: c, AuthMiddleware: middleware.NewAuthMiddleware(redisDb).Handle, RedisDb: redisDb, } }
-
7、中间件中修改
package middleware import ( "context" "fmt" "github.com/go-redis/redis/v8" "net/http" ) type AuthMiddleware struct { RedisDb *redis.Client } func NewAuthMiddleware(redisDb *redis.Client) *AuthMiddleware { return &AuthMiddleware{ RedisDb: redisDb, } } func (m *AuthMiddleware) Handle(next http.HandlerFunc) http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { token := r.Header.Get("token") fmt.Println("请求的token", token) if token == "" { w.WriteHeader(http.StatusAccepted) w.Write([]byte("请登录")) return } get := m.RedisDb.Get(r.Context(), token) fmt.Println(get, "redis中读取的数据") // 下面的模拟将从token中读取到的数据塞到上下文中 ctx := context.WithValue(r.Context(), "accountId", "1") ctx = context.WithValue(ctx, "username", "admin") next(w, r.WithContext(ctx)) } }
-
8、请求结果
-
9、在别的地方读取上下文中传递的参数
-
在
handler
中fmt.Println("获取请求头传递的数据", r.Context().Value("accountId")) fmt.Println("获取请求头传递的数据", r.Context().Value("username"))
-
在
logic
中fmt.Println("获取请求头传递的数据1", l.ctx.Value("accountId")) fmt.Println("获取请求头传递的数据2", l.ctx.Value("username"))
-
五、参考文件
- 官方地址