Golang使用原生http實現(xiàn)中間件的代碼詳解
Golang原生http實現(xiàn)中間件
中間件(middleware):常被用來做認(rèn)證校驗、審計等
大家常用的Iris、Gin等web框架,都包含了中間件邏輯。但有時我們引入該框架顯得較為繁重,本文將介紹通過golang原生http來實現(xiàn)中間件操作。全部代碼:https://github.com/ziyifast/ziyifast-code_instruction/tree/main/middleware
1 定義http.Handler:具體中間件操作
①CORSMiddleware:允許跨域
// CORSMiddleware handles Cross-Origin Resource Sharing (CORS) responses. func CORSMiddleware(next http.Handler) http.Handler { fmt.Println("cors middleware....") return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { if r.Method == "OPTIONS" { w.Header().Set("Access-Control-Allow-Origin", "*") w.Header().Set("Access-Control-Allow-Methods", "GET, POST, OPTIONS, DELETE") //如果前后端需要傳遞自定義請求頭,需要再Access-Control-Allow-Headers中匹配(Yi-Auth-Token) w.Header().Set("Access-Control-Allow-Headers", "Content-Type, Accept, Yi-Auth-Token") w.WriteHeader(http.StatusOK) return } w.Header().Set("Access-Control-Allow-Origin", "*") w.Header().Set("Access-Control-Allow-Methods", "GET, POST, OPTIONS, DELETE") w.Header().Set("Access-Control-Allow-Headers", "Content-Type,Accept,Yi-Auth-Token") //交給下一個中間件處理 next.ServeHTTP(w, r) }) }
②AuthMiddleware:認(rèn)證
// AuthMiddleware simulates a simple authentication middleware. func AuthMiddleware(next http.Handler) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { fmt.Println("auth middleware...") //store info in ctx token := r.Header.Get("Token") if len(token) != 0 { //TODO 1. check token 2. get userinfo from token userID := "1" ctx := context.WithValue(r.Context(), "userID", userID) r = r.WithContext(ctx) } next.ServeHTTP(w, r) }) }
③AuditMiddleware:審計操作
// AuditMiddleware simulates an audit logging middleware. func AuditMiddleware(next http.Handler) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { fmt.Println("audit middleware...") next.ServeHTTP(w, r) }) }
④SmokeHandler:具體處理操作
// SmokeHandler returns the current time as a string. func SmokeHandler(w http.ResponseWriter, r *http.Request) { fmt.Println("smoke handle....") _, err := w.Write([]byte(time.Now().String())) if err != nil { http.Error(w, "Internal Server Error", http.StatusInternalServerError) } }
2 義中間件類型&定義中間件鏈
①type Middleware func(http.Handler) http.Handler:定義中間件
type Middleware func(http.Handler) http.Handler
②定義中間件鏈MiddlewareChain
// NewMiddlewareChain creates a new middleware chain with the given middlewares. func NewMiddlewareChain(middlewares ...Middleware) Middleware { return func(handler http.Handler) http.Handler { for i := len(middlewares) - 1; i >= 0; i-- { handler = middlewares[i](handler) } return handler } }
3 啟動http服務(wù)
func RunAndServe() error { defer func() { if e := recover(); e != nil { fmt.Println("err=", e) } }() mux := http.NewServeMux() // Create middleware chains for routes. authMiddlewareChain := NewMiddlewareChain(CORSMiddleware, AuthMiddleware, AuditMiddleware) //noAuthMiddlewareChain := NewMiddlewareChain(CORSMiddleware) // Convert the middleware chain result to http.HandlerFunc. smokeHandlerWrapped := func(w http.ResponseWriter, r *http.Request) { authMiddlewareChain(http.HandlerFunc(SmokeHandler)).ServeHTTP(w, r) } mux.HandleFunc("/smoke", smokeHandlerWrapped) fmt.Printf("listening on http://localhost:%d\n", 9999) return http.ListenAndServe(":9999", mux) }
4 測試
啟動后端
go run main.go
2. 瀏覽器訪問http://localhost:9999/smoke
3. 后端日志打印
可以看到是最后才處理我們的業(yè)務(wù)Handler
全部代碼
package main import ( "context" "fmt" "net/http" "time" ) type Middleware func(http.Handler) http.Handler // CORSMiddleware handles Cross-Origin Resource Sharing (CORS) responses. func CORSMiddleware(next http.Handler) http.Handler { fmt.Println("cors middleware....") return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { if r.Method == "OPTIONS" { w.Header().Set("Access-Control-Allow-Origin", "*") w.Header().Set("Access-Control-Allow-Methods", "GET, POST, OPTIONS, DELETE") //如果前后端需要傳遞自定義請求頭,需要再Access-Control-Allow-Headers中匹配(Yi-Auth-Token) w.Header().Set("Access-Control-Allow-Headers", "Content-Type, Accept, Yi-Auth-Token") w.WriteHeader(http.StatusOK) return } w.Header().Set("Access-Control-Allow-Origin", "*") w.Header().Set("Access-Control-Allow-Methods", "GET, POST, OPTIONS, DELETE") w.Header().Set("Access-Control-Allow-Headers", "Content-Type,Accept,Yi-Auth-Token") next.ServeHTTP(w, r) }) } // AuthMiddleware simulates a simple authentication middleware. func AuthMiddleware(next http.Handler) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { fmt.Println("auth middleware...") //store info in ctx token := r.Header.Get("Token") if len(token) != 0 { //TODO 1. check token 2. get userinfo from token userID := "1" ctx := context.WithValue(r.Context(), "userID", userID) r = r.WithContext(ctx) } next.ServeHTTP(w, r) }) } // AuditMiddleware simulates an audit logging middleware. func AuditMiddleware(next http.Handler) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { fmt.Println("audit middleware...") next.ServeHTTP(w, r) }) } // SmokeHandler returns the current time as a string. func SmokeHandler(w http.ResponseWriter, r *http.Request) { fmt.Println("smoke handle....") _, err := w.Write([]byte(time.Now().String())) if err != nil { http.Error(w, "Internal Server Error", http.StatusInternalServerError) } } // NewMiddlewareChain creates a new middleware chain with the given middlewares. func NewMiddlewareChain(middlewares ...Middleware) Middleware { return func(handler http.Handler) http.Handler { for i := len(middlewares) - 1; i >= 0; i-- { handler = middlewares[i](handler) } return handler } } func RunAndServe() error { defer func() { if e := recover(); e != nil { fmt.Println("err=", e) } }() mux := http.NewServeMux() // Create middleware chains for routes. authMiddlewareChain := NewMiddlewareChain(CORSMiddleware, AuthMiddleware, AuditMiddleware) //noAuthMiddlewareChain := NewMiddlewareChain(CORSMiddleware) // Convert the middleware chain result to http.HandlerFunc. smokeHandlerWrapped := func(w http.ResponseWriter, r *http.Request) { authMiddlewareChain(http.HandlerFunc(SmokeHandler)).ServeHTTP(w, r) } mux.HandleFunc("/smoke", smokeHandlerWrapped) fmt.Printf("listening on http://localhost:%d\n", 9999) return http.ListenAndServe(":9999", mux) } func main() { RunAndServe() }
以上就是Golang使用原生http實現(xiàn)中間件的代碼詳解的詳細內(nèi)容,更多關(guān)于Golang http中間件的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
golang gopm get -g -v 無法獲取第三方庫的解決方案
這篇文章主要介紹了golang gopm get -g -v 無法獲取第三方庫的解決方案,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2021-05-05基于context.Context的Golang?loader緩存請求放大問題解決
這篇文章主要為大家介紹了基于context.Context的Golang?loader緩存請求放大解決方案,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪2023-05-05golang gin 監(jiān)聽rabbitmq隊列無限消費的案例代碼
這篇文章主要介紹了golang gin 監(jiān)聽rabbitmq隊列無限消費,本文通過實例代碼給大家介紹的非常詳細,對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下2022-12-12golang值類型轉(zhuǎn)換成[]uint8類型的操作
這篇文章主要介紹了golang值類型轉(zhuǎn)換成[]uint8類型的操作,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2021-05-05Go 類型轉(zhuǎn)化工具庫cast函數(shù)詳解
這篇文章主要介紹了Go 類型轉(zhuǎn)化工具庫cast函數(shù)詳解,cast 是在Github上開源的工具庫,就像他的名字一樣,他為我們提供了非常便捷的類型轉(zhuǎn)化的方法2022-07-07