go 微服務(wù)框架kratos使用中間件的方法
一、中間件的概念
在go語言中,中間件是一種用于處理http請(qǐng)求的開發(fā)模式,允許開發(fā)人員在請(qǐng)求到達(dá)處理程序之前或之后執(zhí)行特定的操作,如日志記錄、身份驗(yàn)證、錯(cuò)誤處理等。
中間件通常是一個(gè)函數(shù),它接收一個(gè) `http.Handler` 作為參數(shù)并返回另一個(gè) `http.Handler`。
go源碼中 Handler 的定義如下:
type Handler interface { ServeHTTP(ResponseWriter, *Request) }
二、go原生http中使用中間件的方法
使用方法:
1、創(chuàng)建中間件函數(shù),輸入?yún)?shù) http.Handler,輸出參數(shù) http.Handler
2、將處理器函數(shù)作為參數(shù)傳入上述中間件函數(shù)
3、運(yùn)用 Handle(pattern string, handler Handler) 等函數(shù)將中間件函數(shù)綁定到請(qǐng)求路由中
代碼示例:
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("請(qǐng)求處理之前 Request URI: %s\n", r.RequestURI) next.ServeHTTP(w, r) log.Printf("處理程序之后進(jìn)行的操作...\n") }) } // handler 處理函數(shù) func SayHello(w http.ResponseWriter, r *http.Request) { fmt.Println("Hello world") } func main() { //創(chuàng)建一個(gè) HTTP 請(qǐng)求路由器 mux := http.NewServeMux() // 使用日志記錄中間件 mux.Handle("/index", loggingMiddleware(http.HandlerFunc(SayHello))) //啟動(dòng)服務(wù),使用創(chuàng)建的 ServeMux http.ListenAndServe(":8081", mux) }
運(yùn)行效果:
三、go微服務(wù)框架Kratos使用中間件的方法
kratos介紹中間件的官網(wǎng)地址:概覽 | Kratos
1、內(nèi)置中間件使用方法
①通過 Middleware(m ...middleware.Middleware) ServerOption 添加所需的中間件
②將上述由中間件組成的 ServerOption 添加到 []http.ServerOption 中
③通過函數(shù) NewServer(opts ...ServerOption) *Server 創(chuàng)建 httpServer
代碼示例:
func NewHTTPServer(c *conf.Server, logger log.Logger, blog *service.BlogService) *http.Server { opts := []http.ServerOption{ http.Middleware( //使用kratos內(nèi)置中間件 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())) } //創(chuàng)建 httpServer srv := http.NewServer(opts...) v1.RegisterBlogServiceHTTPServer(srv, blog) return srv }
2、自定義中間件使用方法
①實(shí)現(xiàn) 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 實(shí)例以便訪問接口相關(guān)的元信息。
②像添加內(nèi)置中間件一樣,將自定義中間件添加到 http.Middleware 和 []http.ServerOption 中
③通過函數(shù) NewServer(opts ...ServerOption) *Server 創(chuàng)建 httpServer
代碼示例:
// auth.go 單元 //自定義 JWT 認(rèn)證中間件 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())) } //創(chuàng)建 httpServer srv := http.NewServer(opts...) v1.RegisterBlogServiceHTTPServer(srv, blog) return srv }
3、為特定路由定制中間件的使用方法
使用方法:
對(duì)特定路由定制中間件:
server: selector.Server(ms...)
client: selector.Client(ms...)
代碼示例:
// server/http.go 單元 // 添加驗(yàn)證白名單 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())) } //創(chuàng)建 httpServer srv := http.NewServer(opts...) v1.RegisterBlogServiceHTTPServer(srv, blog) return srv }
注意: 定制中間件是通過 operation 匹配,并不是 http 本身的路由?。。?/strong>
gRPC path 的拼接規(guī)則為 /包名.服務(wù)名/方法名(/package.Service/Method)
。
到此這篇關(guān)于go 微服務(wù)框架kratos使用中間件的方法的文章就介紹到這了,更多相關(guān)go 微服務(wù)框架kratos使用中間件內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Golang Gorm實(shí)現(xiàn)自定義多態(tài)模型關(guān)聯(lián)查詢
GORM 是一個(gè)流行的開源 ORM (Object-Relational Mapping) 庫,專為 Go 語言設(shè)計(jì),它簡(jiǎn)化了與 SQL 數(shù)據(jù)庫的交互,GORM 封裝了數(shù)據(jù)庫操作,使得開發(fā)者能夠通過簡(jiǎn)單的鏈?zhǔn)秸{(diào)用來執(zhí)行 CRUD,本文給大家介紹了Golang Gorm實(shí)現(xiàn)自定義多態(tài)模型關(guān)聯(lián)查詢,需要的朋友可以參考下2024-11-11構(gòu)建Golang應(yīng)用最小Docker鏡像的實(shí)現(xiàn)
這篇文章主要介紹了構(gòu)建Golang應(yīng)用最小Docker鏡像的實(shí)現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2020-05-05Golang實(shí)現(xiàn)復(fù)合數(shù)據(jù)類型
Go語言的復(fù)合數(shù)據(jù)類型包括數(shù)組、切片、映射、結(jié)構(gòu)體和接口,本文就來介紹一下Golang實(shí)現(xiàn)復(fù)合數(shù)據(jù)類型,具有一定的參考價(jià)值,感興趣的可以了解一下2025-02-02