Files
user_service/deploy/api/api_gateway/main.go
2025-10-09 18:19:57 +08:00

137 lines
3.4 KiB
Go

package main
import (
"log"
"net/http"
"net/http/httputil"
"net/url"
"os"
"time"
"github.com/gin-contrib/cors"
"github.com/gin-gonic/gin"
)
var serviceMap = map[string]string{
"/user/login": "http://user_login:80",
"/user/register": "http://user_register:80",
"/user/delete": "http://user_delete:80",
"/user/update/account": "http://user_update_account:80",
"/user/update/password": "http://user_update_password:80",
}
// 日志中间件(记录网关接收的请求)
func loggerMiddleware() gin.HandlerFunc {
return func(c *gin.Context) {
startTime := time.Now()
c.Next()
endTime := time.Now()
log.Printf(
"[网关请求] %s %s | 状态码: %d | 耗时: %s | 客户端IP: %s",
c.Request.Method,
c.Request.URL.Path,
c.Writer.Status(),
endTime.Sub(startTime),
c.ClientIP(),
)
}
}
// 反向代理处理(添加详细转发日志)
func reverseProxy(target string) gin.HandlerFunc {
return func(c *gin.Context) {
// 解析目标服务地址
targetURL, err := url.Parse(target)
if err != nil {
log.Printf("[代理错误] 目标服务地址解析失败: %s, 错误: %v", target, err)
c.JSON(http.StatusInternalServerError, gin.H{
"success": false,
"message": "服务配置错误",
})
return
}
// 创建反向代理实例
proxy := httputil.NewSingleHostReverseProxy(targetURL)
// 记录转发前的请求信息
reqStart := time.Now()
log.Printf(
"[开始转发] 方法: %s | 原始路径: %s | 目标服务: %s | 客户端IP: %s",
c.Request.Method,
c.Request.URL.Path,
targetURL.String(),
c.ClientIP(),
)
// 自定义请求转发逻辑(并记录请求头)
originalDirector := proxy.Director
proxy.Director = func(req *http.Request) {
originalDirector(req)
// 传递关键头信息
req.Header.Set("Origin", c.Request.Header.Get("Origin"))
req.Host = targetURL.Host
req.Header.Set("X-Forwarded-By", "user-gateway")
// 打印转发的请求头(调试用,生产环境可注释)
log.Printf("[转发请求头] 目标服务: %s | Origin: %s | Host: %s",
targetURL.Host,
req.Header.Get("Origin"),
req.Host,
)
}
// 记录响应信息
proxy.ModifyResponse = func(resp *http.Response) error {
// 计算转发耗时
proxyDuration := time.Since(reqStart)
// 打印响应状态
log.Printf(
"[转发响应] 目标服务: %s | 状态码: %d | 耗时: %s | 响应头Origin: %s",
targetURL.Host,
resp.StatusCode,
proxyDuration,
resp.Header.Get("Access-Control-Allow-Origin"),
)
return nil
}
// 执行代理转发
proxy.ServeHTTP(c.Writer, c.Request)
}
}
func main() {
r := gin.Default()
// 注册日志中间件
r.Use(loggerMiddleware())
// 跨域配置
r.Use(cors.New(cors.Config{
AllowOrigins: []string{"*"},
AllowMethods: []string{"GET", "POST", "PUT", "PATCH", "DELETE", "OPTIONS"},
AllowHeaders: []string{"Origin", "Content-Type", "Accept", "Authorization"},
ExposeHeaders: []string{"Content-Length"},
AllowCredentials: true,
MaxAge: 12 * time.Hour,
}))
// 注册路由
for path, target := range serviceMap {
r.Any(path, reverseProxy(target))
r.Any(path+"/*any", reverseProxy(target))
}
// 启动服务
port := os.Getenv("GATEWAY_PORT")
if port == "" {
port = "80"
}
log.Printf("网关服务启动在 %s 端口", port)
if err := r.Run(":" + port); err != nil {
log.Fatalf("服务启动失败: %v", err)
}
}