package api import ( "context" "crypto/tls" "net/http" "os" "os/signal" "strconv" "sync" "syscall" "time" "github.com/gorilla/mux" "github.com/sirupsen/logrus" ) type Api struct { httpServer *http.Server mux *mux.Router online bool running chan os.Signal ssl bool cert string key string certMu sync.Mutex tlscert *tls.Certificate } type ApiConfig struct { Address string Port int SSL bool Cert string Key string } func NewApi(config ApiConfig) *Api { logrus.Info(config) srv := &http.Server{ Addr: config.Address + ":" + strconv.Itoa(config.Port), ReadTimeout: 5 * time.Second, WriteTimeout: 10 * time.Second, IdleTimeout: 120 * time.Second, } logrus.Warn(srv.Addr) apiWebServer := &Api{ httpServer: srv, mux: mux.NewRouter(), online: false, } if config.SSL { apiWebServer.ssl = true apiWebServer.cert = config.Cert apiWebServer.key = config.Key apiWebServer.tlscert = nil } return apiWebServer } func (api *Api) AddHandler(path string, handler func(http.ResponseWriter, *http.Request), method string) { api.mux.HandleFunc(path, handler).Methods(method) } func (api *Api) Start(wg *sync.WaitGroup) error { defer wg.Done() api.httpServer.Handler = api.mux api.httpServer.TLSConfig = &tls.Config{ GetCertificate: api.getCertificate, } go func() { if api.ssl { err := api.httpServer.ListenAndServeTLS(api.cert, api.key) if err != nil { logrus.Fatal(err) } } else { api.httpServer.ListenAndServe() } }() go logrus.Info("API webserver has started") api.online = true api.running = make(chan os.Signal, 1) signal.Notify(api.running, syscall.SIGINT, syscall.SIGTERM, os.Interrupt) <-api.running ctx, _ := context.WithTimeout(context.Background(), 5*time.Second) if err := api.httpServer.Shutdown(ctx); err != nil { go logrus.Error(err) } else { go logrus.Info("API webserver shutdown") } api.online = false return nil } func (api *Api) Stop() { if api.online { go logrus.Info("Shutting down API webserver") api.running <- syscall.SIGINT } } func (api *Api) getCertificate(clientHello *tls.ClientHelloInfo) (*tls.Certificate, error) { api.certMu.Lock() defer api.certMu.Unlock() cert, err := tls.LoadX509KeyPair(api.cert, api.key) if err != nil { go logrus.Error(err) return nil, err } return &cert, nil }