micro/api/server/http/http.go

111 lines
2.1 KiB
Go
Raw Normal View History

2019-06-03 20:44:43 +03:00
// Package http provides a http server with features; acme, cors, etc
package http
import (
"crypto/tls"
"net"
"net/http"
"sync"
"github.com/unistack-org/micro/v3/api/server"
"github.com/unistack-org/micro/v3/logger"
2019-06-03 20:44:43 +03:00
)
type httpServer struct {
mux *http.ServeMux
opts server.Options
sync.RWMutex
2019-06-03 20:44:43 +03:00
address string
exit chan chan error
}
2020-04-02 19:44:48 +03:00
func NewServer(address string, opts ...server.Option) server.Server {
2019-06-03 20:44:43 +03:00
return &httpServer{
opts: server.NewOptions(opts...),
2019-06-03 20:44:43 +03:00
mux: http.NewServeMux(),
address: address,
exit: make(chan chan error),
}
}
func (s *httpServer) Address() string {
s.RLock()
defer s.RUnlock()
2019-06-03 20:44:43 +03:00
return s.address
}
func (s *httpServer) Init(opts ...server.Option) error {
for _, o := range opts {
o(&s.opts)
}
return nil
}
func (s *httpServer) Handle(path string, handler http.Handler) {
2020-04-19 02:41:03 +03:00
// TODO: move this stuff out to one place with ServeHTTP
2020-04-07 21:29:26 +03:00
// apply the wrappers, e.g. auth
for _, wrapper := range s.opts.Wrappers {
2020-04-19 02:41:03 +03:00
handler = wrapper(handler)
2020-04-07 21:29:26 +03:00
}
2020-03-04 14:40:53 +03:00
2020-04-19 02:41:03 +03:00
s.mux.Handle(path, handler)
2019-06-03 20:44:43 +03:00
}
func (s *httpServer) Start() error {
var l net.Listener
var err error
s.RLock()
config := s.opts
s.RUnlock()
2019-10-11 18:52:57 +03:00
if s.opts.EnableACME && s.opts.ACMEProvider != nil {
2019-06-03 20:44:43 +03:00
// should we check the address to make sure its using :443?
l, err = s.opts.ACMEProvider.Listen(s.opts.ACMEHosts...)
2019-06-03 20:44:43 +03:00
} else if s.opts.EnableTLS && s.opts.TLSConfig != nil {
l, err = tls.Listen("tcp", s.address, s.opts.TLSConfig)
} else {
// otherwise plain listen
l, err = net.Listen("tcp", s.address)
}
if err != nil {
return err
}
if config.Logger.V(logger.InfoLevel) {
config.Logger.Infof("HTTP API Listening on %s", l.Addr().String())
}
2019-06-03 20:44:43 +03:00
s.Lock()
2019-06-03 20:44:43 +03:00
s.address = l.Addr().String()
s.Unlock()
2019-06-03 20:44:43 +03:00
go func() {
if err := http.Serve(l, s.mux); err != nil {
// temporary fix
if config.Logger.V(logger.ErrorLevel) {
config.Logger.Errorf("serve err: %v", err)
}
s.Stop()
2019-06-03 20:44:43 +03:00
}
}()
go func() {
ch := <-s.exit
ch <- l.Close()
}()
return nil
}
func (s *httpServer) Stop() error {
ch := make(chan error)
s.exit <- ch
return <-ch
}
func (s *httpServer) String() string {
return "http"
}