2019-12-01 22:44:49 +03:00
|
|
|
package main
|
|
|
|
|
|
|
|
import (
|
|
|
|
"context"
|
|
|
|
"log"
|
|
|
|
"net/http"
|
2019-12-02 01:34:59 +03:00
|
|
|
"os"
|
2019-12-01 22:44:49 +03:00
|
|
|
"time"
|
|
|
|
|
|
|
|
"github.com/neonxp/rutina"
|
|
|
|
"golang.org/x/crypto/acme/autocert"
|
|
|
|
)
|
|
|
|
|
2019-12-01 23:37:00 +03:00
|
|
|
var httpSrv *http.Server
|
|
|
|
var httpsSrv *http.Server
|
2019-12-01 22:44:49 +03:00
|
|
|
|
|
|
|
func main() {
|
2019-12-02 01:34:59 +03:00
|
|
|
certDir := os.Getenv("CERTDIR")
|
|
|
|
if certDir == "" {
|
|
|
|
certDir = "/usr/app/certs"
|
|
|
|
}
|
2019-12-01 22:44:49 +03:00
|
|
|
r := rutina.New(rutina.WithListenOsSignals())
|
|
|
|
w, err := newWatcher()
|
|
|
|
if err != nil {
|
|
|
|
panic(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
// Docker
|
|
|
|
r.Go(w.watch)
|
|
|
|
|
|
|
|
// HTTPS
|
|
|
|
r.Go(func(ctx context.Context) error {
|
2019-12-02 01:34:59 +03:00
|
|
|
httpsSrv = &http.Server{Addr: ":https", Handler: getTlsHandler(w)}
|
2019-12-01 22:44:49 +03:00
|
|
|
hosts := []string{}
|
|
|
|
w.Range(func(key, value interface{}) bool {
|
|
|
|
h := value.(host)
|
|
|
|
if !h.TLS {
|
|
|
|
return true
|
|
|
|
}
|
|
|
|
hosts = append(hosts, h.Host)
|
|
|
|
return true
|
|
|
|
})
|
|
|
|
m := &autocert.Manager{
|
2019-12-02 01:34:59 +03:00
|
|
|
Cache: autocert.DirCache(certDir),
|
2019-12-01 22:44:49 +03:00
|
|
|
Prompt: autocert.AcceptTOS,
|
|
|
|
HostPolicy: autocert.HostWhitelist(hosts...),
|
|
|
|
}
|
2019-12-01 23:37:00 +03:00
|
|
|
log.Println("https hosts:", hosts)
|
2019-12-01 22:44:49 +03:00
|
|
|
httpsSrv.TLSConfig = m.TLSConfig()
|
|
|
|
if err := httpsSrv.ListenAndServeTLS("", ""); err != http.ErrServerClosed {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
return nil
|
|
|
|
}, rutina.RestartIfDone)
|
|
|
|
r.Go(func(ctx context.Context) error {
|
|
|
|
select {
|
|
|
|
case <-ctx.Done():
|
|
|
|
case <-w.update():
|
2019-12-01 23:37:00 +03:00
|
|
|
log.Println("reload https config")
|
|
|
|
}
|
|
|
|
if httpsSrv == nil {
|
|
|
|
return nil
|
2019-12-01 22:44:49 +03:00
|
|
|
}
|
2019-12-01 23:37:00 +03:00
|
|
|
tctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
|
2019-12-01 22:44:49 +03:00
|
|
|
defer cancel()
|
|
|
|
return httpsSrv.Shutdown(tctx)
|
|
|
|
}, rutina.RestartIfDone)
|
|
|
|
|
|
|
|
// HTTP
|
|
|
|
r.Go(func(ctx context.Context) error {
|
2019-12-02 01:34:59 +03:00
|
|
|
httpSrv = &http.Server{Addr: ":http", Handler: getHandler(w)}
|
2019-12-01 22:44:49 +03:00
|
|
|
if err := httpSrv.ListenAndServe(); err != http.ErrServerClosed {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
return nil
|
|
|
|
})
|
|
|
|
r.Go(func(ctx context.Context) error {
|
|
|
|
<-ctx.Done()
|
|
|
|
log.Println("Graceful shutdown")
|
2019-12-01 23:37:00 +03:00
|
|
|
if httpsSrv == nil {
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
tctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
|
2019-12-01 22:44:49 +03:00
|
|
|
defer cancel()
|
|
|
|
return httpSrv.Shutdown(tctx)
|
|
|
|
})
|
|
|
|
|
|
|
|
if err := r.Wait(); err != nil {
|
|
|
|
log.Fatal(err)
|
|
|
|
}
|
|
|
|
log.Println("Success stop")
|
|
|
|
}
|