中间件使用

在go-zero中,中间件可以分为路由中间件和全局中间件,路由中间件是指某一些特定路由需要实现中间件逻辑,其和jwt类似,没有放在jwt:xxx下的路由不会使用中间件功能, 而全局中间件的服务范围则是整个服务。

路由中间件

1、编辑 api 文件 userlogin/userlogin.api 生命接口需要添加的中间件,多个中间件用逗号分隔

@server(middleware : Tagging,Version
)
service userlogin-api {@handler Tagsget /api/tags returns (TagResponse)
}

2、goctl api 命令重新执行 生成middleware 文件

  • userlogin/internal/middleware/taggingmiddleware.go
  • userlogin/internal/middleware/versionmiddleware.go

可以看到路由文件中userlogin/internal/handler/routes.go 新增了一下代码

server.AddRoutes(rest.WithMiddlewares([]rest.Middleware{serverCtx.Tagging, serverCtx.Version},[]rest.Route{{Method:  http.MethodGet,Path:    "/api/tags",Handler: TagsHandler(serverCtx),},}...,),)

3、 文件中添加中间件依赖 userlogin/internal/svc/servicecontext.go

type ServiceContext struct {Config    config.ConfigTagging   rest.MiddlewareVersion   rest.MiddlewareUserModel user.UserModel
}func NewServiceContext(c config.Config) *ServiceContext {conn := sqlx.NewMysql(c.Mysql.DataSource)return &ServiceContext{Config:    c,UserModel: user.NewUserModel(conn, c.CacheRedis),Tagging:   middleware.NewTaggingMiddleware().Handle,Version:   middleware.NewVersionMiddleware().Handle,}
}

4、启动测试

http://127.0.0.1:8000/api/tags
{ “tag”: “tagV111–v1.1.0” }

全局中间件

userlogin/userlogin.go

flag.Parse()var c config.Configconf.MustLoad(*configFile, &c)logx.MustSetup(c.LogConf)server := rest.MustNewServer(c.RestConf)defer server.Stop()// 全局中间件server.Use(func(next http.HandlerFunc) http.HandlerFunc {return func(writer http.ResponseWriter, request *http.Request) {logx.Info("global middleware")next(writer, request)}})ctx := svc.NewServiceContext(c)handler.RegisterHandlers(server, ctx)fmt.Printf("Starting server at %s:%d...\n", c.Host, c.Port)server.Start()

链路追踪

go-zero 框架已实现了链路追踪,并且Jaeger, Zipkin 这两种链路追踪上报工具,只要简单配置就实现链路追踪。

1、编辑配置文件 增加jaeger配置

Telemetry:Name: user.apiEndpoint: http://jaeger:14268/api/tracesSampler: 1.0Batcher: jaeger

2、userlogin/internal/config/config.go 增加相应的映射

type Config struct {Telemetry trace.Config
}

3、启动测试
访问 jaeger UI界面 http://127.0.0.1:5000/search

错误处理

在业务中还会定义一些业务性错误,常用做法都是通过 code、msg 两个字段来进行业务处理结果描述

  1. 自定义错误 userlogin/common/errorx/baseerror.go
package errorxconst defaultCode = 1001
const DBErrorCode = 5001type CodeError struct {Code int    `json:"code"`Msg  string `json:"msg"`
}type CodeErrorResponse struct {Code int    `json:"code"`Msg  string `json:"msg"`
}func NewCodeError(code int, msg string) error {return &CodeError{Code: code, Msg: msg}
}func NewDefaultError(msg string) error {return NewCodeError(defaultCode, msg)
}func (e *CodeError) Error() string {return e.Msg
}func (e *CodeError) Data() *CodeErrorResponse {return &CodeErrorResponse{Code: e.Code,Msg:  e.Msg,}
}

2、业务逻辑代码中替换为自定义错误 userlogin/internal/logic/loginlogic.go

if err != nil {if err == user.ErrNotFound {return nil, errorx.NewDefaultError("用户不存在")}return nil, errorx.NewCodeError(errorx.DBErrorCode, err.Error())}

3、开启自定义错误 userlogin/userlogin.go

httpx.SetErrorHandler(func(err error) (int, interface{}) {switch e := err.(type) {case *errorx.CodeError:return http.StatusOK, e.Data()default:return http.StatusInternalServerError, nil}})

4、启动测试

#  curl -i -X POST http://127.0.0.1:8000/api/login -H 'Content-Type: application/json' -d '{"email":"notfound@gmail.com","password":"****"}'
HTTP/1.1 200 OK
Content-Type: application/json; charset=utf-8
Traceparent: 00-d004fc85afc1bcb7f4cf6218de12e518-5eed79e06803e434-01
Date: Mon, 25 Jul 2022 14:07:02 GMT
Content-Length: 37{"code":1001,"msg":"用户不存在"}

自定义认证错误

curl -i -X GET 'http://127.0.0.1:8000/api/userinfo’

HTTP/1.1 401 Unauthorized
Traceparent: 00-f1a3a6dee278d0aa8604c5eab2c276a3-f4a8de7774b93cf4-01
Date: Mon, 25 Jul 2022 14:11:32 GMT
Content-Length: 0

修改代码 userlogin/userlogin.go

unauthorized := rest.WithUnauthorizedCallback(func(w http.ResponseWriter, r *http.Request, err error) {httpx.WriteJson(w, http.StatusOK, errorx.NewCodeError(http.StatusUnauthorized, err.Error()))})server := rest.MustNewServer(c.RestConf, unauthorized)

测试

HTTP/1.1 200 OK
Content-Type: application/json; charset=utf-8
Traceparent: 00-f136c8b772b717f394871d447c2ad0af-400e2c6cd45ab383-01
Date: Mon, 25 Jul 2022 14:09:46 GMT
Content-Length: 48{"code":401,"msg":"no token present in request"}

go-zero 单体应用实践(二)相关推荐

  1. 软件工程专业(互联网应用开发与优化方向)软件工程实践二环节教学大纲

    软件工程专业(互联网应用开发与优化方向)软件工程实践二环节教学大纲 培训课程 Phthon Web开发 实训公司 XXX 总周数 3周

  2. P4语言编程快速开始 实践二

    参考:P4语言编程快速开始 上一篇系列博客:P4语言编程快速开始 实践二 Demo 2 本Demo所做的修改及实现的功能: 为simple_router添加一个计数器(counter),该计数器附加( ...

  3. ASP.NET MVC5 网站开发实践(二) Member区域 - 用户部分(2)用户登录、注销

    上次实现了用户注册,这次来实现用户登录,用到IAuthenticationManager的SignOut.SignIn方法和基于声明的标识.最后修改用户注册代码实现注册成功后直接登录. 目录: ASP ...

  4. Asp.NetCore程序发布到CentOs(含安装部署netcore)--最佳实践(二)

    原文:Asp.NetCore程序发布到CentOs(含安装部署netcore)--最佳实践(二) Asp.NetCore程序发布到CentOs(含安装部署netcore)--最佳实践(一) 接上一篇 ...

  5. Nginx反向代理与负载均衡应用实践(二)

    Nginx反向代理与负载均衡应用实践(二) 链接:https://pan.baidu.com/s/1xB20bnuanh0Avs4kwRpSXQ 提取码:migq 复制这段内容后打开百度网盘手机App ...

  6. SOLR7实践(二)--DIH配置及使用

    DIH配置及使用@SOLR7实践(二) DIH配置及使用 网上已经有很多相关文章了,但是实践中还是遇到了些问题,备忘一下. 一.配置solrconfig.xml 编辑/var/solr/data/ne ...

  7. Java内部类与异常类(上机实践二)

    Java内部类与异常类(上机实践二) 实践一 内部购物卷 手机专卖店为了促销自己的产品,决定发行内部购物券,但其他商场不能发行该购物券.编写一个 MobileShop 类(模拟手机专卖店),该类中有一 ...

  8. 《Python网络爬虫从入门到实践 第2版》第15章 爬虫实践二:知乎Live

    第15章 爬虫实践二:知乎Live 知乎是中文互联网一个非常大的知识社交平台.在知乎上,用户可以通过问答等交流方式获取知识.区别于百度知道等问答网站,知乎的回答往往非常深入,都是回答者精心写的,知乎上 ...

  9. Linux内核 实践二

    实践二 内核模块编译 20135307 张嘉琪 一.实验原理 Linux模块是一些可以作为独立程序来编译的函数和数据类型的集合.之所以提供模块机制,是因为Linux本身是一个单内核.单内核由于所有内容 ...

  10. ROS理论与实践——二、ROS基础

    ROS理论与实践--二.ROS基础 前言 一.创建工作空间 1 什么是工作空间 2 创建流程 二.创建功能包 1 创建命令 2 创建流程 三.ROS通信编程 1 话题编程 1.1 话题编程流程 1.2 ...

最新文章

  1. Rocksdb 通过posix_advise 让内核减少在page_cache的预读
  2. iOS15.4 来袭:新增“男妈妈”表情及口罩面容解锁、AirTags 反跟踪等新功能
  3. oracle+root+密码忘记,教您如何修复各种UNIX系统下root密码
  4. java徐仕锋_传智播客云计算开发 Hadopp视频教程 传智播客之javaEE + Hadoop...
  5. Gym 101775J Straight Master(差分数组)题解
  6. 设计模式-Factory Method Pattern
  7. java基础教程第三版耿祥义,后台开发JAVA岗
  8. python类型和格式_json数据格式和python中字典的数据类型
  9. Web开发小结 - 2
  10. pip指定源安装_几种python安装简单方法
  11. H5 FileReader对象
  12. I.MX6 android 禁止低电量自动关机
  13. x61 linux 驱动 无线网卡,联想thinkpadx61无线网卡驱动下载-联想x61无线网卡驱动 win7官方版 - 极光下载站...
  14. QQ输入法怎么设置快捷短语
  15. 读取金税盘、税控盘或税务Ukey基本信息
  16. 计算机视觉基础——3D空间坐标点的重建(三角测量)
  17. K_A07_003 基于 STM32等单片机驱动DRV8825模块按键控制步进电机正反转
  18. 学会区分 RNN 的 output 和 state
  19. NAT原理与NAT穿透
  20. 身份证里提取出生年月的方法(实用)

热门文章

  1. CSS中最合理ID/CLASS的命名规范 —— 绯色的css 系列
  2. torch(七)、Math operations(2)
  3. 《那些年啊,那些事——一个程序员的奋斗史》——75
  4. docker -用-v方式创建容器数据卷
  5. 奢侈时装,不再迷信千禧一代
  6. 全球与中国用于AR-MR的高折射率玻璃基板市场运营模式与投资战略规划研究报告2022-2028年
  7. mysql 正则去小数位_mysql必知必会--用正则表达式 进行搜索
  8. Zotero | Zotero translator插件更新 | 解决百度学术文献无法获取问题
  9. vue里面怎么实现页面跳转_vue.js怎样做跳转页面?
  10. SVG滤镜、阴影、渐变