为什么不能从同一个golang程序中同时运行HTTP和HTTPS?
这是启动两个服务器的代码。.首先启动的服务器将运行-第二个服务器将不运行。
运行程序时没有错误返回,但是请求http://www.localhost或https://secure.localhost超时
http://www.localhost
https://secure.localhost
// Start HTTP err_http := http.ListenAndServe(fmt.Sprintf(":%d", port), http_r) if err_http != nil { log.Fatal("Web server (HTTP): ", err_http) } // Start HTTPS err_https := http.ListenAndServeTLS(fmt.Sprintf(":%d", ssl_port), "D:/Go/src/www/ssl/public.crt", "D:/Go/src/www/ssl/private.key", https_r) if err_https != nil { log.Fatal("Web server (HTTPS): ", err_https) }
这是完整的代码
package main import ( "net/http" "fmt" "log" "os" "io" "runtime" // go get github.com/gorilla/mux "github.com/gorilla/mux" ) const ( HOST = "localhost" ) func Handler_404(w http.ResponseWriter, r *http.Request){ fmt.Fprint(w, "Oops, something went wrong!") } func Handler_www(w http.ResponseWriter, r *http.Request){ fmt.Fprint(w, "Hello world :)") } func Handler_api(w http.ResponseWriter, r *http.Request){ fmt.Fprint(w, "This is the API") } func Handler_secure(w http.ResponseWriter, r *http.Request){ fmt.Fprint(w, "This is Secure") } func redirect(r *mux.Router, from string, to string){ r.Host(from).Subrouter().HandleFunc("/", func (w http.ResponseWriter, r *http.Request){ http.Redirect(w, r, to, 301) }) } func main(){ port := 9000 ssl_port := 443 runtime.GOMAXPROCS(runtime.NumCPU()) http_r := mux.NewRouter() https_r := mux.NewRouter() // HTTP 404 http_r.NotFoundHandler = http.HandlerFunc(Handler_404) // Redirect "http://HOST" => "http://www.HOST" redirect(http_r, HOST, fmt.Sprintf("http://www.%s:%d", HOST, port)) // Redirect "http://secure.HOST" => "https://secure.HOST" redirect(http_r, "secure."+HOST, fmt.Sprintf("https://secure.%s", HOST)) www := http_r.Host("www."+HOST).Subrouter() www.HandleFunc("/", Handler_www) api := http_r.Host("api."+HOST).Subrouter() api.HandleFunc("/", Handler_api) secure := https_r.Host("secure."+HOST).Subrouter() secure.HandleFunc("/", Handler_secure) // Start HTTP err_http := http.ListenAndServe(fmt.Sprintf(":%d", port), http_r) if err_http != nil { log.Fatal("Web server (HTTP): ", err_http) } // Start HTTPS err_https := http.ListenAndServeTLS(fmt.Sprintf(":%d", ssl_port), "D:/Go/src/www/ssl/public.crt", "D:/Go/src/www/ssl/private.key", https_r) if err_https != nil { log.Fatal("Web server (HTTPS): ", err_https) } }
ListenAndServe和ListenAndServeTLS打开侦听套接字,然后循环永远服务于客户端连接。这些函数仅在错误时返回。
主goroutine永远不会进入启动TLS服务器,因为主goroutine正忙于在ListenAndServe中等待HTTP连接。
要解决此问题,请在新的goroutine中启动HTTP服务器:
// Start HTTP go func() { err_http := http.ListenAndServe(fmt.Sprintf(":%d", port), http_r) if err_http != nil { log.Fatal("Web server (HTTP): ", err_http) } }() // Start HTTPS err_https := http.ListenAndServeTLS(fmt.Sprintf(":%d", ssl_port), "D:/Go/src/www/ssl/public.crt", "D:/Go/src/www/ssl/private.key", https_r) if err_https != nil { log.Fatal("Web server (HTTPS): ", err_https) }