go 微服务框架kratos使用中间件的方法-kb88凯时官网登录

来自:网络
时间:2024-08-28
阅读:
免费资源网,https://freexyz.cn/

一、中间件的概念

在go语言中,中间件是一种用于处理http请求的开发模式,允许开发人员在请求到达处理程序之前或之后执行特定的操作,如日志记录、身份验证、错误处理等。

中间件通常是一个函数,它接收一个 `http.handler` 作为参数并返回另一个 `http.handler`。

go源码中 handler 的定义如下:

type handler interface {
	servehttp(responsewriter, *request)
}

二、go原生http中使用中间件的方法

使用方法:

1、创建中间件函数,输入参数 http.handler,输出参数 http.handler

2、将处理器函数作为参数传入上述中间件函数

3、运用 handle(pattern string, handler handler) 等函数将中间件函数绑定到请求路由中

代码示例:

package main
import (
	"fmt"
	"log"
	"net/http"
)
// 日志记录中间件
func loggingmiddleware(next http.handler) http.handler {
	return http.handlerfunc(func(w http.responsewriter, r *http.request) {
		log.printf("请求处理之前   request uri: %s\n", r.requesturi)
		next.servehttp(w, r)
		log.printf("处理程序之后进行的操作...\n")
	})
}
// handler 处理函数
func sayhello(w http.responsewriter, r *http.request) {
	fmt.println("hello world")
}
func main() {
	//创建一个 http 请求路由器
	mux := http.newservemux()
	// 使用日志记录中间件
	mux.handle("/index", loggingmiddleware(http.handlerfunc(sayhello)))
	//启动服务,使用创建的 servemux
	http.listenandserve(":8081", mux)
}

运行效果:

go 微服务框架kratos使用中间件的方法

三、go微服务框架kratos使用中间件的方法

kratos介绍中间件的d88尊龙官网手机app官网地址:

1、内置中间件使用方法

①通过 middleware(m ...middleware.middleware) serveroption 添加所需的中间件

②将上述由中间件组成的 serveroption 添加到 []http.serveroption 中

③通过函数 newserver(opts ...serveroption) *server 创建 httpserver

代码示例:

func newhttpserver(c *conf.server, logger log.logger, blog *service.blogservice) *http.server {
	opts := []http.serveroption{
		http.middleware(
			//使用kratos内置中间件
			recovery.recovery(),
			tracing.server(),
			logging.server(logger),
			validate.validator(),
		),
	}
	if c.http.network != "" {
		opts = append(opts, http.network(c.http.network))
	}
	if c.http.addr != "" {
		opts = append(opts, http.address(c.http.addr))
	}
	if c.http.timeout != nil {
		opts = append(opts, http.timeout(c.http.timeout.asduration()))
	}
	//创建 httpserver 
	srv := http.newserver(opts...)
	v1.registerblogservicehttpserver(srv, blog)
	return srv
}

2、自定义中间件使用方法

①实现 middleware.middleware 接口,其定义如下:

// handler defines the handler invoked by middleware.
type handler func(ctx context.context, req interface{}) (interface{}, error)
// middleware is http/grpc transport middleware.
type middleware func(handler) handler

中间件中您可以使用 tr, ok := transport.fromservercontext(ctx) 获得 transporter 实例以便访问接口相关的元信息。

②像添加内置中间件一样,将自定义中间件添加到 http.middleware 和 []http.serveroption 中

③通过函数 newserver(opts ...serveroption) *server 创建 httpserver

代码示例:

// auth.go 单元
//自定义 jwt 认证中间件
func jwtauth(jwtsecret string) middleware.middleware {
	return func(handler middleware.handler) middleware.handler {
		return func(ctx context.context, req interface{}) (reply interface{}, err error) {
			if tr, ok := transport.fromservercontext(ctx); ok {
				tokenstring := tr.requestheader().get("authorization")
				spew.dump(tokenstring)
				//token, err := jwt.parsewithclaims(tokenstring, &jwt.standardclaims{}, func(token *jwt.token) (interface{}, error) {
				token, err := jwt.parse(tokenstring, func(token *jwt.token) (interface{}, error) {
					// don't forget to validate the alg is what you expect:
					if _, ok := token.method.(*jwt.signingmethodhmac); !ok {
						return nil, fmt.errorf("unexpected signing method: %v", token.header["alg"])
					}
					// hmacsamplesecret is a []byte containing your secret, e.g. []byte("my_secret_key")
					return []byte(jwtsecret), nil
				})
				if err != nil {
					log.fatal(err)
				}
				if claims, ok := token.claims.(jwt.mapclaims); ok {
					fmt.println(claims["iss"], claims["exp"])
					//fmt.println(claims.issuer, claims.expiresat)
				} else {
					fmt.println(err)
				}
			}
			return handler(ctx, req)
		}
	}
}
// server/http.go 单元
func newhttpserver(c *conf.server, confauth *conf.auth, logger log.logger, blog *service.blogservice) *http.server {
	opts := []http.serveroption{
		http.middleware(
			//自定义中间件 jwtauth
			auth.jwtauth(confauth.jwtsecrect),
		),
	}
	if c.http.network != "" {
		opts = append(opts, http.network(c.http.network))
	}
	if c.http.addr != "" {
		opts = append(opts, http.address(c.http.addr))
	}
	if c.http.timeout != nil {
		opts = append(opts, http.timeout(c.http.timeout.asduration()))
	}
	//创建 httpserver 
	srv := http.newserver(opts...)
	v1.registerblogservicehttpserver(srv, blog)
	return srv
}

3、为特定路由定制中间件的使用方法

使用方法:

对特定路由定制中间件:

server: selector.server(ms...)

client: selector.client(ms...)

代码示例:

// server/http.go 单元
// 添加验证白名单
func newwhitelistmatcher() selector.matchfunc {
	whitelist := make(map[string]struct{})
	whitelist["/blog.api.v1.account/login"] = struct{}{}
	whitelist["/blog.api.v1.account/register"] = struct{}{}
	return func(ctx context.context, operation string) bool {
		if _, ok := whitelist[operation]; ok {
			return false
		}
		return true
	}
}
// server/http.go 单元
func newhttpserver(c *conf.server, confauth *conf.auth, logger log.logger, blog *service.blogservice) *http.server {
	opts := []http.serveroption{
		http.middleware(
			//自定义中间件 jwtauth
			selector.server(auth.jwtauth(confauth.jwtsecrect)).
				match(newwhitelistmatcher()).
				build(),
		),
	}
	if c.http.network != "" {
		opts = append(opts, http.network(c.http.network))
	}
	if c.http.addr != "" {
		opts = append(opts, http.address(c.http.addr))
	}
	if c.http.timeout != nil {
		opts = append(opts, http.timeout(c.http.timeout.asduration()))
	}
	//创建 httpserver 
	srv := http.newserver(opts...)
	v1.registerblogservicehttpserver(srv, blog)
	return srv
}

注意: 定制中间件是通过 operation 匹配,并不是 http 本身的路由!!!

grpc path 的拼接规则为 /包名.服务名/方法名(/package.service/method)

免费资源网,https://freexyz.cn/
返回顶部
顶部
网站地图