goweb中间件

中间件基本概念

中间件(Middleware)是一种在HTTP请求到达最终处理程序(Handler)之前或之后执行特定功能的机制。

在 Go 语言里,net/http 是标准库中用于构建 HTTP 服务器的包,中间件则是处理 HTTP 请求时常用的技术。中间件其实就是一个函数,它会接收一个 http.Handler 类型的参数,并且返回另一个 http.Handler。中间件能够在请求到达最终处理程序之前或者响应返回客户端之前执行一些通用操作,像日志记录、认证、压缩等。

下面是一个简单的中间件函数示例:

go 复制代码
go
package main

import (
    "log"
    "net/http"
)

// 中间件函数,接收一个 http.Handler 并返回另一个 http.Handler
func loggingMiddleware(next http.Handler) http.Handler {
    return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
        // 在请求处理之前执行的操作
        log.Printf("Received request: %s %s", r.Method, r.URL.Path)

        // 调用下一个处理程序
        next.ServeHTTP(w, r)

        // 在请求处理之后执行的操作
        log.Printf("Request completed: %s %s", r.Method, r.URL.Path)
    })
}

// 最终处理程序
func helloHandler(w http.ResponseWriter, r *http.Request) {
    w.Write([]byte("Hello, World!"))
}

func main() {
    // 创建一个新的 mux
    mux := http.NewServeMux()

    // 应用中间件到最终处理程序
    mux.Handle("/", loggingMiddleware(http.HandlerFunc(helloHandler)))

    // 启动服务器
    log.Println("Server started on :8080")
    log.Fatal(http.ListenAndServe(":8080", mux))
}
  • 中间件函数 loggingMiddleware:
  • 它接收一个 http.Handler 类型的参数 next,代表下一个要执行的处理程序。
  • 返回一个新的 http.HandlerFunc,在这个函数里可以执行请求处理前后的操作。
  • next.ServeHTTP(w, r) 这行代码会调用下一个处理程序。
  • 最终处理程序 helloHandler:

helloHandler是实际处理请求的函数,它会向客户端返回 "Hello, World!"。

中间件链式调用

多个中间件可以串联起来形成处理链:

go 复制代码
package main

import (
    "log"
    "net/http"
)

// 日志中间件
func loggingMiddleware(next http.Handler) http.Handler {
    return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
        log.Printf("Received request: %s %s", r.Method, r.URL.Path)
        next.ServeHTTP(w, r)
        log.Printf("Request completed: %s %s", r.Method, r.URL.Path)
    })
}

// 认证中间件
func authMiddleware(next http.Handler) http.Handler {
    return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
        // 简单的认证逻辑
        authHeader := r.Header.Get("Authorization")
        if authHeader != "Bearer secret_token" {
            http.Error(w, "Unauthorized", http.StatusUnauthorized)
            return
        }
        next.ServeHTTP(w, r)
    })
}

// 最终处理程序
func helloHandler(w http.ResponseWriter, r *http.Request) {
    w.Write([]byte("Hello, World!"))
}

func main() {
    mux := http.NewServeMux()

    // 应用多个中间件到最终处理程序
    finalHandler := loggingMiddleware(authMiddleware(http.HandlerFunc(helloHandler)))
    mux.Handle("/", finalHandler)

    log.Println("Server started on :8080")
    log.Fatal(http.ListenAndServe(":8080", mux))
}
  • 这里新增了一个 authMiddleware 中间件,用于简单的认证。
  • 在 main 函数里,先把 authMiddleware 应用到 helloHandler 上,再把 loggingMiddleware 应用到结果上,这样就实现了多个中间件的组合。

通过使用中间件,能够让代码更具模块化和可维护性,并且可以在多个处理程序之间共享通用的逻辑。

中间件链中传递自定义参数

​场景​ ​:需要在多个中间件间共享数据(如请求ID、用户会话)

​实现方式​ ​:通过 context.Context 传递参数

go 复制代码
package main

import (
	"context"
	"fmt"
	"net/http"
)

// 中间件函数
func middleware(next http.Handler) http.Handler {
	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		// 设置上下文值
		ctx := context.WithValue(r.Context(), "key", "value")
		ctx = context.WithValue(ctx, "user_id", 123)
		r = r.WithContext(ctx)

		// 调用下一个处理函数
		next.ServeHTTP(w, r)
	})
}

// 处理函数
func handler(w http.ResponseWriter, r *http.Request) {
	// 从上下文中获取值
	value := r.Context().Value("key").(string)
	userID := r.Context().Value("user_id").(int)
	fmt.Fprintf(w, "Received user_id %d value: %v", userID, value)
}

func main() {
	// 创建一个处理函数
	mux := http.NewServeMux()
	mux.HandleFunc("/", handler)

	http.Handle("/", middleware(mux))

	// 启动服务器
	fmt.Println("Server started on :80")
	http.ListenAndServe(":80", nil)
}

​特点​​:

  • 数据在中间件链中透明传递
  • 避免全局变量和参数层层传递

相关推荐
钟智强8 小时前
红队实战复盘:如何运用【火尖枪】高效突破复杂登录防线
服务器·安全·web安全·http·go·php·bruteforce
Grassto8 小时前
Go Module 基础概念全解析:module、version、sum 是什么
golang·go·go module
码luffyliu20 小时前
从 2 小时价格轮询任务通知丢失,拆解 Go Context 生命周期管控核心
后端·golang·go
踏浪无痕1 天前
一个 Java 老兵转 Go 后,终于理解了“简单”的力量
后端·程序员·go
代码扳手1 天前
一次线上事故后的反思:Go 项目中如何构建可靠的单元测试
后端·go
Penge6661 天前
Go JSON 序列化大整数丢失精度分析
后端·go
ServBay2 天前
掌握这9个GO技巧,代码高效又高能
后端·go
Grassto2 天前
一个 import 语句,引发的 Go 第三方包加载之旅
golang·go·go module
岁月的眸3 天前
【科大讯飞声纹识别和语音内容识别的实时接口实现】
人工智能·go·语音识别