backend.go 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144
  1. package backend
  2. import (
  3. "context"
  4. "fmt"
  5. "io/ioutil"
  6. "net/http"
  7. "sync"
  8. "time"
  9. "github.com/ChineseSubFinder/ChineseSubFinder/pkg"
  10. "github.com/ChineseSubFinder/ChineseSubFinder/pkg/local_http_proxy_server"
  11. "github.com/ChineseSubFinder/ChineseSubFinder/pkg/settings"
  12. "github.com/ChineseSubFinder/ChineseSubFinder/frontend/dist"
  13. "github.com/gin-contrib/cors"
  14. "github.com/gin-gonic/gin"
  15. "github.com/sirupsen/logrus"
  16. "github.com/ChineseSubFinder/ChineseSubFinder/pkg/logic/cron_helper"
  17. )
  18. type BackEnd struct {
  19. logger *logrus.Logger
  20. cronHelper *cron_helper.CronHelper
  21. httpPort int
  22. running bool
  23. srv *http.Server
  24. locker sync.Mutex
  25. restartSignal chan interface{}
  26. }
  27. func NewBackEnd(logger *logrus.Logger, cronHelper *cron_helper.CronHelper, httpPort int, restartSignal chan interface{}) *BackEnd {
  28. return &BackEnd{logger: logger, cronHelper: cronHelper, httpPort: httpPort, restartSignal: restartSignal}
  29. }
  30. func (b *BackEnd) start() {
  31. defer b.locker.Unlock()
  32. b.locker.Lock()
  33. if b.running == true {
  34. b.logger.Debugln("Http Server is already running")
  35. return
  36. }
  37. b.running = true
  38. // ----------------------------------------
  39. // 设置代理
  40. err := local_http_proxy_server.SetProxyInfo(settings.Get().AdvancedSettings.ProxySettings.GetInfos())
  41. if err != nil {
  42. b.logger.Errorln("Set Local Http Proxy Server Error:", err)
  43. return
  44. }
  45. // -----------------------------------------
  46. gin.SetMode(gin.ReleaseMode)
  47. gin.DefaultWriter = ioutil.Discard
  48. engine := gin.Default()
  49. // 默认所有都通过
  50. engine.Use(cors.Default())
  51. cbBase, v1Router := InitRouter(engine, b.cronHelper, b.restartSignal)
  52. engine.GET("/", func(c *gin.Context) {
  53. c.Header("content-type", "text/html;charset=utf-8")
  54. c.String(http.StatusOK, string(dist.SpaIndexHtml))
  55. })
  56. engine.StaticFS(dist.SpaFolderJS, dist.Assets(dist.SpaFolderName+dist.SpaFolderJS, dist.SpaJS))
  57. engine.StaticFS(dist.SpaFolderCSS, dist.Assets(dist.SpaFolderName+dist.SpaFolderCSS, dist.SpaCSS))
  58. engine.StaticFS(dist.SpaFolderFonts, dist.Assets(dist.SpaFolderName+dist.SpaFolderFonts, dist.SpaFonts))
  59. engine.StaticFS(dist.SpaFolderIcons, dist.Assets(dist.SpaFolderName+dist.SpaFolderIcons, dist.SpaIcons))
  60. engine.StaticFS(dist.SpaFolderImages, dist.Assets(dist.SpaFolderName+dist.SpaFolderImages, dist.SpaImages))
  61. // 用于预览视频和字幕的静态文件服务
  62. previewCacheFolder, err := pkg.GetVideoAndSubPreviewCacheFolder()
  63. if err != nil {
  64. b.logger.Errorln("GetVideoAndSubPreviewCacheFolder Error:", err)
  65. return
  66. }
  67. engine.StaticFS("/static/preview", http.Dir(previewCacheFolder))
  68. engine.Any("/api", func(c *gin.Context) {
  69. c.Redirect(http.StatusMovedPermanently, "/")
  70. })
  71. // listen and serve on 0.0.0.0:8080(default)
  72. b.srv = &http.Server{
  73. Addr: fmt.Sprintf(":%d", b.httpPort),
  74. Handler: engine,
  75. }
  76. go func() {
  77. b.logger.Infoln("Try Start Http Server At Port", b.httpPort)
  78. if err := b.srv.ListenAndServe(); err != nil && err != http.ErrServerClosed {
  79. b.logger.Errorln("Start Server Error:", err)
  80. }
  81. defer func() {
  82. cbBase.Close()
  83. v1Router.Close()
  84. }()
  85. }()
  86. }
  87. func (b *BackEnd) Restart() {
  88. stopFunc := func() {
  89. b.locker.Lock()
  90. defer func() {
  91. b.locker.Unlock()
  92. }()
  93. if b.running == false {
  94. b.logger.Debugln("Http Server is not running")
  95. return
  96. }
  97. b.running = false
  98. exitOk := make(chan interface{}, 1)
  99. defer close(exitOk)
  100. ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
  101. defer cancel()
  102. go func() {
  103. if err := b.srv.Shutdown(ctx); err != nil {
  104. b.logger.Errorln("Http Server Shutdown:", err)
  105. }
  106. exitOk <- true
  107. }()
  108. select {
  109. case <-ctx.Done():
  110. b.logger.Warningln("Http Server Shutdown timeout of 5 seconds.")
  111. case <-exitOk:
  112. b.logger.Infoln("Http Server Shutdown Successfully")
  113. }
  114. b.logger.Infoln("Http Server Shutdown Done.")
  115. }
  116. for {
  117. select {
  118. case <-b.restartSignal:
  119. {
  120. stopFunc()
  121. b.start()
  122. }
  123. }
  124. }
  125. }