golang工程——gRpc 拦截器及原理
oauth2认证与拦截器
类似java spring中的拦截器。gRpc也有拦截器的说法,拦截器可作用于客户端请求,服务端请求。对请求进行拦截,进行业务上的一些封装校验等,类似一个中间件的作用
拦截器类型
- 一元请求拦截器
- 流式请求拦截器
- 链式拦截器(一个个调用对应处理函数)
使用场景:
拦截器可以从元数据获取一些认证进行进行校验。
服务端拦截器
拦截器定义
interceptor.go
package serverimport ("context""errors""fmt""google.golang.org/grpc""google.golang.org/grpc/metadata""strings"
)// UnaryInterceptor 一元请求拦截器
func UnaryInterceptor(ctx context.Context, req interface{}, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (resp interface{}, err error) {fmt.Println("server UnaryInterceptor:", info)if err := oauth2Valid(ctx); err != nil {return nil, err}return handler(ctx, req)
}// StreamInterceptor 流式拦截器
func StreamInterceptor(srv interface{}, ss grpc.ServerStream, info *grpc.StreamServerInfo, handler grpc.StreamHandler) error {fmt.Println("server StreamInterceptor")fmt.Println(info)if err := oauth2Valid(ss.Context()); err != nil {return err}return handler(srv, ss)
}// oauth2认证,从上下文获取请求元数据
func oauth2Valid(ctx context.Context) error {md, ok := metadata.FromIncomingContext(ctx)if !ok {return errors.New("元数据获取失败, 身份认证失败")}authorization := md["authorization"]if !valid(authorization) {return errors.New("令牌校验不通过, 身份认证失败")}return nil
}func valid(authorization []string) bool {if len(authorization) < 1 {return false}token := strings.TrimPrefix(authorization[0], "Bearer ")return token == fetchToken()
}func fetchToken() string {return "some-secret-token"
}
拦截器配置
package mainimport ("flag""fmt""google.golang.org/grpc""grpc/echo""grpc/echo-server-practice/server""log""net"
)var (port = flag.Int("port", 50053, "port")
)func getOptions() (opts []grpc.ServerOption) {opts = make([]grpc.ServerOption, 0)opts = append(opts, server.GetMTlsOpt())// 附加一个拦截器,还有链式拦截器 ChainInterceptoropts = append(opts, grpc.UnaryInterceptor(server.UnaryInterceptor))opts = append(opts, grpc.StreamInterceptor(server.StreamInterceptor))return opts
}func main() {flag.Parse()lis, err := net.Listen("tcp", fmt.Sprintf(":%d", *port))if err != nil {log.Fatal(err)}// grpc servers := grpc.NewServer(getOptions()...)......
}
客户端拦截器
客户端拦截器中简单实现利用oauth2做认证
package clientimport ("fmt""golang.org/x/net/context""google.golang.org/grpc""grpc/echo-client/client"
)// UnaryInterceptor 客户端一元请求拦截器func UnaryInterceptor(ctx context.Context, method string, req, reply interface{}, cc *grpc.ClientConn, invoker grpc.UnaryInvoker, opts ...grpc.CallOption) error {fmt.Println("server UnaryInterceptor: ", req)// 其实就proto生成的一元请求里的invoke差不多return invoker(ctx, method, req, reply, cc, opts...)
}
// StreamInterceptor 客户端流式拦截器
func StreamInterceptor(ctx context.Context, desc *grpc.StreamDesc, cc *grpc.ClientConn, method string, streamer grpc.Streamer, opts ...grpc.CallOption) (grpc.ClientStream, error) {fmt.Println("client streamInterceptor")// 和流式请求里的NewStream也是一样的return streamer(ctx, desc, cc, method, opts...)
}
如果客户端启动没配置,可以在拦截器中添加。
客户端 main.go
package mainimport ("flag""google.golang.org/grpc""grpc/echo""grpc/echo-client-practice/client""log"
)var (addr = flag.String("host", "localhost:50053", "")
)func getDiaOption() []grpc.DialOption {dialOptions := make([]grpc.DialOption, 0)dialOptions = append(dialOptions, client.GetMTlsOpt())dialOptions = append(dialOptions, grpc.WithUnaryInterceptor(client.UnaryInterceptor))dialOptions = append(dialOptions, grpc.WithStreamInterceptor(client.StreamInterceptor))dialOptions = append(dialOptions, client.GetAuth(client.FetchToken()))return dialOptions
}func main() {flag.Parse()conn, err := grpc.Dial(*addr, getDiaOption()...)if err != nil {log.Fatal(err)}defer conn.Close()# 下面是伪代码c := echo.NewYourClient(conn)c.CallYourRpc(your_request)
}
链式拦截器执行核心原理
func ChainUnaryClient(interceptors ...grpc.UnaryClientInterceptor) grpc.UnaryClientInterceptor {n := len(interceptors)if n > 1 {lastI := n - 1return func(ctx context.Context, method string, req, reply interface{}, cc *grpc.ClientConn, invoker grpc.UnaryInvoker, opts ...grpc.CallOption) error {var (chainHandler grpc.UnaryInvokercurI int)chainHandler = func(currentCtx context.Context, currentMethod string, currentReq, currentRepl interface{}, currentConn *grpc.ClientConn, currentOpts ...grpc.CallOption) error {if curI == lastI {return invoker(currentCtx, currentMethod, currentReq, currentRepl, currentConn, currentOpts...)}curI++err := interceptors[curI](currentCtx, currentMethod, currentReq, currentRepl, currentConn, chainHandler, currentOpts...)curI--return err}return interceptors[0](ctx, method, req, reply, cc, chainHandler, opts...)}}...
}
当拦截器数量大于 1 时,从 interceptors[1]
开始递归,每一个递归的拦截器 interceptors[i]
会不断地执行,最后才真正的去执行 handler
方法。
相关文章:
golang工程——gRpc 拦截器及原理
oauth2认证与拦截器 类似java spring中的拦截器。gRpc也有拦截器的说法,拦截器可作用于客户端请求,服务端请求。对请求进行拦截,进行业务上的一些封装校验等,类似一个中间件的作用 拦截器类型 一元请求拦截器流式请求拦截器链式…...

Python接口自动化之unittest单元测试
以下主要介绍unittest特性、运行流程及实际案例。 一、单元测试三连问 1、什么是单元测试? 按照阶段来分,一般就是单元测试,集成测试,系统测试,验收测试。单元测试是对单个模块、单个类或者单个函数进行测试。 将访…...

在亚马逊云科技Amazon SageMaker上部署构建聊天机器人的开源大语言模型
开源大型语言模型(LLM)已经变得流行起来,研究人员、开发人员和组织都可以使用这些模型来促进创新和实验。这促进了开源社区开展合作,从而为LLM的开发和改进做出贡献。开源LLM提供了模型架构、训练过程和训练数据的透明度ÿ…...

【51单片机】10-蜂鸣器
1.蜂鸣器的原理 这里的“源”不是指电源。而是指震荡源。 也就是说,有源蜂鸣器内部带震荡源,所以只要一通电就会叫。 而无源内部不带震荡源,所以如果用直流信号无法令其鸣叫。必须用2K~5K的方波去驱动它。 有源蜂鸣器往往比无源的贵ÿ…...

26377-2010 逆反射测量仪 知识梳理
声明 本文是学习GB-T 26377-2010 逆反射测量仪. 而整理的学习笔记,分享出来希望更多人受益,如果存在侵权请及时联系我们 1 范围 本标准规定了逆反射测量仪的术语和定义、结构与分类、技术要求、计量学特性、试验方法、检验规 则以及标志、包装、运输与贮存。 本标准适用于…...

css实现渐变电量效果柱状图
我们通常的做法就是用echarts来实现 比如 echarts象形柱图实现电量效果柱状图 接着我们实现进阶版,增加渐变效果 echarts分割柱形图实现渐变电量效果柱状图 接着是又在渐变的基础上,增加了背景色块的填充 echarts实现渐变电量效果柱状图 其实思路是一…...

FileManager/本地文件增删改查, Cache/图像缓存处理 的操作
1. FileManager 本地文件管理器,增删改查文件 1.1 实现 // 本地文件管理器 class LocalFileManager{// 单例模式static let instance LocalFileManager()let folderName "MyApp_Images"init() {createFolderIfNeeded()}// 创建特定应用的文件夹func cr…...
vue中使用富文本编辑器
vue中使用富文本编辑器(wangEditor) wangEditor官网地址:https://www.wangeditor.com/ 使用示例 <template><div class"app-container"><div class"box"><div class"editor-tool">&l…...

13.(开发工具篇github)如何在GitHub上上传本地项目
一:创建GitHub账户并安装Git 二:创建一个新的仓库(repository) 三、拉取代码 git clone https://github.com/ainier-max/myboot.git git clone git@github.com:ainier-max/myboot.git四、拷贝代码到拉取后的工程 五、上传代码 (1)添加所有文件到暂存...

vue3中状态适配
写一个函数,在函数中定义一个对象 用于存放键值对,最后返回指定状态所对应的的值,即对象[指定状态] 的 对象的值。 在模板中把状态传入 // vue3 setup语法糖中 const formatXXXState (xxxState)>{const stateMap {键1: 值1,键2: 值2,.…...

uniapp h5 端 router.base设置history后仍有#号
manifest.json文件设置: "h5": { "router": { "base": "./", "mode": "history" }, }按相对路径发行时路由模式强制为hash模式,不支持history模式(两者相悖)…...

上网行为监管软件(上网行为管理软件通常具有哪些功能)
在我们的日常生活中,互联网已经成为了我们获取信息、交流思想、进行工作和娱乐的重要平台。然而,随着互联网的普及和使用,网络安全问题也日益突出,尤其是个人隐私保护和网络行为的规范。在这个背景下,上网行为审计软件…...

C#中的for和foreach的探究与学习
一:语句及表示方法 for语句: for(初始表达式;条件表达式;增量表达式) {循环体 }foreach语句: foreach(数据类型 变量 in 数组或集合) {循环体 }理解 1.从程序逻辑上理解,foreach是通过指针偏移实现的(最初在-1位置,每循环一次,指针就便宜一个单位),而for循环是通...

【ES6知识】Promise 对象
文章目录 1.1 概述1.2 静态方法1.3 实例方法1.4 Promise 拒绝事件 1.1 概述 Promise 对象用于表示一个异步操作的最终完成(或失败)及其结果值。是异步编程的一种解决方案(可以解决回调地狱问题)。 一个 Promise 对象代表一个在这…...
【Git】配置SSH密钥实现Git操作免密
背景 在使用Git推送代码的时候,会默认需要输入密码。如果经常推送代码,那就需要经常输入密码,比较繁琐。所以Git也提供了免密登录的功能。 Git本身支持两种协议对远程Git仓库进行访问:HTTPS、SSH。两种方式有一定的区别…...
AI能给百融云带来什么?
一大堆有关ChatGPT的利好消息出现之后,市场的反应难得的跟投资者预期站在了一起,AIGC也终于有了跑赢CPO的苗头。二级市场的逻辑不用重复,毕竟AI已经炒了大半年,但有没有发现一个问题?就是在不知不觉中,AI应…...

AI创作系统ChatGPT商业运营版源码+AI绘画/支持GPT联网提问/支持Midjourney绘画+Prompt应用+支持国内AI提问模型
一、AI创作系统 SparkAi创作系统是基于国外很火的ChatGPT进行开发的Ai智能问答系统。本期针对源码系统整体测试下来非常完美,可以说SparkAi是目前国内一款的ChatGPT对接OpenAI软件系统。那么如何搭建部署AI创作ChatGPT?小编这里写一个详细图文教程吧&am…...

vue.draggable拖拽,项目中三个表格互相拖拽的实例操作,前端分页等更多小技巧~
vue.draggable中文文档 - itxst.com官网在这里,感兴趣的小伙伴可以看看。 NPM或yarn安装方式 yarn add vuedraggable npm i -S vuedraggable UMD浏览器直接引用JS方式 <script src"https://www.itxst.com/package/vue/vue.min.js"></script&…...

400G DR4 QSFP-DD光模块:数据中心应用全攻略
在当今数字化时代,对于企业和供应商来说,高速数据传输至关重要。随着对更快数据传输的需求不断攀升,400G DR4 QSFP-DD光模块已经成为高速网络的最新解决方案。本文将全面介绍400G DR4 QSFP-DD光模块在数据中心应用中的优势和技术规范。 什么…...
自动驾驶:路径规划概述
自动驾驶:路径规划概述 全局路径规划Dijkstra算法A*算法RRT(随机快速探索树)算法PRM(概率路线图)算法 局部路径规划DWA(动态窗口法)算法TEB(时间弹性带)算法Lattice Plan…...

Flask RESTful 示例
目录 1. 环境准备2. 安装依赖3. 修改main.py4. 运行应用5. API使用示例获取所有任务获取单个任务创建新任务更新任务删除任务 中文乱码问题: 下面创建一个简单的Flask RESTful API示例。首先,我们需要创建环境,安装必要的依赖,然后…...
反向工程与模型迁移:打造未来商品详情API的可持续创新体系
在电商行业蓬勃发展的当下,商品详情API作为连接电商平台与开发者、商家及用户的关键纽带,其重要性日益凸显。传统商品详情API主要聚焦于商品基本信息(如名称、价格、库存等)的获取与展示,已难以满足市场对个性化、智能…...

LeetCode - 394. 字符串解码
题目 394. 字符串解码 - 力扣(LeetCode) 思路 使用两个栈:一个存储重复次数,一个存储字符串 遍历输入字符串: 数字处理:遇到数字时,累积计算重复次数左括号处理:保存当前状态&a…...
生成 Git SSH 证书
🔑 1. 生成 SSH 密钥对 在终端(Windows 使用 Git Bash,Mac/Linux 使用 Terminal)执行命令: ssh-keygen -t rsa -b 4096 -C "your_emailexample.com" 参数说明: -t rsa&#x…...
【HTML-16】深入理解HTML中的块元素与行内元素
HTML元素根据其显示特性可以分为两大类:块元素(Block-level Elements)和行内元素(Inline Elements)。理解这两者的区别对于构建良好的网页布局至关重要。本文将全面解析这两种元素的特性、区别以及实际应用场景。 1. 块元素(Block-level Elements) 1.1 基本特性 …...

EtherNet/IP转DeviceNet协议网关详解
一,设备主要功能 疆鸿智能JH-DVN-EIP本产品是自主研发的一款EtherNet/IP从站功能的通讯网关。该产品主要功能是连接DeviceNet总线和EtherNet/IP网络,本网关连接到EtherNet/IP总线中做为从站使用,连接到DeviceNet总线中做为从站使用。 在自动…...
Angular微前端架构:Module Federation + ngx-build-plus (Webpack)
以下是一个完整的 Angular 微前端示例,其中使用的是 Module Federation 和 npx-build-plus 实现了主应用(Shell)与子应用(Remote)的集成。 🛠️ 项目结构 angular-mf/ ├── shell-app/ # 主应用&…...

浪潮交换机配置track检测实现高速公路收费网络主备切换NQA
浪潮交换机track配置 项目背景高速网络拓扑网络情况分析通信线路收费网络路由 收费汇聚交换机相应配置收费汇聚track配置 项目背景 在实施省内一条高速公路时遇到的需求,本次涉及的主要是收费汇聚交换机的配置,浪潮网络设备在高速项目很少,通…...

RabbitMQ入门4.1.0版本(基于java、SpringBoot操作)
RabbitMQ 一、RabbitMQ概述 RabbitMQ RabbitMQ最初由LShift和CohesiveFT于2007年开发,后来由Pivotal Software Inc.(现为VMware子公司)接管。RabbitMQ 是一个开源的消息代理和队列服务器,用 Erlang 语言编写。广泛应用于各种分布…...

Python 实现 Web 静态服务器(HTTP 协议)
目录 一、在本地启动 HTTP 服务器1. Windows 下安装 node.js1)下载安装包2)配置环境变量3)安装镜像4)node.js 的常用命令 2. 安装 http-server 服务3. 使用 http-server 开启服务1)使用 http-server2)详解 …...