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)
}