go-zero中间件的使用

一、自定义中间件

  • 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"))
      

五、参考文件

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

水痕01

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值