go-zero中间件的使用

一、自定义中间件

  • 1、在api中在服务中定义一个中间件,名字随便取

    properties 复制代码
    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、使用命令生成文件

    properties 复制代码
    goctl api go -api *.api -dir . --style=gozero
  • 3、查看路由中是否使用了中间件,还生成了中间件文件

  • 4、在中间件中补充内容

    go 复制代码
    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、自定义中间件

    go 复制代码
    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、在启动文件中加入自定义中间件

    go 复制代码
    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、创建中间件

    go 复制代码
    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、使用中间件

    go 复制代码
    // 全局中间件
    server.Use(middleware.LogMiddleware)
    server.Use(middleware.CorsMiddleware)

四、自定义Auth鉴权中间件

  • 1、这里不使用jwt的方式,采用登录后自己根据规则生成唯一识别的存到redis中,jwt的方式可以自己网上搜索

  • 2、项目中安装redis

    properties 复制代码
    github.com/go-redis/redis/v8
  • 3、配置文件中写上配置

    yaml 复制代码
    Name: demo-api
    Host: 0.0.0.0
    Port: 8888
    
    # redis配置
    RedisConfig:
      Host: localhost
      Port: 6379
      Pass: ""
      Tls: false
  • 4、配置文件中添加配置

    go 复制代码
    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的文件

    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

    go 复制代码
    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、中间件中修改

    go 复制代码
    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

      go 复制代码
      fmt.Println("获取请求头传递的数据", r.Context().Value("accountId"))
      fmt.Println("获取请求头传递的数据", r.Context().Value("username"))
    • logic

      go 复制代码
      fmt.Println("获取请求头传递的数据1", l.ctx.Value("accountId"))
      fmt.Println("获取请求头传递的数据2", l.ctx.Value("username"))

五、参考文件

相关推荐
Scott9999HH6 小时前
【IIoT流量实战】蒸汽管道阀门全关却仍有流量?用 Python 实现涡街信号 FFT 频谱分析与温压全补偿积算网关,深度拆解靠谱的涡街流量计厂家硬核技术标准
开发语言·python
码智社7 小时前
AES加密原理详解及Java实现加解密实战
java·开发语言
AI云海7 小时前
python 列表、元组、集合和字典
开发语言·python
萧瑟余晖8 小时前
JDK 26 新特性详解
java·开发语言
马优晨9 小时前
Freemarker 完整讲解(后端 Java 模板引擎)
java·开发语言·freemarker·freemarker 完整讲解·freemarker模板引擎
人邮异步社区10 小时前
怎么把C语言学到精通?
c语言·开发语言
心平气和量大福大11 小时前
C#-WPF-控件-TextBox 数据绑定
开发语言·c#·wpf
ttwuai11 小时前
Cursor 生成 CRUD 后,Go 后台接口别只测 200:JWT、RBAC 和 tenant_id 怎么验
开发语言·后端·golang
এ慕ོ冬℘゜11 小时前
前端基础:什么是时间戳?JS获取时间戳三种方法与实战用途
开发语言·前端·javascript
执明wa12 小时前
LayoutInflater详解: XML是如何变成View的?
android·xml·开发语言·android studio