diff --git a/cmd/server_amd64.go b/cmd/server_amd64.go index 1ed371bcc..b79103a5f 100644 --- a/cmd/server_amd64.go +++ b/cmd/server_amd64.go @@ -60,6 +60,7 @@ const downloadCcxtUpdateIntervalLogMillis = 1000 type serverInputOptions struct { port *uint16 + ports *uint16 dev *bool devAPIPort *uint16 horizonTestnetURI *string @@ -81,9 +82,10 @@ func (o serverInputOptions) String() string { func init() { options := serverInputOptions{} - options.port = serverCmd.Flags().Uint16P("port", "p", 8000, "port on which to serve") + options.port = serverCmd.Flags().Uint16P("port", "p", 8000, "port on which to serve HTTP") + options.ports = serverCmd.Flags().Uint16P("ports", "P", 8001, "port on which to serve HTTPS (only applicable if tls cert and key provided)") options.dev = serverCmd.Flags().Bool("dev", false, "run in dev mode for hot-reloading of JS code") - options.devAPIPort = serverCmd.Flags().Uint16("dev-api-port", 8001, "port on which to run API server when in dev mode") + options.devAPIPort = serverCmd.Flags().Uint16("dev-api-port", 8002, "port on which to run API server when in dev mode") options.horizonTestnetURI = serverCmd.Flags().String("horizon-testnet-uri", "https://horizon-testnet.stellar.org", "URI to use for the horizon instance connected to the Stellar Test Network (must contain the word 'test')") options.horizonPubnetURI = serverCmd.Flags().String("horizon-pubnet-uri", "https://horizon.stellar.org", "URI to use for the horizon instance connected to the Stellar Public Network (must not contain the word 'test')") options.noHeaders = serverCmd.Flags().Bool("no-headers", false, "do not use Amplitude or set X-App-Name and X-App-Version headers on requests to horizon") @@ -409,10 +411,15 @@ func init() { // gui.FS is automatically compiled based on whether this is a local or deployment build gui.FileServer(r, "/", gui.FS) - log.Printf("starting server on port %d\n", *options.port) + isTLS := *options.tlsCertFile != "" && *options.tlsKeyFile != "" threadTracker := multithreading.MakeThreadTracker() e = threadTracker.TriggerGoroutine(func(inputs []interface{}) { - e1 := networking.StartServer(r, *options.port, *options.tlsCertFile, *options.tlsKeyFile) + port := *options.port + if isTLS { + port = *options.ports + } + log.Printf("starting server on port %d (TLS enabled = %v)\n", port, isTLS) + e1 := networking.StartServer(r, port, *options.tlsCertFile, *options.tlsKeyFile) if e1 != nil { log.Fatal(e1) } @@ -420,6 +427,16 @@ func init() { if e != nil { log.Fatal(e) } + if isTLS { + // we want a new server to redirect traffic from http to https + httpRedirectMux := chi.NewRouter() + networking.AddHTTPSUpgrade(httpRedirectMux, "/") + log.Printf("starting server on port %d to upgrade HTTP requests on the root path '/' to HTTPS connections\n", *options.port) + e1 := networking.StartServer(httpRedirectMux, *options.port, "", "") + if e1 != nil { + log.Fatal(e1) + } + } log.Printf("sleeping for %d seconds before showing the ready string indicator...\n", sleepNumSecondsBeforeReadyString) time.Sleep(sleepNumSecondsBeforeReadyString * time.Second) diff --git a/support/networking/server.go b/support/networking/server.go index d0ac91da2..7a52a1cdd 100644 --- a/support/networking/server.go +++ b/support/networking/server.go @@ -10,6 +10,7 @@ import ( "strconv" "time" + "github.com/go-chi/chi" "github.com/lechengfan/googleauth" ) @@ -112,3 +113,11 @@ func (s *server) googleAuthHandler(h http.Handler) http.Handler { Handler: h, } } + +// AddHTTPSUpgrade adds an entry on the passed in path to redirect to an https connection +func AddHTTPSUpgrade(mux *chi.Mux, path string) { + mux.HandleFunc(path, http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + log.Printf("received request on http port, redirecting to https connection using a temporary redirect (http status code 307)") + http.Redirect(w, r, fmt.Sprintf("https://%s%s", r.Host, path), http.StatusTemporaryRedirect) + })) +}