package main import ( "context" "crypto/tls" "errors" "io/ioutil" "net/http" "net/url" ) import ( "github.com/fatih/color" log "github.com/sirupsen/logrus" "github.com/vulcand/oxy/forward" "github.com/vulcand/oxy/roundrobin" "golang.org/x/crypto/acme/autocert" ) // Initialize the autocert manager and configure it, // also create an instance of the http.Server and link the autocert manager to it. func InitServer() error { m := autocert.Manager{ Cache: autocert.DirCache(*STORAGE), Prompt: autocert.AcceptTOS, HostPolicy: func(ctx context.Context, host string) error { if _, ok := HOSTS[host]; ok { return nil } return errors.New("Unkown host(" + host + ")") }, } errchan := make(chan error) s := &http.Server{ Addr: *HTTPS_ADDR, TLSConfig: &tls.Config{GetCertificate: m.GetCertificate}, Handler: ServeHTTP(), } log.SetOutput(ioutil.Discard) go (func() { handler := m.HTTPHandler(ServeHTTP()) if *AUTOREDIRECT { handler = m.HTTPHandler(nil) } errchan <- http.ListenAndServe(*HTTP_ADDR, handler) })() go (func() { errchan <- s.ListenAndServeTLS("", "") })() return <-errchan } // The main server handler func ServeHTTP() http.Handler { return http.HandlerFunc(func(res http.ResponseWriter, req *http.Request) { if upstreams, ok := HOSTS[req.Host]; ok { forwarder, _ := forward.New(forward.PassHostHeader(true)) loadbalancer, _ := roundrobin.New(forwarder) for _, upstream := range upstreams { if url, err := url.Parse(upstream); err == nil { loadbalancer.UpsertServer(url) } else { colorize(color.FgRed, "⇛", err.Error()) } } if *EXPOSE_INFO { res.Header().Set("X-HTTPSIFY-Version", VERSION) } if *HSTS != "" { res.Header().Set("Strict-Transport-Security", *HSTS) } loadbalancer.ServeHTTP(res, req) return } http.Error(res, "The request service couldn't be found here", http.StatusNotImplemented) }) }