Golang使用原生http實現(xiàn)中間件的代碼詳解
更新時間:2024年05月31日 09:34:14 投稿:bairu
中間件(middleware):常被用來做認(rèn)證校驗、審計等,家常用的Iris、Gin等web框架,都包含了中間件邏輯,但有時我們引入該框架顯得較為繁重,本文將介紹通過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)中間件的代碼詳解的詳細(xì)內(nèi)容,更多關(guān)于Golang http中間件的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
Air實現(xiàn)Go程序?qū)崟r熱重載使用過程解析示例
這篇文章主要為大家介紹了Air實現(xiàn)Go程序?qū)崟r熱重載使用過程解析示例,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步早日升職加薪2022-04-04
Golang優(yōu)雅關(guān)閉channel的方法示例
Goroutine和channel是Go在“并發(fā)”方面兩個核心feature,下面這篇文章主要給大家介紹了關(guān)于Golang如何優(yōu)雅關(guān)閉channel的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),需要的朋友可以參考解決,下面來一起看看吧。2017-11-11
Golang import本地包和導(dǎo)入問題相關(guān)詳解
這篇文章主要介紹了Golang import本地包和導(dǎo)入問題相關(guān)詳解,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2020-02-02

