Golang使用原生http實現(xiàn)中間件的代碼詳解
更新時間:2024年05月31日 09:34:14 投稿:bairu
中間件(middleware):常被用來做認證校驗、審計等,家常用的Iris、Gin等web框架,都包含了中間件邏輯,但有時我們引入該框架顯得較為繁重,本文將介紹通過golang原生http來實現(xiàn)中間件操作,需要的朋友可以參考下
Golang原生http實現(xiàn)中間件
中間件(middleware):常被用來做認證校驗、審計等
大家常用的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:認證
// 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服務
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è)務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)容,更多關于Golang http中間件的資料請關注腳本之家其它相關文章!
相關文章
golang gopm get -g -v 無法獲取第三方庫的解決方案
這篇文章主要介紹了golang gopm get -g -v 無法獲取第三方庫的解決方案,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2021-05-05
基于context.Context的Golang?loader緩存請求放大問題解決
這篇文章主要為大家介紹了基于context.Context的Golang?loader緩存請求放大解決方案,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪2023-05-05
golang gin 監(jiān)聽rabbitmq隊列無限消費的案例代碼
這篇文章主要介紹了golang gin 監(jiān)聽rabbitmq隊列無限消費,本文通過實例代碼給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下2022-12-12
golang值類型轉(zhuǎn)換成[]uint8類型的操作
這篇文章主要介紹了golang值類型轉(zhuǎn)換成[]uint8類型的操作,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2021-05-05
Go 類型轉(zhuǎn)化工具庫cast函數(shù)詳解
這篇文章主要介紹了Go 類型轉(zhuǎn)化工具庫cast函數(shù)詳解,cast 是在Github上開源的工具庫,就像他的名字一樣,他為我們提供了非常便捷的類型轉(zhuǎn)化的方法2022-07-07

