Giter Site home page Giter Site logo

protoc-gen-go-kratos-selector's Introduction

安装

go install gitee.com/pengdacn/protoc-gen-go-kratos-selector@latest

使用

  1. 定义handler

    1. 创建定义handler的protobuf文件,如下

      // file: /api/middleware.proto
      
      syntax = "proto3";
      
      package api.middleware.v1;
      option go_package = "api/middleware/v1;v1";
      
      import "selector/selector.proto";
      
      option (selector.defined) = {
        name: "middleware"
        handlers: [
          {
            // 定义这个handle的名称,必须是唯一的,且符合golang变量命名规范
            id: "jwt"
            // 指定优先级,1优先级最高,2其次,以此类推,若优先级别相同,则按照字符串的比较规则,比较id
            // property不能小于0
            property: 1
          },
          {
            id: "privilege"
            property: 2
          }
        ]
      };
    2. 在需要使用选择器的地方引用middleware.proto中定义的id,如下

      // file: /api/user.proto
      
      
      syntax = "proto3";
      
      package api.user.v1;
      option go_package = "api/user/v1;v1";
      
      import "selector/selector.proto";
      import "google/api/annotations.proto";
      import "google/protobuf/empty.proto";
      
      service User {
        option (selector.select) = {
          // 代表使用的定义handler的proto文件位置,必填
          use: "api/middleware.proto"
          verbs: [
            {
              // verbs中的id必须是在use的proto中定义的,若没有定义,生成则会报错
              id: "jwt"
              // 通过select语法和在方法中定义的tag去选择在这个service中匹配的方法
              select: "!no-jwt"
            },
            {
              id: "privilege"
              select: "!no-privilege"
            }
          ]
        };
      
        rpc Add(google.protobuf.Empty) returns(google.protobuf.Empty) {
          option (google.api.http) = {
            post: "/api/v1/user"
            body: "*"
          };
        }
      
        rpc Update(google.protobuf.Empty) returns(google.protobuf.Empty) {
          option (google.api.http) = {
            put: "/api/v1/user/{id}"
            body: "*"
          };
        }
      
        rpc Remove(google.protobuf.Empty) returns(google.protobuf.Empty) {
          option (google.api.http) = {
            delete: "/api/v1/user/{id}"
          };
        }
      
        rpc List(google.protobuf.Empty) returns(google.protobuf.Empty) {
          option (google.api.http) = {
            get: "/api/v1/users"
          };
        }
      
        rpc Login(google.protobuf.Empty) returns(google.protobuf.Empty) {
          option (google.api.http) = {
            get: "/api/v1/users"
          };
      
          option (selector.tag) = {
            name: "no-jwt"
            additional: [
              "no-privilege"
            ]
          };
        }
      
        rpc GetSelf(google.protobuf.Empty) returns(google.protobuf.Empty) {
          option (google.api.http) = {
            get: "/api/v1/user/self"
          };
      
          option (selector.tag) = {
            name: "no-privilege"
          };
        }
      }

      在这个示例文件中,id为jwt的选择器会选择除了Login方法外的其他所有方法,id为privilege的会选择除了LoginGetSelf外的所有方法

    3. 使用protoc生成选择器代码

      protoc --proto_path=. \
          --proto_path=./third_party \
          --proto_path=./example \
          --go_out=paths=source_relative:. \
          --go-kratos-selector_out=paths=source_relative:. \
          ./example/api/middleware.proto ./example/api/user.proto

      --go-kratos-selector_out=paths=source_relative:. \就是生产选择器插件位置

      生成后代码如下

      // file: /api/middleware_selector.pb.go
      
      // Code generated by proto-gen-go-kratos-selector. DO NOT EDIT.
      // versions:
      // proto-gen-go-kratos-selector v1.0
      // url:
      // https://gitee.com/pengdacn/protoc-gen-go-kratos-selector
      
      package v1
      
      import (
      	context "context"
      	middleware "github.com/go-kratos/kratos/v2/middleware"
      	selector "github.com/go-kratos/kratos/v2/middleware/selector"
      )
      
      type standardSelectorMiddleware struct {
      	id_jwt                map[string]struct{}
      	middlewares_jwt       []middleware.Middleware
      	id_privilege          map[string]struct{}
      	middlewares_privilege []middleware.Middleware
      }
      
      type SelectorMiddleware interface {
      	Build() middleware.Middleware
      	Add_jwt(mlds ...middleware.Middleware)
      	Add_privilege(mlds ...middleware.Middleware)
      }
      
      var (
      	Selector_Jwt       = make(map[string]struct{})
      	Selector_Privilege = make(map[string]struct{})
      
      	_ SelectorMiddleware = (*standardSelectorMiddleware)(nil)
      )
      
      func init() {
      	Selector_Jwt[`/api.user.v1.User/Add`] = struct{}{}
      	Selector_Jwt[`/api.user.v1.User/GetSelf`] = struct{}{}
      	Selector_Jwt[`/api.user.v1.User/List`] = struct{}{}
      	Selector_Jwt[`/api.user.v1.User/Remove`] = struct{}{}
      	Selector_Jwt[`/api.user.v1.User/Update`] = struct{}{}
      	Selector_Privilege[`/api.user.v1.User/Add`] = struct{}{}
      	Selector_Privilege[`/api.user.v1.User/List`] = struct{}{}
      	Selector_Privilege[`/api.user.v1.User/Remove`] = struct{}{}
      	Selector_Privilege[`/api.user.v1.User/Update`] = struct{}{}
      }
      
      func NewSelectorMiddleware() SelectorMiddleware {
      	return &standardSelectorMiddleware{
      		id_jwt:       Selector_Jwt,
      		id_privilege: Selector_Privilege,
      	}
      }
      
      func (s *standardSelectorMiddleware) Build() middleware.Middleware {
      	var selectors []middleware.Middleware
      	selectors = append(
      		selectors,
      		selector.Server(
      			middleware.Chain(s.middlewares_jwt...),
      		).
      			Match(s.match_jwt()).
      			Build(),
      	)
      	selectors = append(
      		selectors,
      		selector.Server(
      			middleware.Chain(s.middlewares_privilege...),
      		).
      			Match(s.match_privilege()).
      			Build(),
      	)
      
      	return middleware.Chain(selectors...)
      }
      func (s *standardSelectorMiddleware) Add_jwt(mlds ...middleware.Middleware) {
      	if len(mlds) != 0 {
      		s.middlewares_jwt = append(s.middlewares_jwt, mlds...)
      	}
      }
      
      func (s *standardSelectorMiddleware) match_jwt() selector.MatchFunc {
      	return func(ctx context.Context, operation string) bool {
      		_, ok := Selector_Jwt[operation]
      
      		return ok
      	}
      }
      func (s *standardSelectorMiddleware) Add_privilege(mlds ...middleware.Middleware) {
      	if len(mlds) != 0 {
      		s.middlewares_privilege = append(s.middlewares_privilege, mlds...)
      	}
      }
      
      func (s *standardSelectorMiddleware) match_privilege() selector.MatchFunc {
      	return func(ctx context.Context, operation string) bool {
      		_, ok := Selector_Privilege[operation]
      
      		return ok
      	}
      }
    4. 在项目中使用

      1. 通过v1.NewSelectorMiddleware创建一个v1.SelectorMiddleware对象

      2. 添加中间键到选择其中

      3. 构建对象为kratos的中间件,并在http.Servergrpc.Server中使用

      http示例如下

      func NewHTTPServer(u *user.Server) http.Server {
          // 1.创建selector对象
          selectors := v1.NewSelectorMiddleware()
          // 2.将需要的中间件添加到handle中
          selectors.Add_jwt(newAuthJwt())
          selectors.Add_privilege(newAuthPrivilege())
          // 3. 构建中间件对象
          selectorMiddleware := selectors.Build()
          
          // 4. 使用
          ...
      }

select语法

  1. 完全匹配

    若有方法,AB

    func A tags: [a,b,c,d]
    func B tags: [e,a,f,g]
    

    选择器

    selector S1 select: a
    selector S2 select: g
    

    则选择器S1匹配AB,选择器S2匹配B

  2. 不能等于匹配

    语法:!+tag,如:!a,表示匹配除了atag外的所有方法,甚至方法没有tag也会匹配

  3. 全部匹配

    固定格式:$any,匹配所有方法,甚至方法没有tag也会匹配

       

protoc-gen-go-kratos-selector's People

Contributors

pengdacn avatar

Stargazers

 avatar 久爱吖 avatar

Watchers

 avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.