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  }