10 KiB
10 KiB
中间件工具文档
概述
中间件工具提供了常用的HTTP中间件功能,包括CORS处理和时区管理。
功能特性
- CORS中间件:支持跨域资源共享配置
- 时区中间件:从请求头读取时区信息,支持默认时区设置
- 中间件链:提供便捷的中间件链式调用
CORS中间件
功能说明
CORS中间件用于处理跨域资源共享,支持:
- 配置允许的源(支持通配符)
- 配置允许的HTTP方法
- 配置允许的请求头
- 配置暴露的响应头
- 支持凭证传递
- 预检请求缓存时间设置
使用方法
基本使用(默认配置)
import (
"net/http"
"github.com/go-common/middleware"
)
func main() {
handler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
// 处理请求
})
// 使用默认CORS配置
corsHandler := middleware.CORS()(handler)
http.Handle("/api", corsHandler)
http.ListenAndServe(":8080", nil)
}
自定义配置
import (
"net/http"
"github.com/go-common/middleware"
)
func main() {
// 自定义CORS配置
corsConfig := &middleware.CORSConfig{
AllowedOrigins: []string{
"https://example.com",
"https://app.example.com",
"*.example.com", // 支持通配符
},
AllowedMethods: []string{"GET", "POST", "PUT", "DELETE", "OPTIONS"},
AllowedHeaders: []string{
"Content-Type",
"Authorization",
"X-Requested-With",
"X-Timezone",
},
ExposedHeaders: []string{"X-Total-Count"},
AllowCredentials: true,
MaxAge: 3600, // 1小时
}
handler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
// 处理请求
})
corsHandler := middleware.CORS(corsConfig)(handler)
http.Handle("/api", corsHandler)
http.ListenAndServe(":8080", nil)
}
允许所有源(开发环境)
corsConfig := &middleware.CORSConfig{
AllowedOrigins: []string{"*"},
AllowedMethods: []string{"GET", "POST", "PUT", "DELETE", "OPTIONS"},
AllowedHeaders: []string{"*"},
}
corsHandler := middleware.CORS(corsConfig)(handler)
CORSConfig 配置说明
| 字段 | 类型 | 说明 | 默认值 |
|---|---|---|---|
| AllowedOrigins | []string | 允许的源,支持 "" 和 ".example.com" | ["*"] |
| AllowedMethods | []string | 允许的HTTP方法 | ["GET", "POST", "PUT", "DELETE", "PATCH", "OPTIONS"] |
| AllowedHeaders | []string | 允许的请求头 | ["Content-Type", "Authorization", "X-Requested-With", "X-Timezone"] |
| ExposedHeaders | []string | 暴露给客户端的响应头 | [] |
| AllowCredentials | bool | 是否允许发送凭证 | false |
| MaxAge | int | 预检请求缓存时间(秒) | 86400 |
注意事项
- 如果
AllowCredentials为true,AllowedOrigins不能使用 "*",必须指定具体的源 - 通配符支持:
"*.example.com"会匹配"https://app.example.com"等子域名 - 预检请求(OPTIONS)会自动处理,无需在业务代码中处理
时区中间件
功能说明
时区中间件用于从请求头读取时区信息,并存储到context中,方便后续使用。
- 从请求头
X-Timezone读取时区 - 如果未传递时区信息,使用默认时区
AsiaShanghai - 时区信息存储到context中,可通过
http.GetTimezone()获取 - 自动验证时区有效性,无效时区会回退到默认时区
使用方法
基本使用(默认时区 AsiaShanghai)
import (
"net/http"
"github.com/go-common/middleware"
"github.com/go-common/http"
"github.com/go-common/datetime"
)
func handler(w http.ResponseWriter, r *http.Request) {
// 从context获取时区
timezone := http.GetTimezone(r)
// 使用时区
now := datetime.Now(timezone)
datetime.FormatDateTime(now, timezone)
http.Success(w, map[string]interface{}{
"timezone": timezone,
"time": datetime.FormatDateTime(now),
})
}
func main() {
handler := middleware.Timezone(http.HandlerFunc(handler))
http.Handle("/api", handler)
http.ListenAndServe(":8080", nil)
}
自定义默认时区
import (
"net/http"
"github.com/go-common/middleware"
"github.com/go-common/datetime"
)
func handler(w http.ResponseWriter, r *http.Request) {
// 处理请求
}
func main() {
// 使用自定义默认时区
handler := middleware.TimezoneWithDefault(datetime.UTC)(http.HandlerFunc(handler))
http.Handle("/api", handler)
http.ListenAndServe(":8080", nil)
}
在业务代码中使用时区
import (
"net/http"
"github.com/go-common/http"
"github.com/go-common/datetime"
)
func GetUserList(w http.ResponseWriter, r *http.Request) {
// 从请求context获取时区
timezone := http.GetTimezone(r)
// 使用时区进行时间处理
now := datetime.Now(timezone)
// 查询数据时使用时区
startTime := datetime.StartOfDay(now, timezone)
endTime := datetime.EndOfDay(now, timezone)
// 返回数据
http.Success(w, map[string]interface{}{
"timezone": timezone,
"startTime": datetime.FormatDateTime(startTime),
"endTime": datetime.FormatDateTime(endTime),
})
}
请求头格式
客户端需要在请求头中传递时区信息:
X-Timezone: Asia/Shanghai
支持的时区格式(IANA时区数据库):
Asia/ShanghaiAmerica/New_YorkEurope/LondonUTC- 等等
注意事项
- 如果请求头中未传递
X-Timezone,默认使用AsiaShanghai - 如果传递的时区无效,会自动回退到默认时区
- 时区信息存储在context中,可以在整个请求生命周期中使用
- 建议在CORS配置中包含
X-Timezone请求头
中间件链
功能说明
中间件链提供便捷的中间件组合方式,支持链式调用。
使用方法
import (
"net/http"
"github.com/go-common/middleware"
)
func handler(w http.ResponseWriter, r *http.Request) {
// 处理请求
}
func main() {
// 创建中间件链
chain := middleware.NewChain(
middleware.CORS(),
middleware.Timezone,
)
// 应用到处理器
handler := chain.ThenFunc(handler)
http.Handle("/api", handler)
http.ListenAndServe(":8080", nil)
}
链式追加中间件
chain := middleware.NewChain(middleware.CORS())
chain.Append(middleware.Timezone)
handler := chain.ThenFunc(handler)
完整示例
示例1:CORS + 时区中间件
package main
import (
"log"
"net/http"
"github.com/go-common/middleware"
"github.com/go-common/http"
"github.com/go-common/datetime"
)
func apiHandler(w http.ResponseWriter, r *http.Request) {
// 获取时区
timezone := http.GetTimezone(r)
now := datetime.Now(timezone)
http.Success(w, map[string]interface{}{
"message": "Hello",
"timezone": timezone,
"time": datetime.FormatDateTime(now),
})
}
func main() {
// 配置CORS
corsConfig := &middleware.CORSConfig{
AllowedOrigins: []string{"*"},
AllowedMethods: []string{"GET", "POST", "OPTIONS"},
AllowedHeaders: []string{"Content-Type", "Authorization", "X-Timezone"},
}
// 创建中间件链
chain := middleware.NewChain(
middleware.CORS(corsConfig),
middleware.Timezone,
)
// 应用中间件
handler := chain.ThenFunc(apiHandler)
http.Handle("/api", handler)
log.Println("Server started on :8080")
log.Fatal(http.ListenAndServe(":8080", nil))
}
示例2:与路由框架集成
package main
import (
"net/http"
"github.com/go-common/middleware"
"github.com/go-common/http"
)
func main() {
mux := http.NewServeMux()
// 创建中间件链
chain := middleware.NewChain(
middleware.CORS(),
middleware.Timezone,
)
// 应用中间件到所有路由
mux.Handle("/api/users", chain.ThenFunc(getUsers))
mux.Handle("/api/posts", chain.ThenFunc(getPosts))
http.ListenAndServe(":8080", mux)
}
func getUsers(w http.ResponseWriter, r *http.Request) {
timezone := http.GetTimezone(r)
// 处理逻辑
http.Success(w, nil)
}
func getPosts(w http.ResponseWriter, r *http.Request) {
timezone := http.GetTimezone(r)
// 处理逻辑
http.Success(w, nil)
}
API 参考
CORS中间件
CORS(config ...*CORSConfig) func(http.Handler) http.Handler
创建CORS中间件。
参数:
config: 可选的CORS配置,不指定则使用默认配置
返回: 中间件函数
DefaultCORSConfig() *CORSConfig
返回默认的CORS配置。
时区中间件
Timezone(next http.Handler) http.Handler
时区处理中间件(默认时区为 AsiaShanghai)。
TimezoneWithDefault(defaultTimezone string) func(http.Handler) http.Handler
时区处理中间件(可自定义默认时区)。
参数:
defaultTimezone: 默认时区字符串
返回: 中间件函数
GetTimezoneFromContext(ctx context.Context) string
从context中获取时区。
中间件链
NewChain(middlewares ...func(http.Handler) http.Handler) *Chain
创建新的中间件链。
(c *Chain) Then(handler http.Handler) http.Handler
将中间件链应用到处理器。
(c *Chain) ThenFunc(handler http.HandlerFunc) http.Handler
将中间件链应用到处理器函数。
(c *Chain) Append(middlewares ...func(http.Handler) http.Handler) *Chain
追加中间件到链中。
注意事项
-
CORS配置:
- 生产环境建议明确指定允许的源,避免使用 "*"
- 如果使用凭证(cookies),必须明确指定源,不能使用 "*"
-
时区处理:
- 时区信息存储在context中,确保中间件在处理器之前执行
- 时区验证失败时会自动回退到默认时区,不会返回错误
-
中间件顺序:
- CORS中间件应该放在最外层,以便处理预检请求
- 时区中间件可以放在CORS之后
-
性能考虑:
- CORS预检请求会被缓存,减少重复请求
- 时区验证只在请求头存在时进行,性能影响很小