github.com/btccom/go-micro/v2@v2.9.3/api/server/http/http.go (about) 1 // Package http provides a http server with features; acme, cors, etc 2 package http 3 4 import ( 5 "crypto/tls" 6 "net" 7 "net/http" 8 "os" 9 "sync" 10 11 "github.com/gorilla/handlers" 12 "github.com/btccom/go-micro/v2/api/server" 13 "github.com/btccom/go-micro/v2/api/server/cors" 14 "github.com/btccom/go-micro/v2/logger" 15 ) 16 17 type httpServer struct { 18 mux *http.ServeMux 19 opts server.Options 20 21 mtx sync.RWMutex 22 address string 23 exit chan chan error 24 } 25 26 func NewServer(address string, opts ...server.Option) server.Server { 27 var options server.Options 28 for _, o := range opts { 29 o(&options) 30 } 31 32 return &httpServer{ 33 opts: options, 34 mux: http.NewServeMux(), 35 address: address, 36 exit: make(chan chan error), 37 } 38 } 39 40 func (s *httpServer) Address() string { 41 s.mtx.RLock() 42 defer s.mtx.RUnlock() 43 return s.address 44 } 45 46 func (s *httpServer) Init(opts ...server.Option) error { 47 for _, o := range opts { 48 o(&s.opts) 49 } 50 return nil 51 } 52 53 func (s *httpServer) Handle(path string, handler http.Handler) { 54 // TODO: move this stuff out to one place with ServeHTTP 55 56 // apply the wrappers, e.g. auth 57 for _, wrapper := range s.opts.Wrappers { 58 handler = wrapper(handler) 59 } 60 61 // wrap with cors 62 if s.opts.EnableCORS { 63 handler = cors.CombinedCORSHandler(handler) 64 } 65 66 // wrap with logger 67 handler = handlers.CombinedLoggingHandler(os.Stdout, handler) 68 69 s.mux.Handle(path, handler) 70 } 71 72 func (s *httpServer) Start() error { 73 var l net.Listener 74 var err error 75 76 if s.opts.EnableACME && s.opts.ACMEProvider != nil { 77 // should we check the address to make sure its using :443? 78 l, err = s.opts.ACMEProvider.Listen(s.opts.ACMEHosts...) 79 } else if s.opts.EnableTLS && s.opts.TLSConfig != nil { 80 l, err = tls.Listen("tcp", s.address, s.opts.TLSConfig) 81 } else { 82 // otherwise plain listen 83 l, err = net.Listen("tcp", s.address) 84 } 85 if err != nil { 86 return err 87 } 88 89 if logger.V(logger.InfoLevel, logger.DefaultLogger) { 90 logger.Infof("HTTP API Listening on %s", l.Addr().String()) 91 } 92 93 s.mtx.Lock() 94 s.address = l.Addr().String() 95 s.mtx.Unlock() 96 97 go func() { 98 if err := http.Serve(l, s.mux); err != nil { 99 // temporary fix 100 //logger.Fatal(err) 101 } 102 }() 103 104 go func() { 105 ch := <-s.exit 106 ch <- l.Close() 107 }() 108 109 return nil 110 } 111 112 func (s *httpServer) Stop() error { 113 ch := make(chan error) 114 s.exit <- ch 115 return <-ch 116 } 117 118 func (s *httpServer) String() string { 119 return "http" 120 }