https_server.go 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138
  1. package http_server
  2. import (
  3. "embed"
  4. "encoding/json"
  5. "fmt"
  6. "io/fs"
  7. olog "log"
  8. "net/http"
  9. "pmail/config"
  10. "pmail/controllers"
  11. "pmail/controllers/email"
  12. "pmail/dto/response"
  13. "pmail/i18n"
  14. "pmail/models"
  15. "pmail/session"
  16. "pmail/utils/context"
  17. "pmail/utils/id"
  18. "time"
  19. log "github.com/sirupsen/logrus"
  20. "github.com/spf13/cast"
  21. )
  22. //go:embed dist/*
  23. var local embed.FS
  24. var httpsServer *http.Server
  25. type nullWrite struct {
  26. }
  27. func (w *nullWrite) Write(p []byte) (int, error) {
  28. return len(p), nil
  29. }
  30. func HttpsStart() {
  31. mux := http.NewServeMux()
  32. fe, err := fs.Sub(local, "dist")
  33. if err != nil {
  34. panic(err)
  35. }
  36. mux.Handle("/", http.FileServer(http.FS(fe)))
  37. // 挑战请求类似这样 /.well-known/acme-challenge/QPyMAyaWw9s5JvV1oruyqWHG7OqkHMJEHPoUz2046KM
  38. mux.HandleFunc("/.well-known/", controllers.AcmeChallenge)
  39. mux.HandleFunc("/api/ping", contextIterceptor(controllers.Ping))
  40. mux.HandleFunc("/api/login", contextIterceptor(controllers.Login))
  41. mux.HandleFunc("/api/group", contextIterceptor(controllers.GetUserGroup))
  42. mux.HandleFunc("/api/group/list", contextIterceptor(controllers.GetUserGroupList))
  43. mux.HandleFunc("/api/group/add", contextIterceptor(controllers.AddGroup))
  44. mux.HandleFunc("/api/group/del", contextIterceptor(controllers.DelGroup))
  45. mux.HandleFunc("/api/email/list", contextIterceptor(email.EmailList))
  46. mux.HandleFunc("/api/email/read", contextIterceptor(email.MarkRead))
  47. mux.HandleFunc("/api/email/del", contextIterceptor(email.EmailDelete))
  48. mux.HandleFunc("/api/email/detail", contextIterceptor(email.EmailDetail))
  49. mux.HandleFunc("/api/email/send", contextIterceptor(email.Send))
  50. mux.HandleFunc("/api/email/move", contextIterceptor(email.Move))
  51. mux.HandleFunc("/api/settings/modify_password", contextIterceptor(controllers.ModifyPassword))
  52. mux.HandleFunc("/api/rule/get", contextIterceptor(controllers.GetRule))
  53. mux.HandleFunc("/api/rule/add", contextIterceptor(controllers.UpsertRule))
  54. mux.HandleFunc("/api/rule/update", contextIterceptor(controllers.UpsertRule))
  55. mux.HandleFunc("/api/rule/del", contextIterceptor(controllers.DelRule))
  56. mux.HandleFunc("/attachments/", contextIterceptor(controllers.GetAttachments))
  57. mux.HandleFunc("/attachments/download/", contextIterceptor(controllers.Download))
  58. // go http server会打一堆没用的日志,写一个空的日志处理器,屏蔽掉日志输出
  59. nullLog := olog.New(&nullWrite{}, "", olog.Ldate)
  60. HttpsPort := 443
  61. if config.Instance.HttpsPort > 0 {
  62. HttpsPort = config.Instance.HttpsPort
  63. }
  64. if config.Instance.HttpsEnabled != 2 {
  65. log.Infof("Https Server Start On Port :%d", HttpsPort)
  66. httpsServer = &http.Server{
  67. Addr: fmt.Sprintf(":%d", HttpsPort),
  68. Handler: session.Instance.LoadAndSave(mux),
  69. ReadTimeout: time.Second * 90,
  70. WriteTimeout: time.Second * 90,
  71. ErrorLog: nullLog,
  72. }
  73. err = httpsServer.ListenAndServeTLS("config/ssl/public.crt", "config/ssl/private.key")
  74. if err != nil {
  75. panic(err)
  76. }
  77. }
  78. }
  79. func HttpsStop() {
  80. if httpsServer != nil {
  81. httpsServer.Close()
  82. }
  83. }
  84. // 注入context
  85. func contextIterceptor(h controllers.HandlerFunc) http.HandlerFunc {
  86. return func(w http.ResponseWriter, r *http.Request) {
  87. if w.Header().Get("Content-Type") == "" {
  88. w.Header().Set("Content-Type", "application/json")
  89. }
  90. ctx := &context.Context{}
  91. ctx.Context = r.Context()
  92. ctx.SetValue(context.LogID, id.GenLogID())
  93. lang := r.Header.Get("Lang")
  94. if lang == "" {
  95. lang = "en"
  96. }
  97. ctx.Lang = lang
  98. if config.IsInit {
  99. user := cast.ToString(session.Instance.Get(ctx, "user"))
  100. var userInfo *models.User
  101. if user != "" {
  102. _ = json.Unmarshal([]byte(user), &userInfo)
  103. }
  104. if userInfo != nil && userInfo.ID > 0 {
  105. ctx.UserID = userInfo.ID
  106. ctx.UserName = userInfo.Name
  107. ctx.UserAccount = userInfo.Account
  108. }
  109. if ctx.UserID == 0 {
  110. if r.URL.Path != "/api/ping" && r.URL.Path != "/api/login" {
  111. response.NewErrorResponse(response.NeedLogin, i18n.GetText(ctx.Lang, "login_exp"), "").FPrint(w)
  112. return
  113. }
  114. }
  115. } else if r.URL.Path != "/api/setup" {
  116. response.NewErrorResponse(response.NeedSetup, "", "").FPrint(w)
  117. return
  118. }
  119. h(ctx, w, r)
  120. }
  121. }