kbus_http.go 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238
  1. // package kbus_http -- шина сообщений поверх HTTP.
  2. package kbus_http
  3. import (
  4. "net/http"
  5. "sync"
  6. "github.com/gofiber/fiber/v3"
  7. "gitp78su.ipnodns.ru/svi/kern/v4/lev0"
  8. mL1 "gitp78su.ipnodns.ru/svi/kern/v4/lev1"
  9. "gitp78su.ipnodns.ru/svi/kern/v4/lev1/comp_spec"
  10. "gitp78su.ipnodns.ru/svi/kern/v4/lev1/safe_bool"
  11. "gitp78su.ipnodns.ru/svi/kern/v4/lev2/kctx"
  12. "gitp78su.ipnodns.ru/svi/kern/v4/lev2/kserv_http"
  13. "gitp78su.ipnodns.ru/svi/kern/v4/lev2/lti/bus_ent"
  14. "gitp78su.ipnodns.ru/svi/kern/v4/lev2/lti/bus_ent/topic"
  15. "gitp78su.ipnodns.ru/svi/kern/v4/lev2/lti/bus_mock/mock_hand_sub_http"
  16. "gitp78su.ipnodns.ru/svi/kern/v4/lev2/lti/bus_spec"
  17. "gitp78su.ipnodns.ru/svi/kern/v4/lev2/lti/dot"
  18. "gitp78su.ipnodns.ru/svi/kern/v4/lev2/lti/kbus_base"
  19. )
  20. // kBusHttp -- шина данных поверх HTTP.
  21. type kBusHttp struct {
  22. *kbus_base.KBusBase
  23. log comp_spec.ILogBuf
  24. }
  25. var (
  26. Bus_ *kBusHttp
  27. block sync.Mutex
  28. )
  29. // GetKernelBusHttp -- возвращает шину HTTP.
  30. func GetKernelBusHttp() bus_spec.IKernelBus {
  31. block.Lock()
  32. defer block.Unlock()
  33. if Bus_ != nil {
  34. return Bus_
  35. }
  36. paramLogBuf := &mL1.LogBufParam{
  37. IsTerm_: safe_bool.NewSafeBool(true),
  38. Prefix_: lev0.LetTxt("kBusHttp"),
  39. }
  40. log := mL1.NewLogBuf(paramLogBuf)
  41. log.Debug("GetKernelBusHttp(): new")
  42. kCtx := kctx.GetKernelCtx()
  43. kBus := kbus_base.GetKernelBusBase()
  44. sf := &kBusHttp{
  45. KBusBase: kBus,
  46. log: log,
  47. }
  48. kServHttp := kserv_http.GetKernelServHttp()
  49. fibApp := kServHttp.Fiber()
  50. fibApp.Post("/bus/sub", sf.postSub) // Топик подписки, IN
  51. fibApp.Post("/bus/unsub", sf.postUnsub) // Топик отписки, IN
  52. fibApp.Post("/bus/request", sf.postSendRequest) // Топик входящих запросов, IN
  53. fibApp.Post("/bus/pub", sf.postPublish) // Топик публикаций подписки, IN
  54. kCtx.Set("kernBus", sf, "GetKernelBusHttp(): http data bus")
  55. Bus_ = sf
  56. return Bus_
  57. }
  58. // Входящий запрос HTTP на подписку.
  59. func (sf *kBusHttp) postSub(ctx fiber.Ctx) error {
  60. sf.log.Debug("postSub()")
  61. ctx.Set("Content-type", "text/html; charset=utf8")
  62. ctx.Set("Content-type", "text/json")
  63. ctx.Set("Cache-Control", "no-cache")
  64. sf.log.Debug("postSub()")
  65. req := &dot.SubscribeReq{}
  66. err := ctx.Bind().Body(req)
  67. if err != nil {
  68. resp := &dot.SubscribeResp{
  69. Status_: lev0.LetTxt("kernelBusHttp.postSub(): in parse request, err=\n\t%v\n", err),
  70. Uuid_: req.Uuid_,
  71. }
  72. resp.SelfCheck()
  73. ctx.Response().SetStatusCode(http.StatusBadRequest)
  74. err := lev0.LetErr("kBusHttp.postSub(): in body parser, status=%q", resp.Status_)
  75. sf.log.Err(err)
  76. return ctx.JSON(resp)
  77. }
  78. resp := sf.processSubscribe(req)
  79. resp.SelfCheck()
  80. return ctx.JSON(resp)
  81. }
  82. // Процесс подписки веб-хука.
  83. func (sf *kBusHttp) processSubscribe(req *dot.SubscribeReq) *dot.SubscribeResp {
  84. req.SelfCheck()
  85. topic := bus_ent.ITopicFix(topic.NewTopic(req.Topic_))
  86. handler := mock_hand_sub_http.NewMockHandSubHttp(topic, req.WebHook_)
  87. resp := &dot.SubscribeResp{
  88. Status_: lev0.LetTxt("ok"),
  89. Uuid_: req.Uuid_,
  90. Name_: handler.Name().Get(),
  91. }
  92. res := sf.Subscribe(handler)
  93. if res.IsErr() {
  94. resp.Status_ = lev0.LetTxt(
  95. "kernelBusHttp.processSubscribe(): err=\n\t%v",
  96. res.Err())
  97. return resp
  98. }
  99. return resp
  100. }
  101. // Входящая публикация.
  102. func (sf *kBusHttp) postPublish(ctx fiber.Ctx) error {
  103. sf.log.Debug("postPublish()")
  104. sf.postCommon(ctx)
  105. req := &dot.PublishReq{}
  106. err := ctx.Bind().Body(req)
  107. if err != nil {
  108. resp := &dot.PublishResp{
  109. Status_: lev0.LetTxt("kernelBusHttp.postPublish(): in parse request, err=\n\t%v\n", err),
  110. Uuid_: req.Uuid_,
  111. }
  112. resp.SelfCheck()
  113. ctx.Response().SetStatusCode(http.StatusBadRequest)
  114. err := lev0.LetErr("postPublish(): in body parser, status=%v", resp.Status_)
  115. sf.log.Err(err)
  116. return ctx.JSON(resp)
  117. }
  118. resp := sf.processPublish(req)
  119. resp.SelfCheck()
  120. return ctx.JSON(resp)
  121. }
  122. // Входящая отписка от топика по HTTP.
  123. func (sf *kBusHttp) postUnsub(ctx fiber.Ctx) error {
  124. sf.log.Debug("postUnsub()")
  125. sf.postCommon(ctx)
  126. req := &dot.UnsubReq{}
  127. err := ctx.Bind().Body(req)
  128. if err != nil {
  129. resp := &dot.ServeResp{
  130. Status_: lev0.LetTxt("kernelBusHttp.postSendRequest(): err=\n\t%v", err),
  131. Uuid_: req.Uuid_,
  132. }
  133. resp.SelfCheck()
  134. ctx.Response().SetStatusCode(http.StatusBadRequest)
  135. err := lev0.LetErr("kBusHttp.postUnsub(): in body parser, status=%q", resp.Status_)
  136. sf.log.Err(err)
  137. return ctx.JSON(resp)
  138. }
  139. resp := sf.processUnsubRequest(req)
  140. resp.SelfCheck()
  141. return ctx.JSON(resp)
  142. }
  143. // Общая часть процесса публикации и отписки.
  144. func (sf *kBusHttp) postCommon(ctx fiber.Ctx) {
  145. ctx.Set("Content-type", "text/html; charset=utf8")
  146. ctx.Set("Content-type", "text/json")
  147. ctx.Set("Cache-Control", "no-cache")
  148. }
  149. // Выполняет процесс публикации.
  150. func (sf *kBusHttp) processPublish(req *dot.PublishReq) *dot.PublishResp {
  151. req.SelfCheck()
  152. topic := bus_ent.ITopicFix(topic.NewTopic(req.Topic_))
  153. res := sf.Publish(topic, req.BinMsg_)
  154. resp := &dot.PublishResp{
  155. Status_: lev0.LetTxt("ok"),
  156. Uuid_: req.Uuid_,
  157. }
  158. if res.IsErr() {
  159. resp.Status_ = lev0.LetTxt("kernelBusHttp.processPublish(): err=\n\t%v", res.Err())
  160. return resp
  161. }
  162. return resp
  163. }
  164. // Входящий запрос.
  165. func (sf *kBusHttp) postSendRequest(ctx fiber.Ctx) error {
  166. sf.log.Debug("postSendRequest()")
  167. ctx.Set("Content-type", "text/html; charset=utf8")
  168. ctx.Set("Content-type", "text/json")
  169. ctx.Set("Cache-Control", "no-cache")
  170. req := &dot.ServeReq{}
  171. err := ctx.Bind().Body(req)
  172. if err != nil {
  173. resp := &dot.ServeResp{
  174. Status_: lev0.LetTxt("kernelBusHttp.postSendRequest(): err=\n\t%v", err),
  175. Uuid_: req.Uuid_,
  176. }
  177. resp.SelfCheck()
  178. ctx.Response().SetStatusCode(http.StatusBadRequest)
  179. err := lev0.LetErr("kBusHttp.postSendRequest(): in body parser, status=%v", resp.Status_)
  180. sf.log.Err(err)
  181. return ctx.JSON(resp)
  182. }
  183. resp := sf.processSendRequest(req)
  184. resp.SelfCheck()
  185. return ctx.JSON(resp)
  186. }
  187. // Обрабатывает входящий запрос.
  188. func (sf *kBusHttp) processSendRequest(req *dot.ServeReq) *dot.ServeResp {
  189. req.SelfCheck()
  190. topic := bus_ent.ITopicFix(topic.NewTopic(req.Topic_))
  191. res := sf.SendRequest(topic, req.BinReq_)
  192. resp := &dot.ServeResp{
  193. Status_: lev0.LetTxt("ok"),
  194. Uuid_: req.Uuid_,
  195. }
  196. if res.IsErr() {
  197. resp.Status_ = lev0.LetTxt("kernelBusHttp.processSendRequest(): err=\n\t%v", res.Err())
  198. return resp
  199. }
  200. resp.BinResp_ = res.Ok()
  201. return resp
  202. }
  203. // Процесс отписки от топика.
  204. func (sf *kBusHttp) processUnsubRequest(req *dot.UnsubReq) *dot.UnsubResp {
  205. req.SelfCheck()
  206. resp := &dot.UnsubResp{
  207. Status_: lev0.LetTxt("ok"),
  208. Uuid_: req.Uuid_,
  209. }
  210. optHandler := sf.KCtx_.Get(req.HandlerName_)
  211. if optHandler.IsNone() {
  212. resp.Status_ = lev0.LetTxt("kernelBusHttp.processUnsubRequest(): not get handler(%v) from kernel ctx",
  213. req.HandlerName_)
  214. return resp
  215. }
  216. if optHandler == nil {
  217. resp.Status_ = lev0.LetTxt("kernelBusHttp.processUnsubRequest(): handler(%v) not exists", req.HandlerName_)
  218. return resp
  219. }
  220. hand := optHandler.Some().Val().(bus_spec.IBusHandlerSubscribe)
  221. sf.Unsubscribe(hand)
  222. return resp
  223. }