建议和反馈

请填写你的反馈内容

Golang 之 中间件

2020-12-03 ·2659次阅读 ·读完需要2分钟



golang 中间件的实现本质:

写一个func,接受handler并且返回handler

把私货写在func里面,从而实现把你要写的操作执行了之后,再把原有的流程进行下去

 

一个好的中间件有一个责任就是可插拔并且自足。

 

 

例子:

package mainimport (	"fmt"	"github.com/devfeel/dotweb")func main() {	app := dotweb.New()	// App注册中间件	app.Use(NewSessionAuth())	// 开启SESSION	app.HttpServer.SetEnabledSession(true)	// 设置路由 输出字符串 Hello Dotweb	app.HttpServer.GET("/", func(ctx dotweb.Context) error {		method := ctx.Request().Method		return ctx.WriteString("Hello Dotweb\n" + "Method:" + method)	})	//开启服务 端口号	fmt.Println("dotweb.StartServer => 8080")	err := app.StartServer(8080)	fmt.Println("dotweb.StartServer error => ", err)}// SessionAuth 结构体type SessionAuth struct {	dotweb.BaseMiddlware}// Handle 处理程序func (m *SessionAuth) Handle(ctx dotweb.Context) error {	fmt.Println("SessionID = ", ctx.SessionID(), " RequestURI = ", ctx.Request().RequestURI)	return m.Next(ctx)}// NewSessionAuth Newfunc NewSessionAuth() *SessionAuth {	sAuth := new(SessionAuth)	return sAu}

 

Handle是什么时候被调用的?

 

我们看看BaseMiddlWare的源码:

// BaseMiddleware is the base struct, user defined middleware should extend thistype BaseMiddleware struct {next           MiddlewareexcludeRouters map[string]struct{}}func (bm *BaseMiddleware) SetNext(m Middleware) {bm.next = m}func (bm *BaseMiddleware) Next(ctx Context) error {httpCtx := ctx.(*HttpContext)if httpCtx.middlewareStep == "" {httpCtx.middlewareStep = middleware_App}if bm.next == nil {if httpCtx.middlewareStep == middleware_App {httpCtx.middlewareStep = middleware_Groupif len(httpCtx.RouterNode().GroupMiddlewares()) > 0 {return httpCtx.RouterNode().GroupMiddlewares()[0].Handle(ctx)}}if httpCtx.middlewareStep == middleware_Group {httpCtx.middlewareStep = middleware_Routerif len(httpCtx.RouterNode().Middlewares()) > 0 {return httpCtx.RouterNode().Middlewares()[0].Handle(ctx)}}if httpCtx.middlewareStep == middleware_Router {return httpCtx.Handler()(ctx)}} else {// check exclude configif ctx.RouterNode().Node().hasExcludeMiddleware && bm.next.HasExclude() {if bm.next.ExistsExcludeRouter(ctx.RouterNode().Node().fullPath) {return bm.next.Next(ctx)}}return bm.next.Handle(ctx)}return n}

通过这个代码我们大概能看出:

BaseMiddleware其实是一个链表的node

中间件组成了一个链表,并且有不同的类型

有group中间件和普通中间件

根据当前ctx所处的处理步骤决定调用哪一个中间件

最后调用ctx的handler

 

 

自定义的middleware要继承 BaseMiddleware

并且实现handle

func (asm *ApiSignMiddleware) Handle(ctx dotweb.Context) error {if sign := ctx.Request().QueryHeader("Sign"); len(sign) <= 0 {return ctx.WriteJsonC(http.StatusBadRequest, models.Response{Err: common.ErrSignParams, Data: nil})} else {uri := ctx.Request().RequestURIif index := strings.Index(uri, "?"); index != -1 {uri = uri[:index]}if ok := checkSign(sign, uri); !ok {return ctx.WriteJsonC(http.StatusBadRequest, models.Response{Err: common.ErrSignParams, Data: nil})}return asm.Next(ctx)}}

这样就可以对传进来的Contex进行解析

 

 

 

分析一下blogserver里面用到的middleware:

CrosMiddleware

func (cm *CrosMiddleware) Handle(ctx dotweb.Context) error {if strings.Contains(ctx.Request().RequestURI, "v1") && ctx.Request().Method != "OPTIONS" {if sign := ctx.Request().QueryHeader("Sign"); len(sign) <= 0 {return ctx.WriteJsonC(http.StatusBadRequest, models.Response{Err: common.ErrSignParams, Data: nil})} else {uri := ctx.Request().RequestURIif index := strings.Index(uri, "?"); index != -1 {uri = uri[:index]}if ok := checkSign(sign, uri); !ok {return ctx.WriteJsonC(http.StatusBadRequest, models.Response{Err: common.ErrSignParams, Data: nil})}return cm.Next(ctx)}}return cm.Next(ctx)}
 

CrosMiddleware 对uri的非参数部分调用checkSign

//验证签名 (requestUri(不含query)+secret)func checkSign(sign, uri string) bool {result := utils.Md5(uri + config.Config().SecretKey)return result == sign}

传过来得header里面得sign值应该跟 uri + 配置文件里面的 SecretKey 取md5 一致


声明:作为区块链技术信息平台,本站所提供的资讯信息不代表任何投资暗示,本站所发布文章仅代表个人观点,与链客社区官方立场无关。
评论(0)问答(0)
请先登录或注册

请先登陆或注册

相关推荐

DataWhale & Golang(二、数据类型、关键字、标识符)

二、数据类型、关键字、标识符学习大纲:  目录二、数据类型、关键字、标识符          学习大纲 &nb......
marvel · 2020-12-17
2163阅读 · 0赞赏 · 0问答

go语言----函数 结构体 接口 多态

函数Go语言 函数是反过来声明 变量类型和  函数返回值一。一个返回值package mainimport "fmt"func max(a int,b......
YYF · 2020-12-12
2484阅读 · 0赞赏 · 0问答

Ronaldo

3867.0

LK币

28

粉丝

63

笔记

感谢"Ronaldo"

这篇精彩的笔记,目前已经帮助

  • 0
  • 2
  • 6
  • 5
  • 9
喜欢0
链客社群 加入

微博进入

商务合作>

广告投放>

公司名称:北京链客行科技有限公司

联系方式:010-67707199

ICP备案号:京ICP备18032136号

Copyright:链客区块链技术问答社区 版权所有

感谢您的提问,问题被社区永久收入以便新人查看。一定要记得采纳最佳答案哦!加油!

感谢您的善举,每一次解答会成为新人的灯塔,回答被采纳后获得20算力和相应的LK币奖励

您将赞赏给对方2LK币的奖励哦!感谢您的赞赏!

您将赞赏给对方2LK币的奖励哦!感谢您的赞赏!