main.go 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171
  1. package http_server
  2. import (
  3. "bytes"
  4. "embed"
  5. "encoding/hex"
  6. "encoding/json"
  7. "fmt"
  8. log "github.com/sirupsen/logrus"
  9. "github.com/spf13/cast"
  10. "io/fs"
  11. "math/rand"
  12. "net"
  13. "net/http"
  14. "os"
  15. "pmail/config"
  16. "pmail/controllers"
  17. "pmail/controllers/email"
  18. "pmail/dto"
  19. "pmail/dto/response"
  20. "pmail/i18n"
  21. "pmail/session"
  22. "time"
  23. )
  24. //go:embed dist/*
  25. var local embed.FS
  26. var ip string
  27. const HttpPort = 80
  28. var setupServer *http.Server
  29. func SetupStart() {
  30. mux := http.NewServeMux()
  31. fe, err := fs.Sub(local, "dist")
  32. if err != nil {
  33. panic(err)
  34. }
  35. mux.Handle("/", http.FileServer(http.FS(fe)))
  36. mux.HandleFunc("/api/", contextIterceptor(controllers.Setup))
  37. mux.HandleFunc("/", controllers.Proxy)
  38. setupServer := &http.Server{
  39. Addr: fmt.Sprintf(":%d", HttpPort),
  40. Handler: mux,
  41. ReadTimeout: time.Second * 60,
  42. WriteTimeout: time.Second * 60,
  43. }
  44. err = setupServer.ListenAndServe()
  45. if err != nil {
  46. panic(err)
  47. }
  48. }
  49. func SetupStop() {
  50. err := setupServer.Close()
  51. if err != nil {
  52. panic(err)
  53. }
  54. }
  55. func Start() {
  56. log.Infof("Http Server Start at :%d", HttpPort)
  57. mux := http.NewServeMux()
  58. fe, err := fs.Sub(local, "dist")
  59. if err != nil {
  60. panic(err)
  61. }
  62. mux.Handle("/", http.FileServer(http.FS(fe)))
  63. mux.HandleFunc("/api/ping", contextIterceptor(controllers.Ping))
  64. mux.HandleFunc("/api/login", contextIterceptor(controllers.Login))
  65. mux.HandleFunc("/api/group", contextIterceptor(controllers.GetUserGroup))
  66. mux.HandleFunc("/api/email/list", contextIterceptor(email.EmailList))
  67. mux.HandleFunc("/api/email/detail", contextIterceptor(email.EmailDetail))
  68. mux.HandleFunc("/api/email/send", contextIterceptor(email.Send))
  69. mux.HandleFunc("/api/settings/modify_password", contextIterceptor(controllers.ModifyPassword))
  70. mux.HandleFunc("/attachments/", contextIterceptor(controllers.GetAttachments))
  71. mux.HandleFunc("/attachments/download/", contextIterceptor(controllers.Download))
  72. server := &http.Server{
  73. Addr: fmt.Sprintf(":%d", HttpPort),
  74. Handler: session.Instance.LoadAndSave(mux),
  75. ReadTimeout: time.Second * 60,
  76. WriteTimeout: time.Second * 60,
  77. }
  78. //err := server.ListenAndServeTLS( "config/ssl/public.crt", "config/ssl/private.key", nil)
  79. err = server.ListenAndServe()
  80. if err != nil {
  81. panic(err)
  82. }
  83. }
  84. func getLocalIP() string {
  85. ip := "127.0.0.1"
  86. addrs, err := net.InterfaceAddrs()
  87. if err != nil {
  88. return ip
  89. }
  90. for _, a := range addrs {
  91. if ipnet, ok := a.(*net.IPNet); ok && !ipnet.IP.IsLoopback() {
  92. if ipnet.IP.To4() != nil {
  93. ip = ipnet.IP.String()
  94. break
  95. }
  96. }
  97. }
  98. return ip
  99. }
  100. func genLogID() string {
  101. r := rand.New(rand.NewSource(time.Now().UnixMicro()))
  102. if ip == "" {
  103. ip = getLocalIP()
  104. }
  105. now := time.Now()
  106. timestamp := uint32(now.Unix())
  107. timeNano := now.UnixNano()
  108. pid := os.Getpid()
  109. b := bytes.Buffer{}
  110. b.WriteString(hex.EncodeToString(net.ParseIP(ip).To4()))
  111. b.WriteString(fmt.Sprintf("%x", timestamp&0xffffffff))
  112. b.WriteString(fmt.Sprintf("%04x", timeNano&0xffff))
  113. b.WriteString(fmt.Sprintf("%04x", pid&0xffff))
  114. b.WriteString(fmt.Sprintf("%06x", r.Int31n(1<<24)))
  115. b.WriteString("b0")
  116. return b.String()
  117. }
  118. // 注入context
  119. func contextIterceptor(h controllers.HandlerFunc) http.HandlerFunc {
  120. return func(w http.ResponseWriter, r *http.Request) {
  121. if w.Header().Get("Content-Type") == "" {
  122. w.Header().Set("Content-Type", "application/json")
  123. }
  124. ctx := &dto.Context{}
  125. ctx.Context = r.Context()
  126. ctx.SetValue(dto.LogID, genLogID())
  127. lang := r.Header.Get("Lang")
  128. if lang == "" {
  129. lang = "en"
  130. }
  131. ctx.Lang = lang
  132. if config.IsInit {
  133. user := cast.ToString(session.Instance.Get(ctx, "user"))
  134. if user != "" {
  135. _ = json.Unmarshal([]byte(user), &ctx.UserInfo)
  136. }
  137. if ctx.UserInfo == nil || ctx.UserInfo.ID == 0 {
  138. if r.URL.Path != "/api/ping" && r.URL.Path != "/api/login" {
  139. response.NewErrorResponse(response.ParamsError, i18n.GetText(ctx.Lang, "login_exp"), "").FPrint(w)
  140. return
  141. }
  142. }
  143. } else if r.URL.Path != "/api/setup" {
  144. response.NewErrorResponse(response.NeedSetup, "", "").FPrint(w)
  145. return
  146. }
  147. h(ctx, w, r)
  148. }
  149. }