kserv_http.go 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147
  1. // package kserv_http -- встроенный HTTP-сервер
  2. package kserv_http
  3. import (
  4. "embed"
  5. "fmt"
  6. "net/http"
  7. "os"
  8. "strings"
  9. "sync"
  10. "time"
  11. "github.com/gofiber/fiber/v2"
  12. "github.com/gofiber/fiber/v2/middleware/compress"
  13. "github.com/gofiber/fiber/v2/middleware/filesystem"
  14. "github.com/gofiber/fiber/v2/middleware/monitor"
  15. . "gitp78su.ipnodns.ru/svi/kern/kc/helpers"
  16. "gitp78su.ipnodns.ru/svi/kern/kc/local_ctx"
  17. "gitp78su.ipnodns.ru/svi/kern/kc/safe_bool"
  18. "gitp78su.ipnodns.ru/svi/kern/krn/kctx"
  19. . "gitp78su.ipnodns.ru/svi/kern/krn/ktypes"
  20. )
  21. const (
  22. streamName = "kernel_server_http" // Контрольная строка для ожидателя потока
  23. )
  24. // kServHttp -- встроенный HTTP-сервер
  25. type kServHttp struct {
  26. kCtx IKernelCtx
  27. ctx ILocalCtx
  28. log ILogBuf
  29. strUrl string // URL, на котором слушает HTTP-сервер
  30. fiberApp *fiber.App
  31. isWork ISafeBool
  32. isEnd ISafeBool
  33. }
  34. //go:embed static/*
  35. var embedDirStatic embed.FS
  36. var (
  37. kernServHttp *kServHttp
  38. block sync.Mutex
  39. )
  40. // GetKernelServHttp -- возвращает встроенный HTTP-сервер
  41. func GetKernelServHttp() IKernelServerHttp {
  42. block.Lock()
  43. defer block.Unlock()
  44. if kernServHttp != nil {
  45. kernServHttp.log.Debug("GetKernelServHttp()")
  46. return kernServHttp
  47. }
  48. ctx := kctx.GetKernelCtx()
  49. strUrl := os.Getenv("LOCAL_HTTP_URL")
  50. Hassert(strUrl != "", "GetKernelServHttp(): env LOCAL_HTTP_URL not set")
  51. confFiber := fiber.Config{
  52. ServerHeader: ctx.Get("monolitName").Val().(string),
  53. UnescapePath: true,
  54. ReadTimeout: time.Second * 15,
  55. WriteTimeout: time.Second * 15,
  56. AppName: ctx.Get("monolitName").Val().(string),
  57. Network: "tcp4",
  58. EnablePrintRoutes: true,
  59. }
  60. sf := &kServHttp{
  61. kCtx: ctx,
  62. ctx: local_ctx.NewLocalCtx(ctx.BaseCtx()),
  63. strUrl: strUrl,
  64. fiberApp: fiber.New(confFiber),
  65. isWork: safe_bool.NewSafeBool(),
  66. isEnd: safe_bool.NewSafeBool(),
  67. }
  68. sf.log = sf.ctx.Log()
  69. sf.log.Debug("GetKernelServHttp(): first run")
  70. sf.fiberApp.Use(compress.New(compress.Config{
  71. Level: compress.LevelBestCompression, // 2
  72. }))
  73. sf.fiberApp.Use("/static", filesystem.New(filesystem.Config{
  74. Root: http.FS(embedDirStatic),
  75. PathPrefix: "static",
  76. Browse: true,
  77. MaxAge: 3600 * 24,
  78. }))
  79. sf.fiberApp.Get("/monitor", monitor.New(monitor.Config{Title: ctx.Get("monolitName").Val().(string)}))
  80. err := sf.kCtx.Wg().Add(streamName)
  81. Hassert(err == nil, "NewKernelServHttp(): in add stream %v, err=\n\t%v", streamName, err)
  82. ctx.Set("fiberApp", sf.fiberApp, "kServHttp: internal fiber app")
  83. kernServHttp = sf
  84. ctx.Set("kServHttp", kernServHttp, "kServHttp")
  85. return kernServHttp
  86. }
  87. // IsWork -- возвращает признак работы
  88. func (sf *kServHttp) IsWork() bool {
  89. return sf.isWork.Get()
  90. }
  91. // Log -- возвращает локальный лог
  92. func (sf *kServHttp) Log() ILogBuf {
  93. return sf.log
  94. }
  95. // Fiber -- возвращает объект веб-приложения fiber
  96. func (sf *kServHttp) Fiber() *fiber.App {
  97. return sf.fiberApp
  98. }
  99. // Run -- запускает сервер в работу (блокирующий вызов)
  100. func (sf *kServHttp) Run() {
  101. if sf.isEnd.Get() {
  102. return
  103. }
  104. if sf.isWork.Get() {
  105. return
  106. }
  107. go sf.close()
  108. sf.isWork.Set()
  109. sf.log.Debug("kServHttp.Run(): url='%v'", sf.strUrl)
  110. lstPort := strings.Split(sf.strUrl, ":")
  111. strPort := lstPort[len(lstPort)-1]
  112. strPort = strings.ReplaceAll(strPort, "/", "")
  113. strPort = strings.ReplaceAll(strPort, `"`, "")
  114. err := sf.fiberApp.Listen(":" + strPort)
  115. strOut := fmt.Sprintf("kServHttp.Run(): in listen, err=\n\t%v", err)
  116. sf.log.Err(strOut)
  117. sf.kCtx.Cancel()
  118. sf.isWork.Reset()
  119. sf.isEnd.Set()
  120. }
  121. // Ожидает окончания работы
  122. func (sf *kServHttp) close() {
  123. sf.kCtx.Done()
  124. if !sf.isWork.Get() {
  125. return
  126. }
  127. sf.isWork.Reset()
  128. sf.isEnd.Set()
  129. err := sf.fiberApp.Server().Shutdown()
  130. Assert(err == nil, "kServHttp.close(): in close server, err=\n\t%v", err)
  131. sf.kCtx.Wg().Done(streamName)
  132. sf.log.Debug("kServHttp.close(): end")
  133. }