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

五、参考文件

相关推荐
blammmp6 分钟前
Java:数据结构-枚举
java·开发语言·数据结构
何曾参静谧19 分钟前
「C/C++」C/C++ 指针篇 之 指针运算
c语言·开发语言·c++
暗黑起源喵24 分钟前
设计模式-工厂设计模式
java·开发语言·设计模式
WaaTong29 分钟前
Java反射
java·开发语言·反射
Troc_wangpeng30 分钟前
R language 关于二维平面直角坐标系的制作
开发语言·机器学习
努力的家伙是不讨厌的32 分钟前
解析json导出csv或者直接入库
开发语言·python·json
Envyᥫᩣ1 小时前
C#语言:从入门到精通
开发语言·c#
newxtc1 小时前
【国内中间件厂商排名及四大中间件对比分析】
安全·web安全·网络安全·中间件·行为验证·国产中间件
Wlq04151 小时前
middleware中间件概述
中间件
Thuni_soft1 小时前
华宇TAS应用中间件入围鲲鹏应用创新大赛2024全国总决赛
中间件