首页 > 常见问题 > 正文

golang中间件有什么作用

尊渡假赌尊渡假赌尊渡假赌
发布: 2023-05-26 11:03:35
原创
2247 人浏览过

Golang中间件的责任是可插拔并且自足,其作用是:1、在处理请求的过程中,对请求进行拦截、处理或者过滤,并且可以在处理请求的前后进行一些操作,例如日志记录、身份验证、处理请求的参数等;2、中间件可以在代码结构上实现业务逻辑和处理请求的分离,使得代码更加清晰和易于维护;3、中间件可以被复用,减少了代码重复编写的工作量。

golang中间件有什么作用

本教程操作环境:windows10系统、GO 1.20.1版本、Dell G3电脑。

Golang中间件的作用

中间件主要责任就是可插拔并且自足。在处理请求的过程中,对请求进行拦截、处理或者过滤,并且可以在处理请求的前后进行一些操作,例如日志记录、身份验证、处理请求的参数等。中间件可以在代码结构上实现业务逻辑和处理请求的分离,使得代码更加清晰和易于维护。同时,中间件可以被复用,减少了代码重复编写的工作量。

代码示例如下:

package main
import (
	"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 New
func NewSessionAuth() *SessionAuth {
	sAuth := new(SessionAuth)
	return sAu
}
登录后复制

Handle是什么时候被调用的?

我们看看BaseMiddlWare的源码:

// BaseMiddleware is the base struct, user defined middleware should extend this
type BaseMiddleware struct {
    next           Middleware
    excludeRouters 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_Group
            if len(httpCtx.RouterNode().GroupMiddlewares()) > 0 {
                return httpCtx.RouterNode().GroupMiddlewares()[0].Handle(ctx)
            }
        }

        if httpCtx.middlewareStep == middleware_Group {
            httpCtx.middlewareStep = middleware_Router
            if len(httpCtx.RouterNode().Middlewares()) > 0 {
                return httpCtx.RouterNode().Middlewares()[0].Handle(ctx)
            }
        }

        if httpCtx.middlewareStep == middleware_Router {
            return httpCtx.Handler()(ctx)
        }
    } else {
        // check exclude config
        if 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().RequestURI
        if 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().RequestURI
            if 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一致

以上是golang中间件有什么作用的详细内容。更多信息请关注PHP中文网其他相关文章!

相关标签:
来源:php.cn
本站声明
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn
最新问题
热门教程
更多>
最新下载
更多>
网站特效
网站源码
网站素材
前端模板