dynamiclistener/server/server.go

109 lines
2.3 KiB
Go
Raw Normal View History

package server
import (
"context"
2019-12-04 18:32:00 +00:00
"crypto"
"crypto/x509"
"fmt"
"net/http"
"github.com/rancher/dynamiclistener"
"github.com/rancher/dynamiclistener/factory"
"github.com/rancher/dynamiclistener/storage/memory"
"github.com/sirupsen/logrus"
)
2019-12-04 18:32:00 +00:00
type ListenOpts struct {
CA *x509.Certificate
CAKey crypto.Signer
Storage dynamiclistener.TLSStorage
}
func ListenAndServe(ctx context.Context, httpsPort, httpPort int, handler http.Handler, opts *ListenOpts) error {
var (
// https listener will change this if http is enabled
targetHandler = handler
)
2019-12-04 18:32:00 +00:00
if opts == nil {
opts = &ListenOpts{}
}
if httpsPort > 0 {
2019-12-04 18:32:00 +00:00
var (
caCert *x509.Certificate
caKey crypto.Signer
err error
)
if opts.CA != nil && opts.CAKey != nil {
caCert, caKey = opts.CA, opts.CAKey
} else {
caCert, caKey, err = factory.LoadOrGenCA()
if err != nil {
return err
}
}
tlsTCPListener, err := dynamiclistener.NewTCPListener("0.0.0.0", httpsPort)
if err != nil {
return err
}
2019-12-04 18:32:00 +00:00
storage := opts.Storage
if storage == nil {
storage = memory.New()
}
dynListener, dynHandler, err := dynamiclistener.NewListener(tlsTCPListener, storage, caCert, caKey, dynamiclistener.Config{})
if err != nil {
return err
}
targetHandler = wrapHandler(dynHandler, handler)
tlsServer := http.Server{
Handler: targetHandler,
}
targetHandler = dynamiclistener.HTTPRedirect(targetHandler)
go func() {
logrus.Infof("Listening on 0.0.0.0:%d", httpsPort)
err := tlsServer.Serve(dynListener)
if err != http.ErrServerClosed && err != nil {
logrus.Fatalf("https server failed: %v", err)
}
}()
go func() {
<-ctx.Done()
tlsServer.Shutdown(context.Background())
}()
}
if httpPort > 0 {
httpServer := http.Server{
Addr: fmt.Sprintf("0.0.0.0:%d", httpPort),
Handler: targetHandler,
}
go func() {
logrus.Infof("Listening on 0.0.0.0:%d", httpPort)
err := httpServer.ListenAndServe()
if err != http.ErrServerClosed && err != nil {
logrus.Fatalf("http server failed: %v", err)
}
}()
go func() {
<-ctx.Done()
httpServer.Shutdown(context.Background())
}()
}
return nil
}
func wrapHandler(handler http.Handler, next http.Handler) http.Handler {
return http.HandlerFunc(func(rw http.ResponseWriter, req *http.Request) {
handler.ServeHTTP(rw, req)
next.ServeHTTP(rw, req)
})
}