package goxy import ( "crypto/tls" "net/http" "net/http/httputil" ) type Server struct { DataFile string Route wwwServer http.Server tlsServer http.Server rpcServer http.Server } func NewServer(dataFile, listenWWW, listenTLS, listenRPC string) (*Server, error) { r := make(Route) server := &Server{ DataFile: dataFile, Route: r, wwwServer: http.Server{ Addr: listenWWW, }, tlsServer: http.Server{ Addr: listenTLS, TLSConfig: &tls.Config{ GetCertificate: r.GetCertificate, }, }, rpcServer: http.Server{ Addr: listenRPC, }, } if dataFile != "" { server.Load(dataFile) } RegisterRPC(server) http.Handle("/debug/route", server.Route) return server, server.Update() } // Update routes from in-memory state func (s *Server) Update() error { wwwMux := http.NewServeMux() tlsMux := http.NewServeMux() for _, v := range s.Route { host := v.ServerName.Host + v.ServerName.Path up := v.Upstream switch v.ServerName.Scheme { case "http", "": wwwMux.Handle(host, httputil.NewSingleHostReverseProxy(up)) case "https": wwwMux.Handle(host, http.RedirectHandler("https://"+host, http.StatusMovedPermanently)) tlsMux.Handle(host, httputil.NewSingleHostReverseProxy(up)) case "ws": wwwMux.Handle(host, NewWebSocketProxy(up)) case "wss": wwwMux.Handle(host, http.RedirectHandler("wss://"+host, http.StatusMovedPermanently)) tlsMux.Handle(host, NewWebSocketProxy(up)) } } s.wwwServer.Handler = wwwMux s.tlsServer.Handler = tlsMux return nil } func (s *Server) Start() error { errc := make(chan error) go func() { errc <- s.wwwServer.ListenAndServe() }() go func() { errc <- s.tlsServer.ListenAndServeTLS("", "") }() go func() { errc <- s.rpcServer.ListenAndServe() }() return <-errc }