HTTP 服务器

server/ghttp 中基于 net.http 实现了 Server,用以注册 http 到 dove.Server() 中。

Gin

中间件

日志中间件和 Recover 中间件。

package middleware

import (
    "fmt"
    "net/http"
    "runtime/debug"
    "time"

    "github.com/camry/g/glog"
    "github.com/gin-gonic/gin"
)

func GinLogger() gin.HandlerFunc {
    return func(c *gin.Context) {
        start := time.Now()
        c.Next()

        req := c.Request
        res := c.Writer

        fields := []any{
            "remote_ip", c.ClientIP(),
            "latency", time.Now().Sub(start),
            "host", req.Host,
            "request", fmt.Sprintf("%s %s", req.Method, req.RequestURI),
            "status", res.Status(),
            "size", res.Size(),
            "user_agent", req.UserAgent(),
            "errors", c.Errors.ByType(gin.ErrorTypePrivate).String(),
            "raw", req.URL.RawQuery,
        }

        n := res.Status()
        switch {
        case n >= 500:
            fields = append(fields, "msg", "Server error")
            glog.Errorw(fields...)
        case n >= 400:
            fields = append(fields, "msg", "Client error")
            glog.Warnw(fields...)
        case n >= 300:
            fields = append(fields, "msg", "Redirection")
            glog.Infow(fields...)
        default:
            fields = append(fields, "msg", "Success")
            glog.Infow(fields...)
        }
    }
}

func GinRecover() gin.HandlerFunc {
    return func(c *gin.Context) {
        defer func() {
            if r := recover(); r != nil {
                glog.Errorf(`panic: %v`, r)
                glog.Errorf(`stack: %v`, string(debug.Stack()))
                debug.PrintStack()
                c.String(http.StatusInternalServerError, "Internal Server Error")
                c.AbortWithStatus(http.StatusInternalServerError)
            }
        }()
        c.Next()
    }
}

路由

使用 Gin 路由。

package http

func NewRouter() *gin.Engine {
    gin.SetMode(gin.ReleaseMode)

    router := gin.Default()

    router.Use(middleware.GinLogger(), middleware.GinRecover())

    homeC := controllers.NewHome()

    router.GET("/", homeC.Index)
    router.GET("/home/debug", homeC.Debug)

    return router
}

服务注册

使用 Dove 框架注册 HTTP 服务器。

hs := ghttp.NewServer(
    ghttp.Address(":8001"),
    ghttp.Handler(http.NewRouter()),
)

app := dove.New(
    dove.Name("dove"),
    dove.Version("v1.0.0"),
    dove.Server(hs),
)

if err := app.Run(); err != nil {
    log.Fatalln(err)
}