middleware.go 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125
  1. package router
  2. import (
  3. "fmt"
  4. "log/slog"
  5. "net/http"
  6. "runtime/debug"
  7. "strings"
  8. "time"
  9. )
  10. import (
  11. "github.com/gin-gonic/gin"
  12. )
  13. import (
  14. "resource-server/common"
  15. "resource-server/logger"
  16. )
  17. func InitMiddleware(r *gin.Engine) {
  18. // NoCache is a middleware function that appends headers
  19. r.Use(NoCache)
  20. // 跨域处理
  21. r.Use(Options)
  22. // Secure is a middleware function that appends security
  23. r.Use(Secure)
  24. // Use Slog Logger
  25. r.Use(GinLogger(logger.WithGroup("gin")))
  26. // Global Recover
  27. r.Use(GinRecovery(logger.WithGroup("ginRecovery")))
  28. // check token
  29. r.Use(CheckAuth)
  30. }
  31. // NoCache is a middleware function that appends headers
  32. // to prevent the client from caching the HTTP response.
  33. func NoCache(c *gin.Context) {
  34. c.Header("Cache-Control", "no-cache, no-store, max-age=0, must-revalidate, value")
  35. c.Header("Expires", "Thu, 01 Jan 1970 00:00:00 GMT")
  36. c.Header("Last-Modified", time.Now().UTC().Format(http.TimeFormat))
  37. c.Next()
  38. }
  39. // Options is a middleware function that appends headers
  40. // for options requests and aborts then exits the middleware
  41. // chain and ends the request.
  42. func Options(c *gin.Context) {
  43. if c.Request.Method != "OPTIONS" {
  44. c.Next()
  45. } else {
  46. c.Header("Access-Control-Allow-Origin", "*")
  47. c.Header("Access-Control-Allow-Methods", "GET,POST,PUT,PATCH,DELETE,OPTIONS")
  48. c.Header("Access-Control-Allow-Headers", "authorization, origin, content-type, accept")
  49. c.Header("Allow", "HEAD,GET,POST,PUT,PATCH,DELETE,OPTIONS")
  50. c.Header("Content-Type", "application/json")
  51. c.AbortWithStatus(200)
  52. }
  53. }
  54. // Secure is a middleware function that appends security
  55. // and resource access headers.
  56. func Secure(c *gin.Context) {
  57. c.Header("Access-Control-Allow-Origin", "*")
  58. //c.Header("X-Frame-Options", "DENY")
  59. c.Header("X-Content-Type-Options", "nosniff")
  60. c.Header("X-XSS-Protection", "1; mode=block")
  61. if c.Request.TLS != nil {
  62. c.Header("Strict-Transport-Security", "max-age=31536000")
  63. }
  64. // Also consider adding Content-Security-Policy headers
  65. // c.Header("Content-Security-Policy", "script-src 'self' https://cdnjs.cloudflare.com")
  66. }
  67. func CheckAuth(c *gin.Context) {
  68. //if common.Hostname == "DESKTOP-2VF4H05" {
  69. // c.Set("uid", cast.ToUint(1))
  70. // c.Set("username", "dev")
  71. // c.Next()
  72. // return
  73. //}
  74. if strings.HasPrefix(c.FullPath(), "/dr/api/v1/auth") {
  75. token := c.Request.Header.Get("Authorization")
  76. uid, username, err := common.ParseToken(strings.TrimPrefix(token, "Bearer "))
  77. if err != nil {
  78. c.AbortWithStatusJSON(200, common.ErrToH(common.InvalidToken, c.GetHeader("locale")))
  79. }
  80. c.Set("uid", uid)
  81. c.Set("username", username)
  82. }
  83. c.Next()
  84. }
  85. func GinLogger(logger *slog.Logger) gin.HandlerFunc {
  86. return func(c *gin.Context) {
  87. start := time.Now()
  88. path := c.Request.URL.Path
  89. if len(c.Request.URL.RawQuery) > 0 {
  90. path += "?" + c.Request.URL.RawQuery
  91. }
  92. c.Next()
  93. cost := time.Since(start)
  94. logger.Info(fmt.Sprintf("[%s]%s, header[%s-%s-%s] ip[%s], resp[%d] %s errors[%s]",
  95. c.Request.Method,
  96. path,
  97. c.GetHeader("Product"),
  98. c.GetHeader("Source"),
  99. c.GetHeader("Language"),
  100. c.ClientIP(),
  101. c.Writer.Status(),
  102. cost.String(),
  103. c.Errors.ByType(gin.ErrorTypePrivate).String(),
  104. ))
  105. }
  106. }
  107. func GinRecovery(logger *slog.Logger) gin.HandlerFunc {
  108. return gin.CustomRecovery(func(c *gin.Context, recovered interface{}) {
  109. logger.Error("Recovery from panic", "recoverd", recovered, "stack", string(debug.Stack()))
  110. common.HttpErr(c, common.Unknown)
  111. c.AbortWithStatus(http.StatusOK)
  112. })
  113. }