You can not select more than 25 topics Topics must start with a chinese character,a letter or number, can include dashes ('-') and can be up to 35 characters long.

server.go 3.2 kB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141
  1. package http
  2. import (
  3. "bytes"
  4. "context"
  5. "crypto/tls"
  6. "net/http"
  7. "github.com/gin-gonic/gin"
  8. "gitlink.org.cn/cloudream/common/pkgs/async"
  9. "gitlink.org.cn/cloudream/common/pkgs/logger"
  10. "gitlink.org.cn/cloudream/jcs-pub/client/internal/cluster"
  11. "gitlink.org.cn/cloudream/jcs-pub/client/internal/http/auth"
  12. "gitlink.org.cn/cloudream/jcs-pub/client/internal/http/proxy"
  13. "gitlink.org.cn/cloudream/jcs-pub/client/internal/http/types"
  14. v1 "gitlink.org.cn/cloudream/jcs-pub/client/internal/http/v1"
  15. "gitlink.org.cn/cloudream/jcs-pub/client/internal/services"
  16. clirpc "gitlink.org.cn/cloudream/jcs-pub/common/pkgs/rpc/client"
  17. "golang.org/x/net/http2"
  18. )
  19. type ServerEventChan = async.UnboundChannel[ServerEvent]
  20. type ServerEvent interface {
  21. IsServerEvent() bool
  22. }
  23. type ExitEvent struct {
  24. ServerEvent
  25. Err error
  26. }
  27. type Server struct {
  28. cfg types.Config
  29. httpSrv *http.Server
  30. svc *services.Service
  31. clster *cluster.Cluster
  32. eventChan *ServerEventChan
  33. auth *auth.Auth
  34. proxy *proxy.ClusterProxy
  35. v1Svr *v1.Server
  36. }
  37. func NewServer(cfg types.Config, svc *services.Service, clster *cluster.Cluster) *Server {
  38. return &Server{
  39. cfg: cfg,
  40. svc: svc,
  41. clster: clster,
  42. eventChan: async.NewUnboundChannel[ServerEvent](),
  43. v1Svr: v1.NewServer(&cfg, svc),
  44. }
  45. }
  46. func (s *Server) Start() *ServerEventChan {
  47. go func() {
  48. if !s.cfg.Enabled {
  49. return
  50. }
  51. engine := gin.New()
  52. s.httpSrv = &http.Server{
  53. Addr: s.cfg.Listen,
  54. Handler: engine,
  55. }
  56. s.auth = auth.New(&s.cfg)
  57. s.proxy = proxy.NewClusterProxy(s.clster)
  58. s.httpSrv.TLSConfig = &tls.Config{
  59. GetConfigForClient: s.auth.TLSConfigSelector,
  60. }
  61. http2.ConfigureServer(s.httpSrv, &http2.Server{})
  62. s.v1Svr.InitRouters(engine.Group("/v1"), s.auth, s.proxy)
  63. logger.Infof("start serving http at: %s", s.cfg.Listen)
  64. err := s.httpSrv.ListenAndServeTLS("", "")
  65. s.eventChan.Send(ExitEvent{Err: err})
  66. }()
  67. return s.eventChan
  68. }
  69. func (s *Server) Stop() {
  70. if s.httpSrv == nil {
  71. s.eventChan.Send(ExitEvent{})
  72. return
  73. }
  74. s.httpSrv.Shutdown(context.Background())
  75. }
  76. func (s *Server) ServeHTTP(ctx context.Context, req *clirpc.HTTPProxyRequest) (*clirpc.HTTPProxyResponse, error) {
  77. ctx2 := context.WithValue(ctx, auth.ClusterProxyRequest, true)
  78. r, err := http.NewRequestWithContext(ctx2, req.Method, req.URI, bytes.NewReader(req.Body))
  79. if err != nil {
  80. return nil, err
  81. }
  82. for _, v := range req.Header {
  83. r.Header.Add(v.Key, v.Value)
  84. }
  85. resp := proxyRespWriter{
  86. header: make(http.Header),
  87. }
  88. s.httpSrv.Handler.ServeHTTP(&resp, r)
  89. var header []*clirpc.HeaderKV
  90. for k, v := range resp.header {
  91. for _, vv := range v {
  92. header = append(header, &clirpc.HeaderKV{
  93. Key: k,
  94. Value: vv,
  95. })
  96. }
  97. }
  98. return &clirpc.HTTPProxyResponse{
  99. StatusCode: int32(resp.statusCode),
  100. Header: header,
  101. Body: resp.body.Bytes(),
  102. }, nil
  103. }
  104. type proxyRespWriter struct {
  105. statusCode int
  106. header http.Header
  107. body bytes.Buffer
  108. }
  109. func (w *proxyRespWriter) Header() http.Header {
  110. return w.header
  111. }
  112. func (w *proxyRespWriter) Write(b []byte) (int, error) {
  113. return w.body.Write(b)
  114. }
  115. func (w *proxyRespWriter) WriteHeader(statusCode int) {
  116. w.statusCode = statusCode
  117. }

本项目旨在将云际存储公共基础设施化,使个人及企业可低门槛使用高效的云际存储服务(安装开箱即用云际存储客户端即可,无需关注其他组件的部署),同时支持用户灵活便捷定制云际存储的功能细节。