2019-10-27 06:18:58 +00:00
|
|
|
package server
|
|
|
|
|
|
|
|
import (
|
|
|
|
"context"
|
2019-12-04 18:32:00 +00:00
|
|
|
"crypto"
|
|
|
|
"crypto/x509"
|
2019-10-27 06:18:58 +00:00
|
|
|
"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 {
|
2019-10-27 06:18:58 +00:00
|
|
|
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{}
|
|
|
|
}
|
|
|
|
|
2019-10-27 06:18:58 +00:00
|
|
|
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
|
|
|
|
}
|
2019-10-27 06:18:58 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
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{})
|
2019-10-27 06:18:58 +00:00
|
|
|
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)
|
|
|
|
})
|
|
|
|
}
|