github.com/machinefi/w3bstream@v1.6.5-rc9.0.20240426031326-b8c7c4876e72/pkg/depends/conf/http/server.go (about) 1 package http 2 3 import ( 4 "context" 5 "net/http" 6 "strconv" 7 8 "go.opentelemetry.io/otel" 9 10 "github.com/machinefi/w3bstream/pkg/depends/conf/http/mws" 11 "github.com/machinefi/w3bstream/pkg/depends/conf/logger" 12 "github.com/machinefi/w3bstream/pkg/depends/kit/httptransport" 13 "github.com/machinefi/w3bstream/pkg/depends/kit/kit" 14 "github.com/machinefi/w3bstream/pkg/depends/x/contextx" 15 "github.com/machinefi/w3bstream/pkg/depends/x/ptrx" 16 ) 17 18 var middlewares []httptransport.HttpMiddleware 19 20 // WithMiddlewares for custom 21 func WithMiddlewares(ms ...httptransport.HttpMiddleware) { 22 middlewares = append(middlewares, ms...) 23 } 24 25 type Server struct { 26 // Protocol support `http`, `https`, `unix`(http server based on unix domain socket), default `http` 27 Protocol string `env:""` 28 // Addr listen addr, default `0.0.0.0`. if based on a unix socket, set Addr as unix socket file abs path 29 Addr string `env:""` 30 // Port listen port 31 Port int `env:",opt,expose"` 32 // Spec document rel path 33 Spec string `env:",opt,copy"` 34 // HealthCheck path 35 HealthCheck string `env:",opt,healthCheck"` 36 // Debug if enable debug mode 37 Debug *bool `env:""` 38 39 ht *httptransport.HttpTransport 40 injector contextx.WithContext 41 name string 42 } 43 44 func (s Server) WithContextInjector(injector contextx.WithContext) *Server { 45 s.injector = injector 46 return &s 47 } 48 49 func (s Server) WithName(name string) *Server { 50 s.name = name 51 return &s 52 } 53 54 func (s *Server) LivenessCheck() map[string]string { 55 statuses := map[string]string{} 56 57 if s.ht != nil { 58 statuses[s.ht.ServiceMeta.String()] = "ok" 59 } 60 61 return statuses 62 } 63 64 func (s *Server) SetDefault() { 65 if s.Protocol == "" { 66 s.Protocol = "http" 67 } 68 if s.Addr == "" { 69 s.Addr = "0.0.0.0" 70 } 71 if s.Port == 0 { 72 switch s.Protocol { 73 case "http": 74 s.Port = 80 75 case "https": 76 s.Port = 443 77 } 78 } 79 if s.Spec == "" { 80 s.Spec = "./openapi.json" 81 } 82 if s.Debug == nil { 83 s.Debug = ptrx.Ptr(true) 84 } 85 if s.HealthCheck == "" { 86 s.HealthCheck = "http://:" + strconv.FormatInt(int64(s.Port), 10) + "/" 87 } 88 if s.ht == nil { 89 modifiers := make([]httptransport.ServerModifier, 0) 90 if s.Protocol == "http+unix" { 91 modifiers = append(modifiers, func(srv *http.Server) error { 92 srv.Addr = ":unix@" + s.Addr 93 return nil 94 }) 95 } 96 97 s.ht = httptransport.NewHttpTransport(modifiers...) 98 s.ht.SetDefault() 99 } 100 } 101 102 func (s *Server) Serve(router *kit.Router) error { 103 if s.ht == nil { 104 s.ht = httptransport.NewHttpTransport() 105 s.ht.SetDefault() 106 } 107 108 tr := otel.Tracer(s.name) 109 ht := s.ht 110 ht.Port = s.Port 111 112 ht.Middlewares = []httptransport.HttpMiddleware{} 113 ht.Middlewares = append(ht.Middlewares, middlewares...) 114 ht.Middlewares = append(ht.Middlewares, 115 mws.DefaultCORS(), 116 mws.HealthCheckHandler(), 117 mws.MetricsHandler(), 118 TraceLogHandler(tr), 119 NewContextInjectorMw(s.injector), 120 ) 121 if s.Debug != nil && *s.Debug { 122 ht.Middlewares = append(ht.Middlewares, mws.PProfHandler(*s.Debug)) 123 } 124 125 ctx, _ := logger.NewSpanContext(context.Background(), s.name) 126 127 return s.ht.ServeContext(ctx, router) 128 } 129 130 func (s *Server) Shutdown() { 131 _ = s.ht.Shutdown(context.Background()) 132 }