go-zero 单体应用实践(二)
中间件使用
在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 两个字段来进行业务处理结果描述
- 自定义错误 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 单体应用实践(二)相关推荐
- 软件工程专业(互联网应用开发与优化方向)软件工程实践二环节教学大纲
软件工程专业(互联网应用开发与优化方向)软件工程实践二环节教学大纲 培训课程 Phthon Web开发 实训公司 XXX 总周数 3周
- P4语言编程快速开始 实践二
参考:P4语言编程快速开始 上一篇系列博客:P4语言编程快速开始 实践二 Demo 2 本Demo所做的修改及实现的功能: 为simple_router添加一个计数器(counter),该计数器附加( ...
- ASP.NET MVC5 网站开发实践(二) Member区域 - 用户部分(2)用户登录、注销
上次实现了用户注册,这次来实现用户登录,用到IAuthenticationManager的SignOut.SignIn方法和基于声明的标识.最后修改用户注册代码实现注册成功后直接登录. 目录: ASP ...
- Asp.NetCore程序发布到CentOs(含安装部署netcore)--最佳实践(二)
原文:Asp.NetCore程序发布到CentOs(含安装部署netcore)--最佳实践(二) Asp.NetCore程序发布到CentOs(含安装部署netcore)--最佳实践(一) 接上一篇 ...
- Nginx反向代理与负载均衡应用实践(二)
Nginx反向代理与负载均衡应用实践(二) 链接:https://pan.baidu.com/s/1xB20bnuanh0Avs4kwRpSXQ 提取码:migq 复制这段内容后打开百度网盘手机App ...
- SOLR7实践(二)--DIH配置及使用
DIH配置及使用@SOLR7实践(二) DIH配置及使用 网上已经有很多相关文章了,但是实践中还是遇到了些问题,备忘一下. 一.配置solrconfig.xml 编辑/var/solr/data/ne ...
- Java内部类与异常类(上机实践二)
Java内部类与异常类(上机实践二) 实践一 内部购物卷 手机专卖店为了促销自己的产品,决定发行内部购物券,但其他商场不能发行该购物券.编写一个 MobileShop 类(模拟手机专卖店),该类中有一 ...
- 《Python网络爬虫从入门到实践 第2版》第15章 爬虫实践二:知乎Live
第15章 爬虫实践二:知乎Live 知乎是中文互联网一个非常大的知识社交平台.在知乎上,用户可以通过问答等交流方式获取知识.区别于百度知道等问答网站,知乎的回答往往非常深入,都是回答者精心写的,知乎上 ...
- Linux内核 实践二
实践二 内核模块编译 20135307 张嘉琪 一.实验原理 Linux模块是一些可以作为独立程序来编译的函数和数据类型的集合.之所以提供模块机制,是因为Linux本身是一个单内核.单内核由于所有内容 ...
- ROS理论与实践——二、ROS基础
ROS理论与实践--二.ROS基础 前言 一.创建工作空间 1 什么是工作空间 2 创建流程 二.创建功能包 1 创建命令 2 创建流程 三.ROS通信编程 1 话题编程 1.1 话题编程流程 1.2 ...
最新文章
- Rocksdb 通过posix_advise 让内核减少在page_cache的预读
- iOS15.4 来袭:新增“男妈妈”表情及口罩面容解锁、AirTags 反跟踪等新功能
- oracle+root+密码忘记,教您如何修复各种UNIX系统下root密码
- java徐仕锋_传智播客云计算开发 Hadopp视频教程 传智播客之javaEE + Hadoop...
- Gym 101775J Straight Master(差分数组)题解
- 设计模式-Factory Method Pattern
- java基础教程第三版耿祥义,后台开发JAVA岗
- python类型和格式_json数据格式和python中字典的数据类型
- Web开发小结 - 2
- pip指定源安装_几种python安装简单方法
- H5 FileReader对象
- I.MX6 android 禁止低电量自动关机
- x61 linux 驱动 无线网卡,联想thinkpadx61无线网卡驱动下载-联想x61无线网卡驱动 win7官方版 - 极光下载站...
- QQ输入法怎么设置快捷短语
- 读取金税盘、税控盘或税务Ukey基本信息
- 计算机视觉基础——3D空间坐标点的重建(三角测量)
- K_A07_003 基于 STM32等单片机驱动DRV8825模块按键控制步进电机正反转
- 学会区分 RNN 的 output 和 state
- NAT原理与NAT穿透
- 身份证里提取出生年月的方法(实用)
热门文章
- CSS中最合理ID/CLASS的命名规范 —— 绯色的css 系列
- torch(七)、Math operations(2)
- 《那些年啊,那些事——一个程序员的奋斗史》——75
- docker -用-v方式创建容器数据卷
- 奢侈时装,不再迷信千禧一代
- 全球与中国用于AR-MR的高折射率玻璃基板市场运营模式与投资战略规划研究报告2022-2028年
- mysql 正则去小数位_mysql必知必会--用正则表达式 进行搜索
- Zotero | Zotero translator插件更新 | 解决百度学术文献无法获取问题
- vue里面怎么实现页面跳转_vue.js怎样做跳转页面?
- SVG滤镜、阴影、渐变